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
064b60c6
Commit
064b60c6
authored
Jul 29, 2013
by
Ulas Kirazci
Committed by
Gerrit Code Review
Jul 29, 2013
Browse files
Options
Browse Files
Download
Plain Diff
Merge "Add an option to inspect "has" state upon parse."
parents
a91e2fc4
e83bbbbe
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
265 additions
and
31 deletions
+265
-31
README.txt
java/README.txt
+16
-0
NanoTest.java
java/src/test/java/com/google/protobuf/NanoTest.java
+88
-0
javanano_enum_field.cc
src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+24
-2
javanano_generator.cc
src/google/protobuf/compiler/javanano/javanano_generator.cc
+2
-0
javanano_message.cc
src/google/protobuf/compiler/javanano/javanano_message.cc
+9
-0
javanano_params.h
src/google/protobuf/compiler/javanano/javanano_params.h
+10
-1
javanano_primitive_field.cc
...le/protobuf/compiler/javanano/javanano_primitive_field.cc
+36
-28
javanano_primitive_field.h
...gle/protobuf/compiler/javanano/javanano_primitive_field.h
+2
-0
unittest_has_nano.proto
src/google/protobuf/unittest_has_nano.proto
+78
-0
No files found.
java/README.txt
View file @
064b60c6
...
...
@@ -301,6 +301,22 @@ message's constructor or clear() function is called, the default value
penalty. This is not a problem if the field has no default or is an
empty default.
Nano Generator options
java_nano_generate_has:
If true, generates a public boolean variable has<fieldname>
accompanying the optional or required field (not present for
repeated fields, groups or messages). It is set to false initially
and upon clear(). If parseFrom(...) reads the field from the wire,
it is set to true. This is a way for clients to inspect the "has"
value upon parse. If it is set to true, writeTo(...) will ALWAYS
output that field (even if field value is equal to its
default).
IMPORTANT: This option costs an extra 4 bytes per primitive field in
the message. Think carefully about whether you really need this. In
many cases reading the default works and determining whether the
field was received over the wire is irrelevant.
To use nano protobufs:
...
...
java/src/test/java/com/google/protobuf/NanoTest.java
View file @
064b60c6
...
...
@@ -37,6 +37,7 @@ import com.google.protobuf.nano.InternalNano;
import
com.google.protobuf.nano.MessageNano
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano1
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano2
;
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.RecursiveMessageNano
;
...
...
@@ -2095,6 +2096,93 @@ public class NanoTest extends TestCase {
}
}
public
void
testNanoWithHasParseFrom
()
throws
Exception
{
TestAllTypesNanoHas
msg
=
null
;
// Test false on creation, after clear and upon empty parse.
for
(
int
i
=
0
;
i
<
3
;
i
++)
{
if
(
i
==
0
)
{
msg
=
new
TestAllTypesNanoHas
();
}
else
if
(
i
==
1
)
{
msg
.
clear
();
}
else
if
(
i
==
2
)
{
msg
=
TestAllTypesNanoHas
.
parseFrom
(
new
byte
[
0
]);
}
assertFalse
(
msg
.
hasOptionalInt32
);
assertFalse
(
msg
.
hasOptionalString
);
assertFalse
(
msg
.
hasOptionalBytes
);
assertFalse
(
msg
.
hasOptionalNestedEnum
);
assertFalse
(
msg
.
hasDefaultInt32
);
assertFalse
(
msg
.
hasDefaultString
);
assertFalse
(
msg
.
hasDefaultBytes
);
assertFalse
(
msg
.
hasDefaultFloatNan
);
assertFalse
(
msg
.
hasDefaultNestedEnum
);
assertFalse
(
msg
.
hasId
);
msg
.
optionalInt32
=
123
;
msg
.
optionalNestedMessage
=
new
TestAllTypesNanoHas
.
NestedMessage
();
msg
.
optionalNestedMessage
.
bb
=
2
;
msg
.
optionalNestedEnum
=
TestAllTypesNano
.
BAZ
;
}
byte
[]
result
=
MessageNano
.
toByteArray
(
msg
);
int
msgSerializedSize
=
msg
.
getSerializedSize
();
//System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
assertTrue
(
msgSerializedSize
==
13
);
assertEquals
(
result
.
length
,
msgSerializedSize
);
// Has fields true upon parse.
TestAllTypesNanoHas
newMsg
=
TestAllTypesNanoHas
.
parseFrom
(
result
);
assertEquals
(
123
,
newMsg
.
optionalInt32
);
assertTrue
(
newMsg
.
hasOptionalInt32
);
assertEquals
(
2
,
newMsg
.
optionalNestedMessage
.
bb
);
assertTrue
(
newMsg
.
optionalNestedMessage
.
hasBb
);
assertEquals
(
TestAllTypesNanoHas
.
BAZ
,
newMsg
.
optionalNestedEnum
);
assertTrue
(
newMsg
.
hasOptionalNestedEnum
);
}
public
void
testNanoWithHasSerialize
()
throws
Exception
{
TestAllTypesNanoHas
msg
=
new
TestAllTypesNanoHas
();
msg
.
hasOptionalInt32
=
true
;
msg
.
hasOptionalString
=
true
;
msg
.
hasOptionalBytes
=
true
;
msg
.
optionalNestedMessage
=
new
TestAllTypesNanoHas
.
NestedMessage
();
msg
.
optionalNestedMessage
.
hasBb
=
true
;
msg
.
hasOptionalNestedEnum
=
true
;
msg
.
hasDefaultInt32
=
true
;
msg
.
hasDefaultString
=
true
;
msg
.
hasDefaultBytes
=
true
;
msg
.
hasDefaultFloatNan
=
true
;
msg
.
hasDefaultNestedEnum
=
true
;
byte
[]
result
=
MessageNano
.
toByteArray
(
msg
);
int
msgSerializedSize
=
msg
.
getSerializedSize
();
assertEquals
(
result
.
length
,
msgSerializedSize
);
// Now deserialize and find that all fields are set and equal to their defaults.
TestAllTypesNanoHas
newMsg
=
TestAllTypesNanoHas
.
parseFrom
(
result
);
assertTrue
(
newMsg
.
hasOptionalInt32
);
assertTrue
(
newMsg
.
hasOptionalString
);
assertTrue
(
newMsg
.
hasOptionalBytes
);
assertTrue
(
newMsg
.
optionalNestedMessage
.
hasBb
);
assertTrue
(
newMsg
.
hasOptionalNestedEnum
);
assertTrue
(
newMsg
.
hasDefaultInt32
);
assertTrue
(
newMsg
.
hasDefaultString
);
assertTrue
(
newMsg
.
hasDefaultBytes
);
assertTrue
(
newMsg
.
hasDefaultFloatNan
);
assertTrue
(
newMsg
.
hasDefaultNestedEnum
);
assertTrue
(
newMsg
.
hasId
);
assertEquals
(
0
,
newMsg
.
optionalInt32
);
assertEquals
(
0
,
newMsg
.
optionalString
.
length
());
assertEquals
(
0
,
newMsg
.
optionalBytes
.
length
);
assertEquals
(
0
,
newMsg
.
optionalNestedMessage
.
bb
);
assertEquals
(
TestAllTypesNanoHas
.
FOO
,
newMsg
.
optionalNestedEnum
);
assertEquals
(
41
,
newMsg
.
defaultInt32
);
assertEquals
(
"hello"
,
newMsg
.
defaultString
);
assertEquals
(
"world"
,
new
String
(
newMsg
.
defaultBytes
,
"UTF-8"
));
assertEquals
(
TestAllTypesNanoHas
.
BAR
,
newMsg
.
defaultNestedEnum
);
assertEquals
(
Float
.
NaN
,
newMsg
.
defaultFloatNan
);
assertEquals
(
0
,
newMsg
.
id
);
}
/**
* Tests that fields with a default value of NaN are not serialized when
* set to NaN. This is a special case as NaN != NaN, so normal equality
...
...
src/google/protobuf/compiler/javanano/javanano_enum_field.cc
View file @
064b60c6
...
...
@@ -82,12 +82,22 @@ void EnumFieldGenerator::
GenerateMembers
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"public int $name$ = $default$;
\n
"
);
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"public boolean has$capitalized_name$ = false;
\n
"
);
}
}
void
EnumFieldGenerator
::
GenerateParsingCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
" this.$name$ = input.readInt32();
\n
"
);
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
" has$capitalized_name$ = true;
\n
"
);
}
}
void
EnumFieldGenerator
::
...
...
@@ -96,8 +106,14 @@ GenerateSerializationCode(io::Printer* printer) const {
printer
->
Print
(
variables_
,
"output.writeInt32($number$, this.$name$);
\n
"
);
}
else
{
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$ || has$capitalized_name$) {
\n
"
);
}
else
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
);
}
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
" output.writeInt32($number$, this.$name$);
\n
"
"}
\n
"
);
}
...
...
@@ -110,8 +126,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"size += com.google.protobuf.nano.CodedOutputByteBufferNano
\n
"
" .computeInt32Size($number$, this.$name$);
\n
"
);
}
else
{
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$ || has$capitalized_name$) {
\n
"
);
}
else
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
);
}
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano
\n
"
" .computeInt32Size($number$, this.$name$);
\n
"
"}
\n
"
);
...
...
src/google/protobuf/compiler/javanano/javanano_generator.cc
View file @
064b60c6
...
...
@@ -118,6 +118,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
params
.
set_store_unknown_fields
(
options
[
i
].
second
==
"true"
);
}
else
if
(
options
[
i
].
first
==
"java_multiple_files"
)
{
params
.
set_override_java_multiple_files
(
options
[
i
].
second
==
"true"
);
}
else
if
(
options
[
i
].
first
==
"java_nano_generate_has"
)
{
params
.
set_generate_has
(
options
[
i
].
second
==
"true"
);
}
else
{
*
error
=
"Ignore unknown javanano generator option: "
+
options
[
i
].
first
;
}
...
...
src/google/protobuf/compiler/javanano/javanano_message.cc
View file @
064b60c6
...
...
@@ -406,6 +406,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
"name"
,
RenameJavaKeywords
(
UnderscoresToCamelCase
(
field
)),
"default"
,
DefaultValue
(
params_
,
field
));
}
if
(
params_
.
generate_has
()
&&
field
->
label
()
!=
FieldDescriptor
::
LABEL_REPEATED
&&
field
->
type
()
!=
FieldDescriptor
::
TYPE_GROUP
&&
field
->
type
()
!=
FieldDescriptor
::
TYPE_MESSAGE
)
{
printer
->
Print
(
"has$capitalized_name$ = false;
\n
"
,
"capitalized_name"
,
UnderscoresToCapitalizedCamelCase
(
field
));
}
}
// Clear unknown fields.
...
...
src/google/protobuf/compiler/javanano/javanano_params.h
View file @
064b60c6
...
...
@@ -57,13 +57,15 @@ class Params {
NameMap
java_packages_
;
NameMap
java_outer_classnames_
;
NameSet
java_multiple_files_
;
bool
generate_has_
;
public
:
Params
(
const
string
&
base_name
)
:
empty_
(
""
),
base_name_
(
base_name
),
override_java_multiple_files_
(
JAVANANO_MUL_UNSET
),
store_unknown_fields_
(
false
)
{
store_unknown_fields_
(
false
),
generate_has_
(
false
)
{
}
const
string
&
base_name
()
const
{
...
...
@@ -151,6 +153,13 @@ class Params {
return
store_unknown_fields_
;
}
void
set_generate_has
(
bool
value
)
{
generate_has_
=
value
;
}
bool
generate_has
()
const
{
return
generate_has_
;
}
};
}
// namespace javanano
...
...
src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
View file @
064b60c6
...
...
@@ -321,12 +321,46 @@ GenerateMembers(io::Printer* printer) const {
printer
->
Print
(
variables_
,
"public $type$ $name$ = $default$;
\n
"
);
}
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"public boolean has$capitalized_name$ = false;
\n
"
);
}
}
void
PrimitiveFieldGenerator
::
GenerateParsingCode
(
io
::
Printer
*
printer
)
const
{
printer
->
Print
(
variables_
,
"this.$name$ = input.read$capitalized_type$();
\n
"
);
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"has$capitalized_name$ = true;
\n
"
);
}
}
void
PrimitiveFieldGenerator
::
GenerateSerializationConditional
(
io
::
Printer
*
printer
)
const
{
if
(
params_
.
generate_has
())
{
printer
->
Print
(
variables_
,
"if (has$capitalized_name$ || "
);
}
else
{
printer
->
Print
(
variables_
,
"if ("
);
}
if
(
IsArrayType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"!java.util.Arrays.equals(this.$name$, $default$)) {
\n
"
);
}
else
if
(
IsReferenceType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"!this.$name$.equals($default$)) {
\n
"
);
}
else
if
(
IsDefaultNaN
(
descriptor_
))
{
printer
->
Print
(
variables_
,
"!$capitalized_type$.isNaN(this.$name$)) {
\n
"
);
}
else
{
printer
->
Print
(
variables_
,
"this.$name$ != $default$) {
\n
"
);
}
}
void
PrimitiveFieldGenerator
::
...
...
@@ -335,20 +369,7 @@ GenerateSerializationCode(io::Printer* printer) const {
printer
->
Print
(
variables_
,
"output.write$capitalized_type$($number$, this.$name$);
\n
"
);
}
else
{
if
(
IsArrayType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"if (!java.util.Arrays.equals(this.$name$, $default$)) {
\n
"
);
}
else
if
(
IsReferenceType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"if (!this.$name$.equals($default$)) {
\n
"
);
}
else
if
(
IsDefaultNaN
(
descriptor_
))
{
printer
->
Print
(
variables_
,
"if (!$capitalized_type$.isNaN(this.$name$)) {
\n
"
);
}
else
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
);
}
GenerateSerializationConditional
(
printer
);
printer
->
Print
(
variables_
,
" output.write$capitalized_type$($number$, this.$name$);
\n
"
"}
\n
"
);
...
...
@@ -362,20 +383,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"size += com.google.protobuf.nano.CodedOutputByteBufferNano
\n
"
" .compute$capitalized_type$Size($number$, this.$name$);
\n
"
);
}
else
{
if
(
IsArrayType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"if (!java.util.Arrays.equals(this.$name$, $default$)) {
\n
"
);
}
else
if
(
IsReferenceType
(
GetJavaType
(
descriptor_
)))
{
printer
->
Print
(
variables_
,
"if (!this.$name$.equals($default$)) {
\n
"
);
}
else
if
(
IsDefaultNaN
(
descriptor_
))
{
printer
->
Print
(
variables_
,
"if (!$capitalized_type$.isNaN(this.$name$)) {
\n
"
);
}
else
{
printer
->
Print
(
variables_
,
"if (this.$name$ != $default$) {
\n
"
);
}
GenerateSerializationConditional
(
printer
);
printer
->
Print
(
variables_
,
" size += com.google.protobuf.nano.CodedOutputByteBufferNano
\n
"
" .compute$capitalized_type$Size($number$, this.$name$);
\n
"
...
...
src/google/protobuf/compiler/javanano/javanano_primitive_field.h
View file @
064b60c6
...
...
@@ -58,6 +58,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
string
GetBoxedType
()
const
;
private
:
void
GenerateSerializationConditional
(
io
::
Printer
*
printer
)
const
;
const
FieldDescriptor
*
descriptor_
;
map
<
string
,
string
>
variables_
;
...
...
src/google/protobuf/unittest_has_nano.proto
0 → 100644
View file @
064b60c6
// 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.
// Author: ulas@google.com (Ulas Kirazci)
package
protobuf_unittest
;
option
java_package
=
"com.google.protobuf.nano"
;
option
java_outer_classname
=
"NanoHasOuterClass"
;
message
TestAllTypesNanoHas
{
message
NestedMessage
{
optional
int32
bb
=
1
;
}
enum
NestedEnum
{
FOO
=
1
;
BAR
=
2
;
BAZ
=
3
;
}
// Singular
optional
int32
optional_int32
=
1
;
optional
string
optional_string
=
14
;
optional
bytes
optional_bytes
=
15
;
optional
NestedMessage
optional_nested_message
=
18
;
optional
NestedEnum
optional_nested_enum
=
21
;
// Repeated
repeated
int32
repeated_int32
=
31
;
repeated
string
repeated_string
=
44
;
repeated
bytes
repeated_bytes
=
45
;
repeated
NestedMessage
repeated_nested_message
=
48
;
repeated
NestedEnum
repeated_nested_enum
=
51
;
// Singular with defaults
optional
int32
default_int32
=
61
[
default
=
41
];
optional
string
default_string
=
74
[
default
=
"hello"
];
optional
bytes
default_bytes
=
75
[
default
=
"world"
];
optional
float
default_float_nan
=
99
[
default
=
nan
];
optional
NestedEnum
default_nested_enum
=
81
[
default
=
BAR
];
required
int32
id
=
86
;
}
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