Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
2cb2358c
Commit
2cb2358c
authored
Feb 17, 2015
by
Jisi Liu
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #204 from pherl/master
Implement maps for JavaNano
parents
db87a9c0
c265fbe3
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1162 additions
and
86 deletions
+1162
-86
pom.xml
javanano/pom.xml
+1
-0
CodedInputByteBufferNano.java
...va/com/google/protobuf/nano/CodedInputByteBufferNano.java
+40
-0
CodedOutputByteBufferNano.java
...a/com/google/protobuf/nano/CodedOutputByteBufferNano.java
+124
-0
Extension.java
...ano/src/main/java/com/google/protobuf/nano/Extension.java
+19
-54
InternalNano.java
.../src/main/java/com/google/protobuf/nano/InternalNano.java
+223
-0
MapFactories.java
.../src/main/java/com/google/protobuf/nano/MapFactories.java
+67
-0
NanoTest.java
...nano/src/test/java/com/google/protobuf/nano/NanoTest.java
+318
-22
map_test.proto
...ano/src/test/java/com/google/protobuf/nano/map_test.proto
+70
-0
Makefile.am
src/Makefile.am
+12
-10
javanano_field.cc
src/google/protobuf/compiler/javanano/javanano_field.cc
+5
-0
javanano_helpers.cc
src/google/protobuf/compiler/javanano/javanano_helpers.cc
+11
-0
javanano_helpers.h
src/google/protobuf/compiler/javanano/javanano_helpers.h
+8
-0
javanano_map_field.cc
src/google/protobuf/compiler/javanano/javanano_map_field.cc
+186
-0
javanano_map_field.h
src/google/protobuf/compiler/javanano/javanano_map_field.h
+70
-0
javanano_message.cc
src/google/protobuf/compiler/javanano/javanano_message.cc
+8
-0
No files found.
javanano/pom.xml
View file @
2cb2358c
...
...
@@ -94,6 +94,7 @@
<arg
value=
"src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto"
/>
<arg
value=
"src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto"
/>
<arg
value=
"src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto"
/>
<arg
value=
"src/test/java/com/google/protobuf/nano/map_test.proto"
/>
</exec>
<exec
executable=
"../src/protoc"
>
<arg
value=
"--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources"
/>
...
...
javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
View file @
2cb2358c
...
...
@@ -638,4 +638,44 @@ public final class CodedInputByteBufferNano {
throw
InvalidProtocolBufferNanoException
.
truncatedMessage
();
}
}
// Read a primitive type.
Object
readPrimitiveField
(
int
type
)
throws
IOException
{
switch
(
type
)
{
case
InternalNano
.
TYPE_DOUBLE
:
return
readDouble
();
case
InternalNano
.
TYPE_FLOAT
:
return
readFloat
();
case
InternalNano
.
TYPE_INT64
:
return
readInt64
();
case
InternalNano
.
TYPE_UINT64
:
return
readUInt64
();
case
InternalNano
.
TYPE_INT32
:
return
readInt32
();
case
InternalNano
.
TYPE_FIXED64
:
return
readFixed64
();
case
InternalNano
.
TYPE_FIXED32
:
return
readFixed32
();
case
InternalNano
.
TYPE_BOOL
:
return
readBool
();
case
InternalNano
.
TYPE_STRING
:
return
readString
();
case
InternalNano
.
TYPE_BYTES
:
return
readBytes
();
case
InternalNano
.
TYPE_UINT32
:
return
readUInt32
();
case
InternalNano
.
TYPE_ENUM
:
return
readEnum
();
case
InternalNano
.
TYPE_SFIXED32
:
return
readSFixed32
();
case
InternalNano
.
TYPE_SFIXED64
:
return
readSFixed64
();
case
InternalNano
.
TYPE_SINT32
:
return
readSInt32
();
case
InternalNano
.
TYPE_SINT64
:
return
readSInt64
();
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
}
}
}
javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
View file @
2cb2358c
...
...
@@ -876,4 +876,128 @@ public final class CodedOutputByteBufferNano {
// Note: the right-shift must be arithmetic
return
(
n
<<
1
)
^
(
n
>>
63
);
}
static
int
computeFieldSize
(
int
number
,
int
type
,
Object
object
)
{
switch
(
type
)
{
case
InternalNano
.
TYPE_BOOL
:
return
computeBoolSize
(
number
,
(
Boolean
)
object
);
case
InternalNano
.
TYPE_BYTES
:
return
computeBytesSize
(
number
,
(
byte
[])
object
);
case
InternalNano
.
TYPE_STRING
:
return
computeStringSize
(
number
,
(
String
)
object
);
case
InternalNano
.
TYPE_FLOAT
:
return
computeFloatSize
(
number
,
(
Float
)
object
);
case
InternalNano
.
TYPE_DOUBLE
:
return
computeDoubleSize
(
number
,
(
Double
)
object
);
case
InternalNano
.
TYPE_ENUM
:
return
computeEnumSize
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_FIXED32
:
return
computeFixed32Size
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_INT32
:
return
computeInt32Size
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_UINT32
:
return
computeUInt32Size
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_SINT32
:
return
computeSInt32Size
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_SFIXED32
:
return
computeSFixed32Size
(
number
,
(
Integer
)
object
);
case
InternalNano
.
TYPE_INT64
:
return
computeInt64Size
(
number
,
(
Long
)
object
);
case
InternalNano
.
TYPE_UINT64
:
return
computeUInt64Size
(
number
,
(
Long
)
object
);
case
InternalNano
.
TYPE_SINT64
:
return
computeSInt64Size
(
number
,
(
Long
)
object
);
case
InternalNano
.
TYPE_FIXED64
:
return
computeFixed64Size
(
number
,
(
Long
)
object
);
case
InternalNano
.
TYPE_SFIXED64
:
return
computeSFixed64Size
(
number
,
(
Long
)
object
);
case
InternalNano
.
TYPE_MESSAGE
:
return
computeMessageSize
(
number
,
(
MessageNano
)
object
);
case
InternalNano
.
TYPE_GROUP
:
return
computeGroupSize
(
number
,
(
MessageNano
)
object
);
default
:
throw
new
IllegalArgumentException
(
"Unknown type: "
+
type
);
}
}
void
writeField
(
int
number
,
int
type
,
Object
value
)
throws
IOException
{
switch
(
type
)
{
case
InternalNano
.
TYPE_DOUBLE
:
Double
doubleValue
=
(
Double
)
value
;
writeDouble
(
number
,
doubleValue
);
break
;
case
InternalNano
.
TYPE_FLOAT
:
Float
floatValue
=
(
Float
)
value
;
writeFloat
(
number
,
floatValue
);
break
;
case
InternalNano
.
TYPE_INT64
:
Long
int64Value
=
(
Long
)
value
;
writeInt64
(
number
,
int64Value
);
break
;
case
InternalNano
.
TYPE_UINT64
:
Long
uint64Value
=
(
Long
)
value
;
writeUInt64
(
number
,
uint64Value
);
break
;
case
InternalNano
.
TYPE_INT32
:
Integer
int32Value
=
(
Integer
)
value
;
writeInt32
(
number
,
int32Value
);
break
;
case
InternalNano
.
TYPE_FIXED64
:
Long
fixed64Value
=
(
Long
)
value
;
writeFixed64
(
number
,
fixed64Value
);
break
;
case
InternalNano
.
TYPE_FIXED32
:
Integer
fixed32Value
=
(
Integer
)
value
;
writeFixed32
(
number
,
fixed32Value
);
break
;
case
InternalNano
.
TYPE_BOOL
:
Boolean
boolValue
=
(
Boolean
)
value
;
writeBool
(
number
,
boolValue
);
break
;
case
InternalNano
.
TYPE_STRING
:
String
stringValue
=
(
String
)
value
;
writeString
(
number
,
stringValue
);
break
;
case
InternalNano
.
TYPE_BYTES
:
byte
[]
bytesValue
=
(
byte
[])
value
;
writeBytes
(
number
,
bytesValue
);
break
;
case
InternalNano
.
TYPE_UINT32
:
Integer
uint32Value
=
(
Integer
)
value
;
writeUInt32
(
number
,
uint32Value
);
break
;
case
InternalNano
.
TYPE_ENUM
:
Integer
enumValue
=
(
Integer
)
value
;
writeEnum
(
number
,
enumValue
);
break
;
case
InternalNano
.
TYPE_SFIXED32
:
Integer
sfixed32Value
=
(
Integer
)
value
;
writeSFixed32
(
number
,
sfixed32Value
);
break
;
case
InternalNano
.
TYPE_SFIXED64
:
Long
sfixed64Value
=
(
Long
)
value
;
writeSFixed64
(
number
,
sfixed64Value
);
break
;
case
InternalNano
.
TYPE_SINT32
:
Integer
sint32Value
=
(
Integer
)
value
;
writeSInt32
(
number
,
sint32Value
);
break
;
case
InternalNano
.
TYPE_SINT64
:
Long
sint64Value
=
(
Long
)
value
;
writeSInt64
(
number
,
sint64Value
);
break
;
case
InternalNano
.
TYPE_MESSAGE
:
MessageNano
messageValue
=
(
MessageNano
)
value
;
writeMessage
(
number
,
messageValue
);
break
;
case
InternalNano
.
TYPE_GROUP
:
MessageNano
groupValue
=
(
MessageNano
)
value
;
writeGroup
(
number
,
groupValue
);
break
;
default
:
throw
new
IOException
(
"Unknown type: "
+
type
);
}
}
}
javanano/src/main/java/com/google/protobuf/nano/Extension.java
View file @
2cb2358c
...
...
@@ -55,24 +55,24 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* PrimitiveExtension // for primitive/enum typed extensions
*/
public
static
final
int
TYPE_DOUBLE
=
1
;
public
static
final
int
TYPE_FLOAT
=
2
;
public
static
final
int
TYPE_INT64
=
3
;
public
static
final
int
TYPE_UINT64
=
4
;
public
static
final
int
TYPE_INT32
=
5
;
public
static
final
int
TYPE_FIXED64
=
6
;
public
static
final
int
TYPE_FIXED32
=
7
;
public
static
final
int
TYPE_BOOL
=
8
;
public
static
final
int
TYPE_STRING
=
9
;
public
static
final
int
TYPE_GROUP
=
10
;
public
static
final
int
TYPE_MESSAGE
=
11
;
public
static
final
int
TYPE_BYTES
=
12
;
public
static
final
int
TYPE_UINT32
=
13
;
public
static
final
int
TYPE_ENUM
=
14
;
public
static
final
int
TYPE_SFIXED32
=
15
;
public
static
final
int
TYPE_SFIXED64
=
16
;
public
static
final
int
TYPE_SINT32
=
17
;
public
static
final
int
TYPE_SINT64
=
18
;
public
static
final
int
TYPE_DOUBLE
=
InternalNano
.
TYPE_DOUBLE
;
public
static
final
int
TYPE_FLOAT
=
InternalNano
.
TYPE_FLOAT
;
public
static
final
int
TYPE_INT64
=
InternalNano
.
TYPE_INT64
;
public
static
final
int
TYPE_UINT64
=
InternalNano
.
TYPE_UINT6
4
;
public
static
final
int
TYPE_INT32
=
InternalNano
.
TYPE_INT32
;
public
static
final
int
TYPE_FIXED64
=
InternalNano
.
TYPE_FIXED64
;
public
static
final
int
TYPE_FIXED32
=
InternalNano
.
TYPE_FIXED32
;
public
static
final
int
TYPE_BOOL
=
InternalNano
.
TYPE_BOOL
;
public
static
final
int
TYPE_STRING
=
InternalNano
.
TYPE_STRING
;
public
static
final
int
TYPE_GROUP
=
InternalNano
.
TYPE_GROUP
;
public
static
final
int
TYPE_MESSAGE
=
InternalNano
.
TYPE_MESSAGE
;
public
static
final
int
TYPE_BYTES
=
InternalNano
.
TYPE_BYTES
;
public
static
final
int
TYPE_UINT32
=
InternalNano
.
TYPE_UINT32
;
public
static
final
int
TYPE_ENUM
=
InternalNano
.
TYPE_ENUM
;
public
static
final
int
TYPE_SFIXED32
=
InternalNano
.
TYPE_SFIXED32
;
public
static
final
int
TYPE_SFIXED64
=
InternalNano
.
TYPE_SFIXED64
;
public
static
final
int
TYPE_SINT32
=
InternalNano
.
TYPE_SINT32
;
public
static
final
int
TYPE_SINT64
=
InternalNano
.
TYPE_SINT64
;
/**
* Creates an {@code Extension} of the given message type and tag number.
...
...
@@ -338,42 +338,7 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
@Override
protected
Object
readData
(
CodedInputByteBufferNano
input
)
{
try
{
switch
(
type
)
{
case
TYPE_DOUBLE:
return
input
.
readDouble
();
case
TYPE_FLOAT:
return
input
.
readFloat
();
case
TYPE_INT64:
return
input
.
readInt64
();
case
TYPE_UINT64:
return
input
.
readUInt64
();
case
TYPE_INT32:
return
input
.
readInt32
();
case
TYPE_FIXED64:
return
input
.
readFixed64
();
case
TYPE_FIXED32:
return
input
.
readFixed32
();
case
TYPE_BOOL:
return
input
.
readBool
();
case
TYPE_STRING:
return
input
.
readString
();
case
TYPE_BYTES:
return
input
.
readBytes
();
case
TYPE_UINT32:
return
input
.
readUInt32
();
case
TYPE_ENUM:
return
input
.
readEnum
();
case
TYPE_SFIXED32:
return
input
.
readSFixed32
();
case
TYPE_SFIXED64:
return
input
.
readSFixed64
();
case
TYPE_SINT32:
return
input
.
readSInt32
();
case
TYPE_SINT64:
return
input
.
readSInt64
();
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
}
return
input
.
readPrimitiveField
(
type
);
}
catch
(
IOException
e
)
{
throw
new
IllegalArgumentException
(
"Error reading extension field"
,
e
);
}
...
...
javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
View file @
2cb2358c
...
...
@@ -30,8 +30,13 @@
package
com
.
google
.
protobuf
.
nano
;
import
com.google.protobuf.nano.MapFactories.MapFactory
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.util.Arrays
;
import
java.util.Map
;
import
java.util.Map.Entry
;
/**
* The classes contained within are used internally by the Protocol Buffer
...
...
@@ -43,6 +48,26 @@ import java.util.Arrays;
*/
public
final
class
InternalNano
{
public
static
final
int
TYPE_DOUBLE
=
1
;
public
static
final
int
TYPE_FLOAT
=
2
;
public
static
final
int
TYPE_INT64
=
3
;
public
static
final
int
TYPE_UINT64
=
4
;
public
static
final
int
TYPE_INT32
=
5
;
public
static
final
int
TYPE_FIXED64
=
6
;
public
static
final
int
TYPE_FIXED32
=
7
;
public
static
final
int
TYPE_BOOL
=
8
;
public
static
final
int
TYPE_STRING
=
9
;
public
static
final
int
TYPE_GROUP
=
10
;
public
static
final
int
TYPE_MESSAGE
=
11
;
public
static
final
int
TYPE_BYTES
=
12
;
public
static
final
int
TYPE_UINT32
=
13
;
public
static
final
int
TYPE_ENUM
=
14
;
public
static
final
int
TYPE_SFIXED32
=
15
;
public
static
final
int
TYPE_SFIXED64
=
16
;
public
static
final
int
TYPE_SINT32
=
17
;
public
static
final
int
TYPE_SINT64
=
18
;
private
InternalNano
()
{}
/**
...
...
@@ -329,5 +354,203 @@ public final class InternalNano {
}
return
result
;
}
private
static
final
byte
[]
EMPTY_BYTES
=
new
byte
[
0
];
private
static
Object
primitiveDefaultValue
(
int
type
)
{
switch
(
type
)
{
case
TYPE_BOOL:
return
Boolean
.
FALSE
;
case
TYPE_BYTES:
return
EMPTY_BYTES
;
case
TYPE_STRING:
return
""
;
case
TYPE_FLOAT:
return
Float
.
valueOf
(
0
);
case
TYPE_DOUBLE:
return
Double
.
valueOf
(
0
);
case
TYPE_ENUM:
case
TYPE_FIXED32:
case
TYPE_INT32:
case
TYPE_UINT32:
case
TYPE_SINT32:
case
TYPE_SFIXED32:
return
Integer
.
valueOf
(
0
);
case
TYPE_INT64:
case
TYPE_UINT64:
case
TYPE_SINT64:
case
TYPE_FIXED64:
case
TYPE_SFIXED64:
return
Long
.
valueOf
(
0L
);
case
TYPE_MESSAGE:
case
TYPE_GROUP:
default
:
throw
new
IllegalArgumentException
(
"Type: "
+
type
+
" is not a primitive type."
);
}
}
/**
* Merges the map entry into the map field. Note this is only supposed to
* be called by generated messages.
*
* @param map the map field; may be null, in which case a map will be
* instantiated using the {@link MapFactories.MapFactory}
* @param input the input byte buffer
* @param keyType key type, as defined in InternalNano.TYPE_*
* @param valueType value type, as defined in InternalNano.TYPE_*
* @param value an new instance of the value, if the value is a TYPE_MESSAGE;
* otherwise this parameter can be null and will be ignored.
* @param keyTag wire tag for the key
* @param valueTag wire tag for the value
* @return the map field
* @throws IOException
*/
@SuppressWarnings
(
"unchecked"
)
public
static
final
<
K
,
V
>
Map
<
K
,
V
>
mergeMapEntry
(
CodedInputByteBufferNano
input
,
Map
<
K
,
V
>
map
,
MapFactory
mapFactory
,
int
keyType
,
int
valueType
,
V
value
,
int
keyTag
,
int
valueTag
)
throws
IOException
{
map
=
mapFactory
.
forMap
(
map
);
final
int
length
=
input
.
readRawVarint32
();
final
int
oldLimit
=
input
.
pushLimit
(
length
);
K
key
=
null
;
while
(
true
)
{
int
tag
=
input
.
readTag
();
if
(
tag
==
0
)
{
break
;
}
if
(
tag
==
keyTag
)
{
key
=
(
K
)
input
.
readPrimitiveField
(
keyType
);
}
else
if
(
tag
==
valueTag
)
{
if
(
valueType
==
TYPE_MESSAGE
)
{
input
.
readMessage
((
MessageNano
)
value
);
}
else
{
value
=
(
V
)
input
.
readPrimitiveField
(
valueType
);
}
}
else
{
if
(!
input
.
skipField
(
tag
))
{
break
;
}
}
}
input
.
checkLastTagWas
(
0
);
input
.
popLimit
(
oldLimit
);
if
(
key
==
null
)
{
// key can only be primitive types.
key
=
(
K
)
primitiveDefaultValue
(
keyType
);
}
if
(
value
==
null
)
{
// message type value will be initialized by code-gen.
value
=
(
V
)
primitiveDefaultValue
(
valueType
);
}
map
.
put
(
key
,
value
);
return
map
;
}
public
static
<
K
,
V
>
void
serializeMapField
(
CodedOutputByteBufferNano
output
,
Map
<
K
,
V
>
map
,
int
number
,
int
keyType
,
int
valueType
)
throws
IOException
{
for
(
Entry
<
K
,
V
>
entry:
map
.
entrySet
())
{
K
key
=
entry
.
getKey
();
V
value
=
entry
.
getValue
();
if
(
key
==
null
||
value
==
null
)
{
throw
new
IllegalStateException
(
"keys and values in maps cannot be null"
);
}
int
entrySize
=
CodedOutputByteBufferNano
.
computeFieldSize
(
1
,
keyType
,
key
)
+
CodedOutputByteBufferNano
.
computeFieldSize
(
2
,
valueType
,
value
);
output
.
writeTag
(
number
,
WireFormatNano
.
WIRETYPE_LENGTH_DELIMITED
);
output
.
writeRawVarint32
(
entrySize
);
output
.
writeField
(
1
,
keyType
,
key
);
output
.
writeField
(
2
,
valueType
,
value
);
}
}
public
static
<
K
,
V
>
int
computeMapFieldSize
(
Map
<
K
,
V
>
map
,
int
number
,
int
keyType
,
int
valueType
)
{
int
size
=
0
;
int
tagSize
=
CodedOutputByteBufferNano
.
computeTagSize
(
number
);
for
(
Entry
<
K
,
V
>
entry:
map
.
entrySet
())
{
K
key
=
entry
.
getKey
();
V
value
=
entry
.
getValue
();
if
(
key
==
null
||
value
==
null
)
{
throw
new
IllegalStateException
(
"keys and values in maps cannot be null"
);
}
int
entrySize
=
CodedOutputByteBufferNano
.
computeFieldSize
(
1
,
keyType
,
key
)
+
CodedOutputByteBufferNano
.
computeFieldSize
(
2
,
valueType
,
value
);
size
+=
tagSize
+
entrySize
+
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
entrySize
);
}
return
size
;
}
/**
* Checks whether two {@link Map} are equal. We don't use the default equals
* method of {@link Map} because it compares by identity not by content for
* byte arrays.
*/
public
static
<
K
,
V
>
boolean
equals
(
Map
<
K
,
V
>
a
,
Map
<
K
,
V
>
b
)
{
if
(
a
==
b
)
{
return
true
;
}
if
(
a
==
null
)
{
return
b
.
size
()
==
0
;
}
if
(
b
==
null
)
{
return
a
.
size
()
==
0
;
}
if
(
a
.
size
()
!=
b
.
size
())
{
return
false
;
}
for
(
Entry
<
K
,
V
>
entry
:
a
.
entrySet
())
{
if
(!
b
.
containsKey
(
entry
.
getKey
()))
{
return
false
;
}
if
(!
equalsMapValue
(
entry
.
getValue
(),
b
.
get
(
entry
.
getKey
())))
{
return
false
;
}
}
return
true
;
}
private
static
boolean
equalsMapValue
(
Object
a
,
Object
b
)
{
if
(
a
==
null
||
b
==
null
)
{
throw
new
IllegalStateException
(
"keys and values in maps cannot be null"
);
}
if
(
a
instanceof
byte
[]
&&
b
instanceof
byte
[])
{
return
Arrays
.
equals
((
byte
[])
a
,
(
byte
[])
b
);
}
return
a
.
equals
(
b
);
}
public
static
<
K
,
V
>
int
hashCode
(
Map
<
K
,
V
>
map
)
{
if
(
map
==
null
)
{
return
0
;
}
int
result
=
0
;
for
(
Entry
<
K
,
V
>
entry
:
map
.
entrySet
())
{
result
+=
hashCodeForMap
(
entry
.
getKey
())
^
hashCodeForMap
(
entry
.
getValue
());
}
return
result
;
}
private
static
int
hashCodeForMap
(
Object
o
)
{
if
(
o
instanceof
byte
[])
{
return
Arrays
.
hashCode
((
byte
[])
o
);
}
return
o
.
hashCode
();
}
}
javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
0 → 100644
View file @
2cb2358c
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package
com
.
google
.
protobuf
.
nano
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Utility class for maps support.
*/
public
final
class
MapFactories
{
public
static
interface
MapFactory
{
<
K
,
V
>
Map
<
K
,
V
>
forMap
(
Map
<
K
,
V
>
oldMap
);
}
// NOTE(liujisi): The factory setter is temporarily marked as package private.
// The way to provide customized implementations of maps for different
// platforms are still under discussion. Mark it as private to avoid exposing
// the API in proto3 alpha release.
/* public */
static
void
setMapFactory
(
MapFactory
newMapFactory
)
{
mapFactory
=
newMapFactory
;
}
public
static
MapFactory
getMapFactory
()
{
return
mapFactory
;
}
private
static
class
DefaultMapFactory
implements
MapFactory
{
public
<
K
,
V
>
Map
<
K
,
V
>
forMap
(
Map
<
K
,
V
>
oldMap
)
{
if
(
oldMap
==
null
)
{
return
new
HashMap
<
K
,
V
>();
}
return
oldMap
;
}
}
private
static
volatile
MapFactory
mapFactory
=
new
DefaultMapFactory
();
private
MapFactories
()
{}
}
javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
View file @
2cb2358c
...
...
@@ -30,31 +30,11 @@
package
com
.
google
.
protobuf
.
nano
;
import
com.google.protobuf.nano.CodedInputByteBufferNano
;
import
com.google.protobuf.nano.EnumClassNanoMultiple
;
import
com.google.protobuf.nano.EnumClassNanos
;
import
com.google.protobuf.nano.EnumValidity
;
import
com.google.protobuf.nano.EnumValidityAccessors
;
import
com.google.protobuf.nano.FileScopeEnumMultiple
;
import
com.google.protobuf.nano.FileScopeEnumRefNano
;
import
com.google.protobuf.nano.InternalNano
;
import
com.google.protobuf.nano.InvalidProtocolBufferNanoException
;
import
com.google.protobuf.nano.MessageNano
;
import
com.google.protobuf.nano.MessageScopeEnumRefNano
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano1
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano2
;
import
com.google.protobuf.nano.MultipleNameClashNano
;
import
com.google.protobuf.nano.MapTestProto.TestMap
;
import
com.google.protobuf.nano.MapTestProto.TestMap.MessageValue
;
import
com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors
;
import
com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas
;
import
com.google.protobuf.nano.NanoOuterClass
;
import
com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano
;
import
com.google.protobuf.nano.NanoReferenceTypes
;
import
com.google.protobuf.nano.NanoRepeatedPackables
;
import
com.google.protobuf.nano.PackedExtensions
;
import
com.google.protobuf.nano.RepeatedExtensions
;
import
com.google.protobuf.nano.SingularExtensions
;
import
com.google.protobuf.nano.TestRepeatedMergeNano
;
import
com.google.protobuf.nano.UnittestMultipleNano
;
import
com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano
;
import
com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano
;
import
com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano
;
...
...
@@ -67,6 +47,8 @@ import junit.framework.TestCase;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.TreeMap
;
/**
* Test nano runtime.
...
...
@@ -3754,6 +3736,320 @@ public class NanoTest extends TestCase {
assertTrue
(
Arrays
.
equals
(
new
boolean
[]
{
false
,
true
,
false
,
true
},
nonPacked
.
bools
));
}
public
void
testMapsSerializeAndParse
()
throws
Exception
{
TestMap
origin
=
new
TestMap
();
setMapMessage
(
origin
);
assertMapMessageSet
(
origin
);
byte
[]
output
=
MessageNano
.
toByteArray
(
origin
);
TestMap
parsed
=
new
TestMap
();
MessageNano
.
mergeFrom
(
parsed
,
output
);
}
public
void
testMapSerializeRejectNull
()
throws
Exception
{
TestMap
primitiveMap
=
new
TestMap
();
primitiveMap
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
primitiveMap
.
int32ToInt32Field
.
put
(
null
,
1
);
try
{
MessageNano
.
toByteArray
(
primitiveMap
);
fail
(
"should reject null keys"
);
}
catch
(
IllegalStateException
e
)
{
// pass.
}
TestMap
messageMap
=
new
TestMap
();
messageMap
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
messageMap
.
int32ToMessageField
.
put
(
0
,
null
);
try
{
MessageNano
.
toByteArray
(
messageMap
);
fail
(
"should reject null values"
);
}
catch
(
IllegalStateException
e
)
{
// pass.
}
}
/**
* Tests that merging bytes containing conflicting keys with override the
* message value instead of merging the message value into the existing entry.
*/
public
void
testMapMergeOverrideMessageValues
()
throws
Exception
{
TestMap
.
MessageValue
origValue
=
new
TestMap
.
MessageValue
();
origValue
.
value
=
1
;
origValue
.
value2
=
2
;
TestMap
.
MessageValue
newValue
=
new
TestMap
.
MessageValue
();
newValue
.
value
=
3
;
TestMap
origMessage
=
new
TestMap
();
origMessage
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
origMessage
.
int32ToMessageField
.
put
(
1
,
origValue
);
TestMap
newMessage
=
new
TestMap
();
newMessage
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
newMessage
.
int32ToMessageField
.
put
(
1
,
newValue
);
MessageNano
.
mergeFrom
(
origMessage
,
MessageNano
.
toByteArray
(
newMessage
));
TestMap
.
MessageValue
mergedValue
=
origMessage
.
int32ToMessageField
.
get
(
1
);
assertEquals
(
3
,
mergedValue
.
value
);
assertEquals
(
0
,
mergedValue
.
value2
);
}
/**
* Tests that when merging with empty entries,
* we will use default for the key and value, instead of null.
*/
public
void
testMapMergeEmptyEntry
()
throws
Exception
{
TestMap
testMap
=
new
TestMap
();
byte
[]
buffer
=
new
byte
[
1024
];
CodedOutputByteBufferNano
output
=
CodedOutputByteBufferNano
.
newInstance
(
buffer
);
// An empty entry for int32_to_int32 map.
output
.
writeTag
(
1
,
WireFormatNano
.
WIRETYPE_LENGTH_DELIMITED
);
output
.
writeRawVarint32
(
0
);
// An empty entry for int32_to_message map.
output
.
writeTag
(
5
,
WireFormatNano
.
WIRETYPE_LENGTH_DELIMITED
);
output
.
writeRawVarint32
(
0
);
CodedInputByteBufferNano
input
=
CodedInputByteBufferNano
.
newInstance
(
buffer
,
0
,
buffer
.
length
-
output
.
spaceLeft
());
testMap
.
mergeFrom
(
input
);
assertNotNull
(
testMap
.
int32ToInt32Field
);;
assertEquals
(
1
,
testMap
.
int32ToInt32Field
.
size
());
assertEquals
(
Integer
.
valueOf
(
0
),
testMap
.
int32ToInt32Field
.
get
(
0
));
assertNotNull
(
testMap
.
int32ToMessageField
);
assertEquals
(
1
,
testMap
.
int32ToMessageField
.
size
());
TestMap
.
MessageValue
messageValue
=
testMap
.
int32ToMessageField
.
get
(
0
);
assertNotNull
(
messageValue
);
assertEquals
(
0
,
messageValue
.
value
);
assertEquals
(
0
,
messageValue
.
value2
);
}
public
void
testMapEquals
()
throws
Exception
{
TestMap
a
=
new
TestMap
();
TestMap
b
=
new
TestMap
();
// empty and null map fields are equal.
assertTestMapEqual
(
a
,
b
);
a
.
int32ToBytesField
=
new
HashMap
<
Integer
,
byte
[]>();
assertTestMapEqual
(
a
,
b
);
a
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
b
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
setMap
(
a
.
int32ToInt32Field
,
deepCopy
(
int32Values
),
deepCopy
(
int32Values
));
setMap
(
b
.
int32ToInt32Field
,
deepCopy
(
int32Values
),
deepCopy
(
int32Values
));
assertTestMapEqual
(
a
,
b
);
a
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
b
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
setMap
(
a
.
int32ToMessageField
,
deepCopy
(
int32Values
),
deepCopy
(
messageValues
));
setMap
(
b
.
int32ToMessageField
,
deepCopy
(
int32Values
),
deepCopy
(
messageValues
));
assertTestMapEqual
(
a
,
b
);
a
.
stringToInt32Field
=
new
HashMap
<
String
,
Integer
>();
b
.
stringToInt32Field
=
new
HashMap
<
String
,
Integer
>();
setMap
(
a
.
stringToInt32Field
,
deepCopy
(
stringValues
),
deepCopy
(
int32Values
));
setMap
(
b
.
stringToInt32Field
,
deepCopy
(
stringValues
),
deepCopy
(
int32Values
));
assertTestMapEqual
(
a
,
b
);
a
.
int32ToBytesField
=
new
HashMap
<
Integer
,
byte
[]>();
b
.
int32ToBytesField
=
new
HashMap
<
Integer
,
byte
[]>();
setMap
(
a
.
int32ToBytesField
,
deepCopy
(
int32Values
),
deepCopy
(
bytesValues
));
setMap
(
b
.
int32ToBytesField
,
deepCopy
(
int32Values
),
deepCopy
(
bytesValues
));
assertTestMapEqual
(
a
,
b
);
// Make sure the map implementation does not matter.
a
.
int32ToStringField
=
new
TreeMap
<
Integer
,
String
>();
b
.
int32ToStringField
=
new
HashMap
<
Integer
,
String
>();
setMap
(
a
.
int32ToStringField
,
deepCopy
(
int32Values
),
deepCopy
(
stringValues
));
setMap
(
b
.
int32ToStringField
,
deepCopy
(
int32Values
),
deepCopy
(
stringValues
));
assertTestMapEqual
(
a
,
b
);
a
.
clear
();
b
.
clear
();
// unequal cases: different value
a
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
b
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
a
.
int32ToInt32Field
.
put
(
1
,
1
);
b
.
int32ToInt32Field
.
put
(
1
,
2
);
assertTestMapUnequal
(
a
,
b
);
// unequal case: additional entry
b
.
int32ToInt32Field
.
put
(
1
,
1
);
b
.
int32ToInt32Field
.
put
(
2
,
1
);
assertTestMapUnequal
(
a
,
b
);
a
.
int32ToInt32Field
.
put
(
2
,
1
);
assertTestMapEqual
(
a
,
b
);
// unequal case: different message value.
a
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
b
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
MessageValue
va
=
new
MessageValue
();
va
.
value
=
1
;
MessageValue
vb
=
new
MessageValue
();
vb
.
value
=
1
;
a
.
int32ToMessageField
.
put
(
1
,
va
);
b
.
int32ToMessageField
.
put
(
1
,
vb
);
assertTestMapEqual
(
a
,
b
);
vb
.
value
=
2
;
assertTestMapUnequal
(
a
,
b
);
}
private
static
void
assertTestMapEqual
(
TestMap
a
,
TestMap
b
)
throws
Exception
{
assertEquals
(
a
.
hashCode
(),
b
.
hashCode
());
assertTrue
(
a
.
equals
(
b
));
assertTrue
(
b
.
equals
(
a
));
}
private
static
void
assertTestMapUnequal
(
TestMap
a
,
TestMap
b
)
throws
Exception
{
assertFalse
(
a
.
equals
(
b
));
assertFalse
(
b
.
equals
(
a
));
}
private
static
final
Integer
[]
int32Values
=
new
Integer
[]
{
0
,
1
,
-
1
,
Integer
.
MAX_VALUE
,
Integer
.
MIN_VALUE
,
};
private
static
final
Long
[]
int64Values
=
new
Long
[]
{
0L
,
1L
,
-
1L
,
Long
.
MAX_VALUE
,
Long
.
MIN_VALUE
,
};
private
static
final
String
[]
stringValues
=
new
String
[]
{
""
,
"hello"
,
"world"
,
"foo"
,
"bar"
,
};
private
static
final
byte
[][]
bytesValues
=
new
byte
[][]
{
new
byte
[]
{},
new
byte
[]
{
0
},
new
byte
[]
{
1
,
-
1
},
new
byte
[]
{
127
,
-
128
},
new
byte
[]
{
'a'
,
'b'
,
'0'
,
'1'
},
};
private
static
final
Boolean
[]
boolValues
=
new
Boolean
[]
{
false
,
true
,
};
private
static
final
Integer
[]
enumValues
=
new
Integer
[]
{
TestMap
.
FOO
,
TestMap
.
BAR
,
TestMap
.
BAZ
,
TestMap
.
QUX
,
Integer
.
MAX_VALUE
/* unknown */
,
};
private
static
final
TestMap
.
MessageValue
[]
messageValues
=
new
TestMap
.
MessageValue
[]
{
newMapValueMessage
(
0
),
newMapValueMessage
(
1
),
newMapValueMessage
(-
1
),
newMapValueMessage
(
Integer
.
MAX_VALUE
),
newMapValueMessage
(
Integer
.
MIN_VALUE
),
};
private
static
TestMap
.
MessageValue
newMapValueMessage
(
int
value
)
{
TestMap
.
MessageValue
result
=
new
TestMap
.
MessageValue
();
result
.
value
=
value
;
return
result
;
}
@SuppressWarnings
(
"unchecked"
)
private
static
<
T
>
T
[]
deepCopy
(
T
[]
orig
)
throws
Exception
{
if
(
orig
instanceof
MessageValue
[])
{
MessageValue
[]
result
=
new
MessageValue
[
orig
.
length
];
for
(
int
i
=
0
;
i
<
orig
.
length
;
i
++)
{
result
[
i
]
=
new
MessageValue
();
MessageNano
.
mergeFrom
(
result
[
i
],
MessageNano
.
toByteArray
((
MessageValue
)
orig
[
i
]));
}
return
(
T
[])
result
;
}
if
(
orig
instanceof
byte
[][])
{
byte
[][]
result
=
new
byte
[
orig
.
length
][];
for
(
int
i
=
0
;
i
<
orig
.
length
;
i
++)
{
byte
[]
origBytes
=
(
byte
[])
orig
[
i
];
result
[
i
]
=
Arrays
.
copyOf
(
origBytes
,
origBytes
.
length
);
}
}
return
Arrays
.
copyOf
(
orig
,
orig
.
length
);
}
private
<
K
,
V
>
void
setMap
(
Map
<
K
,
V
>
map
,
K
[]
keys
,
V
[]
values
)
{
assert
(
keys
.
length
==
values
.
length
);
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
map
.
put
(
keys
[
i
],
values
[
i
]);
}
}
private
<
K
,
V
>
void
assertMapSet
(
Map
<
K
,
V
>
map
,
K
[]
keys
,
V
[]
values
)
throws
Exception
{
assert
(
keys
.
length
==
values
.
length
);
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
assertEquals
(
values
[
i
],
map
.
get
(
keys
[
i
]));
}
assertEquals
(
keys
.
length
,
map
.
size
());
}
private
void
setMapMessage
(
TestMap
testMap
)
{
testMap
.
int32ToInt32Field
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
int32ToBytesField
=
new
HashMap
<
Integer
,
byte
[]>();
testMap
.
int32ToEnumField
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
int32ToMessageField
=
new
HashMap
<
Integer
,
MapTestProto
.
TestMap
.
MessageValue
>();
testMap
.
int32ToStringField
=
new
HashMap
<
Integer
,
String
>();
testMap
.
stringToInt32Field
=
new
HashMap
<
String
,
Integer
>();
testMap
.
boolToBoolField
=
new
HashMap
<
Boolean
,
Boolean
>();
testMap
.
uint32ToUint32Field
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
sint32ToSint32Field
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
fixed32ToFixed32Field
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
sfixed32ToSfixed32Field
=
new
HashMap
<
Integer
,
Integer
>();
testMap
.
int64ToInt64Field
=
new
HashMap
<
Long
,
Long
>();
testMap
.
uint64ToUint64Field
=
new
HashMap
<
Long
,
Long
>();
testMap
.
sint64ToSint64Field
=
new
HashMap
<
Long
,
Long
>();
testMap
.
fixed64ToFixed64Field
=
new
HashMap
<
Long
,
Long
>();
testMap
.
sfixed64ToSfixed64Field
=
new
HashMap
<
Long
,
Long
>();
setMap
(
testMap
.
int32ToInt32Field
,
int32Values
,
int32Values
);
setMap
(
testMap
.
int32ToBytesField
,
int32Values
,
bytesValues
);
setMap
(
testMap
.
int32ToEnumField
,
int32Values
,
enumValues
);
setMap
(
testMap
.
int32ToMessageField
,
int32Values
,
messageValues
);
setMap
(
testMap
.
int32ToStringField
,
int32Values
,
stringValues
);
setMap
(
testMap
.
stringToInt32Field
,
stringValues
,
int32Values
);
setMap
(
testMap
.
boolToBoolField
,
boolValues
,
boolValues
);
setMap
(
testMap
.
uint32ToUint32Field
,
int32Values
,
int32Values
);
setMap
(
testMap
.
sint32ToSint32Field
,
int32Values
,
int32Values
);
setMap
(
testMap
.
fixed32ToFixed32Field
,
int32Values
,
int32Values
);
setMap
(
testMap
.
sfixed32ToSfixed32Field
,
int32Values
,
int32Values
);
setMap
(
testMap
.
int64ToInt64Field
,
int64Values
,
int64Values
);
setMap
(
testMap
.
uint64ToUint64Field
,
int64Values
,
int64Values
);
setMap
(
testMap
.
sint64ToSint64Field
,
int64Values
,
int64Values
);
setMap
(
testMap
.
fixed64ToFixed64Field
,
int64Values
,
int64Values
);
setMap
(
testMap
.
sfixed64ToSfixed64Field
,
int64Values
,
int64Values
);
}
private
void
assertMapMessageSet
(
TestMap
testMap
)
throws
Exception
{
assertMapSet
(
testMap
.
int32ToInt32Field
,
int32Values
,
int32Values
);
assertMapSet
(
testMap
.
int32ToBytesField
,
int32Values
,
bytesValues
);
assertMapSet
(
testMap
.
int32ToEnumField
,
int32Values
,
enumValues
);
assertMapSet
(
testMap
.
int32ToMessageField
,
int32Values
,
messageValues
);
assertMapSet
(
testMap
.
int32ToStringField
,
int32Values
,
stringValues
);
assertMapSet
(
testMap
.
stringToInt32Field
,
stringValues
,
int32Values
);
assertMapSet
(
testMap
.
boolToBoolField
,
boolValues
,
boolValues
);
assertMapSet
(
testMap
.
uint32ToUint32Field
,
int32Values
,
int32Values
);
assertMapSet
(
testMap
.
sint32ToSint32Field
,
int32Values
,
int32Values
);
assertMapSet
(
testMap
.
fixed32ToFixed32Field
,
int32Values
,
int32Values
);
assertMapSet
(
testMap
.
sfixed32ToSfixed32Field
,
int32Values
,
int32Values
);
assertMapSet
(
testMap
.
int64ToInt64Field
,
int64Values
,
int64Values
);
assertMapSet
(
testMap
.
uint64ToUint64Field
,
int64Values
,
int64Values
);
assertMapSet
(
testMap
.
sint64ToSint64Field
,
int64Values
,
int64Values
);
assertMapSet
(
testMap
.
fixed64ToFixed64Field
,
int64Values
,
int64Values
);
assertMapSet
(
testMap
.
sfixed64ToSfixed64Field
,
int64Values
,
int64Values
);
}
private
void
assertRepeatedPackablesEqual
(
NanoRepeatedPackables
.
NonPacked
nonPacked
,
NanoRepeatedPackables
.
Packed
packed
)
{
// Not using MessageNano.equals() -- that belongs to a separate test.
...
...
javanano/src/test/java/com/google/protobuf/nano/map_test.proto
0 → 100644
View file @
2cb2358c
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax
=
"proto3"
;
package
map_test
;
option
java_package
=
"com.google.protobuf.nano"
;
option
java_outer_classname
=
"MapTestProto"
;
message
TestMap
{
message
MessageValue
{
int32
value
=
1
;
int32
value2
=
2
;
}
enum
EnumValue
{
FOO
=
0
;
BAR
=
1
;
BAZ
=
2
;
QUX
=
3
;
}
map
<
int32
,
int32
>
int32_to_int32_field
=
1
;
map
<
int32
,
string
>
int32_to_string_field
=
2
;
map
<
int32
,
bytes
>
int32_to_bytes_field
=
3
;
map
<
int32
,
EnumValue
>
int32_to_enum_field
=
4
;
map
<
int32
,
MessageValue
>
int32_to_message_field
=
5
;
map
<
string
,
int32
>
string_to_int32_field
=
6
;
map
<
bool
,
bool
>
bool_to_bool_field
=
7
;
// Test all the other primitive types. As the key and value are not coupled in
// the implementation, we do not test all the combinations of key/value pairs,
// so that we can keep the number of test cases manageable
map
<
uint32
,
uint32
>
uint32_to_uint32_field
=
11
;
map
<
sint32
,
sint32
>
sint32_to_sint32_field
=
12
;
map
<
fixed32
,
fixed32
>
fixed32_to_fixed32_field
=
13
;
map
<
sfixed32
,
sfixed32
>
sfixed32_to_sfixed32_field
=
14
;
map
<
int64
,
int64
>
int64_to_int64_field
=
15
;
map
<
uint64
,
uint64
>
uint64_to_uint64_field
=
16
;
map
<
sint64
,
sint64
>
sint64_to_sint64_field
=
17
;
map
<
fixed64
,
fixed64
>
fixed64_to_fixed64_field
=
18
;
map
<
sfixed64
,
sfixed64
>
sfixed64_to_sfixed64_field
=
19
;
}
src/Makefile.am
View file @
2cb2358c
...
...
@@ -243,26 +243,28 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_doc_comment.cc
\
google/protobuf/compiler/java/java_doc_comment.h
\
google/protobuf/compiler/javanano/javanano_enum.cc
\
google/protobuf/compiler/javanano/javanano_enum.h
\
google/protobuf/compiler/javanano/javanano_enum_field.cc
\
google/protobuf/compiler/javanano/javanano_enum_field.h
\
google/protobuf/compiler/javanano/javanano_extension.cc
\
google/protobuf/compiler/javanano/javanano_extension.h
\
google/protobuf/compiler/javanano/javanano_field.cc
\
google/protobuf/compiler/javanano/javanano_field.h
\
google/protobuf/compiler/javanano/javanano_file.cc
\
google/protobuf/compiler/javanano/javanano_file.h
\
google/protobuf/compiler/javanano/javanano_generator.cc
\
google/protobuf/compiler/javanano/javanano_generator.h
\
google/protobuf/compiler/javanano/javanano_helpers.cc
\
google/protobuf/compiler/javanano/javanano_helpers.h
\
google/protobuf/compiler/javanano/javanano_map_field.cc
\
google/protobuf/compiler/javanano/javanano_map_field.h
\
google/protobuf/compiler/javanano/javanano_message.cc
\
google/protobuf/compiler/javanano/javanano_message.h
\
google/protobuf/compiler/javanano/javanano_message_field.cc
\
google/protobuf/compiler/javanano/javanano_message_field.h
\
google/protobuf/compiler/javanano/javanano_params.h
\
google/protobuf/compiler/javanano/javanano_primitive_field.h
\
google/protobuf/compiler/javanano/javanano_enum_field.cc
\
google/protobuf/compiler/javanano/javanano_enum.h
\
google/protobuf/compiler/javanano/javanano_extension.h
\
google/protobuf/compiler/javanano/javanano_field.h
\
google/protobuf/compiler/javanano/javanano_file.h
\
google/protobuf/compiler/javanano/javanano_generator.h
\
google/protobuf/compiler/javanano/javanano_helpers.h
\
google/protobuf/compiler/javanano/javanano_message_field.cc
\
google/protobuf/compiler/javanano/javanano_message.h
\
google/protobuf/compiler/javanano/javanano_primitive_field.cc
\
google/protobuf/compiler/javanano/javanano_primitive_field.h
\
google/protobuf/compiler/python/python_generator.cc
\
google/protobuf/compiler/ruby/ruby_generator.cc
...
...
src/google/protobuf/compiler/javanano/javanano_field.cc
View file @
2cb2358c
...
...
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
#include <google/protobuf/compiler/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/stubs/common.h>
...
...
@@ -97,7 +98,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
if
(
field
->
is_repeated
())
{
switch
(
java_type
)
{
case
JAVATYPE_MESSAGE
:
if
(
IsMapEntry
(
field
->
message_type
()))
{
return
new
MapFieldGenerator
(
field
,
params
);
}
else
{
return
new
RepeatedMessageFieldGenerator
(
field
,
params
);
}
case
JAVATYPE_ENUM
:
return
new
RepeatedEnumFieldGenerator
(
field
,
params
);
default
:
...
...
src/google/protobuf/compiler/javanano/javanano_helpers.cc
View file @
2cb2358c
...
...
@@ -560,6 +560,17 @@ void SetBitOperationVariables(const string name,
(
*
variables
)[
"different_"
+
name
]
=
GenerateDifferentBit
(
bitIndex
);
}
bool
HasMapField
(
const
Descriptor
*
descriptor
)
{
for
(
int
i
=
0
;
i
<
descriptor
->
field_count
();
++
i
)
{
const
FieldDescriptor
*
field
=
descriptor
->
field
(
i
);
if
(
field
->
type
()
==
FieldDescriptor
::
TYPE_MESSAGE
&&
IsMapEntry
(
field
->
message_type
()))
{
return
true
;
}
}
return
false
;
}
}
// namespace javanano
}
// namespace compiler
}
// namespace protobuf
...
...
src/google/protobuf/compiler/javanano/javanano_helpers.h
View file @
2cb2358c
...
...
@@ -181,6 +181,14 @@ string GenerateDifferentBit(int bit_index);
void
SetBitOperationVariables
(
const
string
name
,
int
bitIndex
,
map
<
string
,
string
>*
variables
);
inline
bool
IsMapEntry
(
const
Descriptor
*
descriptor
)
{
// TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
return
descriptor
->
options
().
map_entry
()
&&
descriptor
->
file
()
->
syntax
()
==
FileDescriptor
::
SYNTAX_PROTO3
;
}
bool
HasMapField
(
const
Descriptor
*
descriptor
);
}
// namespace javanano
}
// namespace compiler
}
// namespace protobuf
...
...
src/google/protobuf/compiler/javanano/javanano_map_field.cc
0 → 100644
View file @
2cb2358c
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/compiler/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace
google
{
namespace
protobuf
{
namespace
compiler
{
namespace
javanano
{
namespace
{
string
TypeName
(
const
Params
&
params
,
const
FieldDescriptor
*
field
,
bool
boxed
)
{
JavaType
java_type
=
GetJavaType
(
field
);
switch
(
java_type
)
{
case
JAVATYPE_MESSAGE
:
return
ClassName
(
params
,
field
->
message_type
());
case
JAVATYPE_INT
:
case
JAVATYPE_LONG
:
case
JAVATYPE_FLOAT
:
case
JAVATYPE_DOUBLE
:
case
JAVATYPE_BOOLEAN
:
case
JAVATYPE_STRING
:
case
JAVATYPE_BYTES
:
case
JAVATYPE_ENUM
:
if
(
boxed
)
{
return
BoxedPrimitiveTypeName
(
java_type
);
}
else
{
return
PrimitiveTypeName
(
java_type
);
}
// No default because we want the compiler to complain if any new JavaTypes
// are added..
}
GOOGLE_LOG
(
FATAL
)
<<
"should not reach here."
;
return
""
;
}
const
FieldDescriptor
*
KeyField
(
const
FieldDescriptor
*
descriptor
)
{
GOOGLE_CHECK_EQ
(
FieldDescriptor
::
TYPE_MESSAGE
,
descriptor
->
type
());
const
Descriptor
*
message
=
descriptor
->
message_type
();
GOOGLE_CHECK
(
message
->
options
().
map_entry
());
return
message
->
FindFieldByName
(
"key"
);
}
const
FieldDescriptor
*
ValueField
(
const
FieldDescriptor
*
descriptor
)
{
GOOGLE_CHECK_EQ
(
FieldDescriptor
::
TYPE_MESSAGE
,
descriptor
->
type
());
const
Descriptor
*
message
=
descriptor
->
message_type
();
GOOGLE_CHECK
(
message
->
options
().
map_entry
());
return
message
->
FindFieldByName
(
"value"
);
}
void
SetMapVariables
(
const
Params
&
params
,
const
FieldDescriptor
*
descriptor
,
map
<
string
,
string
>*
variables
)
{
const
FieldDescriptor
*
key
=
KeyField
(
descriptor
);
const
FieldDescriptor
*
value
=
ValueField
(
descriptor
);
(
*
variables
)[
"name"
]
=
RenameJavaKeywords
(
UnderscoresToCamelCase
(
descriptor
));
(
*
variables
)[
"number"
]
=
SimpleItoa
(
descriptor
->
number
());
(
*
variables
)[
"key_type"
]
=
TypeName
(
params
,
key
,
false
);
(
*
variables
)[
"boxed_key_type"
]
=
TypeName
(
params
,
key
,
true
);
(
*
variables
)[
"key_desc_type"
]
=
"TYPE_"
+
ToUpper
(
FieldDescriptor
::
TypeName
(
key
->
type
()));
(
*
variables
)[
"key_tag"
]
=
SimpleItoa
(
internal
::
WireFormat
::
MakeTag
(
key
));
(
*
variables
)[
"value_type"
]
=
TypeName
(
params
,
value
,
false
);
(
*
variables
)[
"boxed_value_type"
]
=
TypeName
(
params
,
value
,
true
);
(
*
variables
)[
"value_desc_type"
]
=
"TYPE_"
+
ToUpper
(
FieldDescriptor
::
TypeName
(
value
->
type
()));
(
*
variables
)[
"value_tag"
]
=
SimpleItoa
(
internal
::
WireFormat
::
MakeTag
(
value
));
(
*
variables
)[
"type_parameters"
]
=
(
*
variables
)[
"boxed_key_type"
]
+
", "
+
(
*
variables
)[
"boxed_value_type"
];
(
*
variables
)[
"value_default"
]
=
value
->
type
()
==
FieldDescriptor
::
TYPE_MESSAGE
?
"new "
+
(
*
variables
)[
"value_type"
]
+
"()"
:
"null"
;
}
}
// namespace
// ===================================================================
MapFieldGenerator
::
MapFieldGenerator
(
const
FieldDescriptor
*
descriptor
,
const
Params
&
params
)
:
FieldGenerator
(
params
),
descriptor_
(
descriptor
)
{
SetMapVariables
(
params
,
descriptor
,
&
variables_
);
}
MapFieldGenerator
::~
MapFieldGenerator
()
{}
void
MapFieldGenerator
::
GenerateMembers
(
io
::
Printer
*
printer
,
bool
/* unused lazy_init */
)
const
{
printer
->
Print
(
variables_
,
"public java.util.Map<$type_parameters$> $name$;
\n
"
);
}
void
MapFieldGenerator
::
GenerateClearCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"$name$ = null;
\n
"
);
}
void
MapFieldGenerator
::
GenerateMergingCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(
\n
"
" input, this.$name$, mapFactory,
\n
"
" com.google.protobuf.nano.InternalNano.$key_desc_type$,
\n
"
" com.google.protobuf.nano.InternalNano.$value_desc_type$,
\n
"
" $value_default$,
\n
"
" $key_tag$, $value_tag$);
\n
"
"
\n
"
);
}
void
MapFieldGenerator
::
GenerateSerializationCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"if (this.$name$ != null) {
\n
"
" com.google.protobuf.nano.InternalNano.serializeMapField(
\n
"
" output, this.$name$, $number$,
\n
"
" com.google.protobuf.nano.InternalNano.$key_desc_type$,
\n
"
" com.google.protobuf.nano.InternalNano.$value_desc_type$);
\n
"
"}
\n
"
);
}
void
MapFieldGenerator
::
GenerateSerializedSizeCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"if (this.$name$ != null) {
\n
"
" size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(
\n
"
" this.$name$, $number$,
\n
"
" com.google.protobuf.nano.InternalNano.$key_desc_type$,
\n
"
" com.google.protobuf.nano.InternalNano.$value_desc_type$);
\n
"
"}
\n
"
);
}
void
MapFieldGenerator
::
GenerateEqualsCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"if (!com.google.protobuf.nano.InternalNano.equals(
\n
"
" this.$name$, other.$name$)) {
\n
"
" return false;
\n
"
"}
\n
"
);
}
void
MapFieldGenerator
::
GenerateHashCodeCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"result = 31 * result +
\n
"
" com.google.protobuf.nano.InternalNano.hashCode(this.$name$);
\n
"
);
}
}
// namespace javanano
}
// namespace compiler
}
// namespace protobuf
}
// namespace google
src/google/protobuf/compiler/javanano/javanano_map_field.h
0 → 100644
View file @
2cb2358c
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
#include <map>
#include <string>
#include <vector>
#include <google/protobuf/compiler/javanano/javanano_field.h>
namespace
google
{
namespace
protobuf
{
namespace
compiler
{
namespace
javanano
{
class
MapFieldGenerator
:
public
FieldGenerator
{
public
:
explicit
MapFieldGenerator
(
const
FieldDescriptor
*
descriptor
,
const
Params
&
params
);
~
MapFieldGenerator
();
// implements FieldGenerator ---------------------------------------
void
GenerateMembers
(
io
::
Printer
*
printer
,
bool
lazy_init
)
const
;
void
GenerateClearCode
(
io
::
Printer
*
printer
)
const
;
void
GenerateMergingCode
(
io
::
Printer
*
printer
)
const
;
void
GenerateSerializationCode
(
io
::
Printer
*
printer
)
const
;
void
GenerateSerializedSizeCode
(
io
::
Printer
*
printer
)
const
;
void
GenerateEqualsCode
(
io
::
Printer
*
printer
)
const
;
void
GenerateHashCodeCode
(
io
::
Printer
*
printer
)
const
;
private
:
const
FieldDescriptor
*
descriptor_
;
map
<
string
,
string
>
variables_
;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
(
MapFieldGenerator
);
};
}
// namespace javanano
}
// namespace compiler
}
// namespace protobuf
}
// namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
src/google/protobuf/compiler/javanano/javanano_message.cc
View file @
2cb2358c
...
...
@@ -90,6 +90,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// Generate static members for all nested types.
for
(
int
i
=
0
;
i
<
descriptor_
->
nested_type_count
();
i
++
)
{
// TODO(kenton): Reuse MessageGenerator objects?
if
(
IsMapEntry
(
descriptor_
->
nested_type
(
i
)))
continue
;
MessageGenerator
(
descriptor_
->
nested_type
(
i
),
params_
)
.
GenerateStaticVariables
(
printer
);
}
...
...
@@ -100,6 +101,7 @@ void MessageGenerator::GenerateStaticVariableInitializers(
// Generate static member initializers for all nested types.
for
(
int
i
=
0
;
i
<
descriptor_
->
nested_type_count
();
i
++
)
{
// TODO(kenton): Reuse MessageGenerator objects?
if
(
IsMapEntry
(
descriptor_
->
nested_type
(
i
)))
continue
;
MessageGenerator
(
descriptor_
->
nested_type
(
i
),
params_
)
.
GenerateStaticVariableInitializers
(
printer
);
}
...
...
@@ -159,6 +161,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
for
(
int
i
=
0
;
i
<
descriptor_
->
nested_type_count
();
i
++
)
{
if
(
IsMapEntry
(
descriptor_
->
nested_type
(
i
)))
continue
;
MessageGenerator
(
descriptor_
->
nested_type
(
i
),
params_
).
Generate
(
printer
);
}
...
...
@@ -342,6 +345,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
"classname"
,
descriptor_
->
name
());
printer
->
Indent
();
if
(
HasMapField
(
descriptor_
))
{
printer
->
Print
(
"com.google.protobuf.nano.MapFactories.MapFactory mapFactory =
\n
"
" com.google.protobuf.nano.MapFactories.getMapFactory();
\n
"
);
}
printer
->
Print
(
"while (true) {
\n
"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment