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
ceb561d6
Commit
ceb561d6
authored
Jun 25, 2009
by
kenton@google.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Swap(), SwapElements(), and RemoveLast() to Reflection. Patch by Scott Stafford.
parent
f22943c7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
414 additions
and
19 deletions
+414
-19
CHANGES.txt
CHANGES.txt
+10
-0
CONTRIBUTORS.txt
CONTRIBUTORS.txt
+2
-0
cpp_message.cc
src/google/protobuf/compiler/cpp/cpp_message.cc
+20
-15
descriptor.pb.cc
src/google/protobuf/descriptor.pb.cc
+0
-0
extension_set.cc
src/google/protobuf/extension_set.cc
+82
-0
extension_set.h
src/google/protobuf/extension_set.h
+3
-0
generated_message_reflection.cc
src/google/protobuf/generated_message_reflection.cc
+87
-2
generated_message_reflection.h
src/google/protobuf/generated_message_reflection.h
+4
-0
generated_message_reflection_unittest.cc
src/google/protobuf/generated_message_reflection_unittest.cc
+116
-0
message.h
src/google/protobuf/message.h
+20
-1
repeated_field.h
src/google/protobuf/repeated_field.h
+56
-1
test_util.cc
src/google/protobuf/test_util.cc
+0
-0
test_util.h
src/google/protobuf/test_util.h
+14
-0
No files found.
CHANGES.txt
View file @
ceb561d6
????-??-?? version 2.1.1:
C++
* Fixed bug where Message.Swap(Message) was only implemented for
optimize_for_speed. Swap now properly implemented in both modes
(Issue 91).
* Added RemoveLast and SwapElements(index1, index2) to Reflection
interface for repeated elements.
* Added Swap(Message) to Reflection interface.
2009-05-13 version 2.1.0:
2009-05-13 version 2.1.0:
General
General
...
...
CONTRIBUTORS.txt
View file @
ceb561d6
...
@@ -70,3 +70,5 @@ Patch contributors:
...
@@ -70,3 +70,5 @@ Patch contributors:
* Small patch improving performance of in Python serialization.
* Small patch improving performance of in Python serialization.
Alexandre Vassalotti <alexandre@peadrop.com>
Alexandre Vassalotti <alexandre@peadrop.com>
* Emacs mode for Protocol Buffers (editors/protobuf-mode.el).
* Emacs mode for Protocol Buffers (editors/protobuf-mode.el).
Scott Stafford <scott.stafford@gmail.com>
* Added Swap(), SwapElements(), and RemoveLast() to Reflection interface.
src/google/protobuf/compiler/cpp/cpp_message.cc
View file @
ceb561d6
...
@@ -684,13 +684,13 @@ GenerateClassMethods(io::Printer* printer) {
...
@@ -684,13 +684,13 @@ GenerateClassMethods(io::Printer* printer) {
GenerateCopyFrom
(
printer
);
GenerateCopyFrom
(
printer
);
printer
->
Print
(
"
\n
"
);
printer
->
Print
(
"
\n
"
);
GenerateSwap
(
printer
);
printer
->
Print
(
"
\n
"
);
GenerateIsInitialized
(
printer
);
GenerateIsInitialized
(
printer
);
printer
->
Print
(
"
\n
"
);
printer
->
Print
(
"
\n
"
);
}
}
GenerateSwap
(
printer
);
printer
->
Print
(
"
\n
"
);
printer
->
Print
(
printer
->
Print
(
"const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {
\n
"
"const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {
\n
"
" return descriptor();
\n
"
" return descriptor();
\n
"
...
@@ -967,22 +967,27 @@ GenerateSwap(io::Printer* printer) {
...
@@ -967,22 +967,27 @@ GenerateSwap(io::Printer* printer) {
printer
->
Print
(
"if (other != this) {
\n
"
);
printer
->
Print
(
"if (other != this) {
\n
"
);
printer
->
Indent
();
printer
->
Indent
();
for
(
int
i
=
0
;
i
<
descriptor_
->
field_count
();
i
++
)
{
if
(
descriptor_
->
file
()
->
options
().
optimize_for
()
==
FileOptions
::
SPEED
)
{
const
FieldDescriptor
*
field
=
descriptor_
->
field
(
i
);
for
(
int
i
=
0
;
i
<
descriptor_
->
field_count
();
i
++
)
{
field_generators_
.
get
(
field
).
GenerateSwappingCode
(
printer
);
const
FieldDescriptor
*
field
=
descriptor_
->
field
(
i
);
}
field_generators_
.
get
(
field
).
GenerateSwappingCode
(
printer
);
}
for
(
int
i
=
0
;
i
<
(
descriptor_
->
field_count
()
+
31
)
/
32
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
descriptor_
->
field_count
()
+
31
)
/
32
;
++
i
)
{
printer
->
Print
(
"std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);
\n
"
,
printer
->
Print
(
"std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);
\n
"
,
"i"
,
SimpleItoa
(
i
));
"i"
,
SimpleItoa
(
i
));
}
}
printer
->
Print
(
"_unknown_fields_.Swap(&other->_unknown_fields_);
\n
"
);
printer
->
Print
(
"_unknown_fields_.Swap(&other->_unknown_fields_);
\n
"
);
printer
->
Print
(
"std::swap(_cached_size_, other->_cached_size_);
\n
"
);
printer
->
Print
(
"std::swap(_cached_size_, other->_cached_size_);
\n
"
);
if
(
descriptor_
->
extension_range_count
()
>
0
)
{
if
(
descriptor_
->
extension_range_count
()
>
0
)
{
printer
->
Print
(
"_extensions_.Swap(&other->_extensions_);
\n
"
);
printer
->
Print
(
"_extensions_.Swap(&other->_extensions_);
\n
"
);
}
}
else
{
printer
->
Print
(
"GetReflection()->Swap(this, other);"
);
}
}
printer
->
Outdent
();
printer
->
Outdent
();
printer
->
Print
(
"}
\n
"
);
printer
->
Print
(
"}
\n
"
);
printer
->
Outdent
();
printer
->
Outdent
();
...
...
src/google/protobuf/descriptor.pb.cc
View file @
ceb561d6
This diff is collapsed.
Click to expand it.
src/google/protobuf/extension_set.cc
View file @
ceb561d6
...
@@ -497,6 +497,88 @@ Message* ExtensionSet::AddMessage(int number, FieldType type,
...
@@ -497,6 +497,88 @@ Message* ExtensionSet::AddMessage(int number, FieldType type,
#undef GOOGLE_DCHECK_TYPE
#undef GOOGLE_DCHECK_TYPE
void
ExtensionSet
::
RemoveLast
(
int
number
)
{
map
<
int
,
Extension
>::
iterator
iter
=
extensions_
.
find
(
number
);
GOOGLE_CHECK
(
iter
!=
extensions_
.
end
())
<<
"Index out-of-bounds (field is empty)."
;
Extension
*
extension
=
&
iter
->
second
;
GOOGLE_DCHECK
(
extension
->
is_repeated
);
switch
(
cpp_type
(
extension
->
type
))
{
case
FieldDescriptor
:
:
CPPTYPE_INT32
:
extension
->
repeated_int32_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_INT64
:
extension
->
repeated_int64_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_UINT32
:
extension
->
repeated_uint32_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_UINT64
:
extension
->
repeated_uint64_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_FLOAT
:
extension
->
repeated_float_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_DOUBLE
:
extension
->
repeated_double_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_BOOL
:
extension
->
repeated_bool_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_ENUM
:
extension
->
repeated_enum_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_STRING
:
extension
->
repeated_string_value
->
RemoveLast
();
break
;
case
FieldDescriptor
:
:
CPPTYPE_MESSAGE
:
extension
->
repeated_message_value
->
RemoveLast
();
break
;
}
}
void
ExtensionSet
::
SwapElements
(
int
number
,
int
index1
,
int
index2
)
{
map
<
int
,
Extension
>::
iterator
iter
=
extensions_
.
find
(
number
);
GOOGLE_CHECK
(
iter
!=
extensions_
.
end
())
<<
"Index out-of-bounds (field is empty)."
;
Extension
*
extension
=
&
iter
->
second
;
GOOGLE_DCHECK
(
extension
->
is_repeated
);
switch
(
cpp_type
(
extension
->
type
))
{
case
FieldDescriptor
:
:
CPPTYPE_INT32
:
extension
->
repeated_int32_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_INT64
:
extension
->
repeated_int64_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_UINT32
:
extension
->
repeated_uint32_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_UINT64
:
extension
->
repeated_uint64_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_FLOAT
:
extension
->
repeated_float_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_DOUBLE
:
extension
->
repeated_double_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_BOOL
:
extension
->
repeated_bool_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_ENUM
:
extension
->
repeated_enum_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_STRING
:
extension
->
repeated_string_value
->
SwapElements
(
index1
,
index2
);
break
;
case
FieldDescriptor
:
:
CPPTYPE_MESSAGE
:
extension
->
repeated_message_value
->
SwapElements
(
index1
,
index2
);
break
;
}
}
// ===================================================================
// ===================================================================
void
ExtensionSet
::
Clear
()
{
void
ExtensionSet
::
Clear
()
{
...
...
src/google/protobuf/extension_set.h
View file @
ceb561d6
...
@@ -228,6 +228,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
...
@@ -228,6 +228,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const
Descriptor
*
message_type
,
const
Descriptor
*
message_type
,
MessageFactory
*
factory
);
MessageFactory
*
factory
);
void
RemoveLast
(
int
number
);
void
SwapElements
(
int
number
,
int
index1
,
int
index2
);
// -----------------------------------------------------------------
// -----------------------------------------------------------------
// TODO(kenton): Hardcore memory management accessors
// TODO(kenton): Hardcore memory management accessors
...
...
src/google/protobuf/generated_message_reflection.cc
View file @
ceb561d6
...
@@ -269,6 +269,61 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
...
@@ -269,6 +269,61 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
return
total_size
;
return
total_size
;
}
}
void
GeneratedMessageReflection
::
Swap
(
Message
*
message1
,
Message
*
message2
)
const
{
if
(
message1
==
message2
)
return
;
GOOGLE_CHECK_EQ
(
message1
->
GetReflection
(),
this
)
<<
"Tried to swap using reflection object incompatible with message1."
;
GOOGLE_CHECK_EQ
(
message2
->
GetReflection
(),
this
)
<<
"Tried to swap using reflection object incompatible with message2."
;
uint32
*
has_bits1
=
MutableHasBits
(
message1
);
uint32
*
has_bits2
=
MutableHasBits
(
message2
);
int
has_bits_size
=
(
descriptor_
->
field_count
()
+
31
)
/
32
;
for
(
int
i
=
0
;
i
<
has_bits_size
;
i
++
)
{
std
::
swap
(
has_bits1
[
i
],
has_bits2
[
i
]);
}
for
(
int
i
=
0
;
i
<
descriptor_
->
field_count
();
i
++
)
{
const
FieldDescriptor
*
field
=
descriptor_
->
field
(
i
);
if
(
field
->
is_repeated
())
{
MutableRaw
<
GenericRepeatedField
>
(
message1
,
field
)
->
GenericSwap
(
MutableRaw
<
GenericRepeatedField
>
(
message2
,
field
));
}
else
{
switch
(
field
->
cpp_type
())
{
#define SWAP_VALUES(CPPTYPE, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
swap(*MutableRaw<TYPE>(message1, field), \
*MutableRaw<TYPE>(message2, field)); \
break;
SWAP_VALUES
(
INT32
,
int32
);
SWAP_VALUES
(
INT64
,
int64
);
SWAP_VALUES
(
UINT32
,
uint32
);
SWAP_VALUES
(
UINT64
,
uint64
);
SWAP_VALUES
(
FLOAT
,
float
);
SWAP_VALUES
(
DOUBLE
,
double
);
SWAP_VALUES
(
BOOL
,
bool
);
SWAP_VALUES
(
ENUM
,
int32
);
SWAP_VALUES
(
STRING
,
string
*
);
SWAP_VALUES
(
MESSAGE
,
Message
*
);
#undef SWAP_PRIMITIVE_VALUES
default
:
GOOGLE_LOG
(
FATAL
)
<<
"Unimplemented type: "
<<
field
->
cpp_type
();
}
}
}
if
(
extensions_offset_
!=
-
1
)
{
MutableExtensionSet
(
message1
)
->
Swap
(
MutableExtensionSet
(
message2
));
}
MutableUnknownFields
(
message1
)
->
Swap
(
MutableUnknownFields
(
message2
));
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
bool
GeneratedMessageReflection
::
HasField
(
const
Message
&
message
,
bool
GeneratedMessageReflection
::
HasField
(
const
Message
&
message
,
...
@@ -285,8 +340,8 @@ bool GeneratedMessageReflection::HasField(const Message& message,
...
@@ -285,8 +340,8 @@ bool GeneratedMessageReflection::HasField(const Message& message,
int
GeneratedMessageReflection
::
FieldSize
(
const
Message
&
message
,
int
GeneratedMessageReflection
::
FieldSize
(
const
Message
&
message
,
const
FieldDescriptor
*
field
)
const
{
const
FieldDescriptor
*
field
)
const
{
USAGE_CHECK_MESSAGE_TYPE
(
HasField
);
USAGE_CHECK_MESSAGE_TYPE
(
FieldSize
);
USAGE_CHECK_REPEATED
(
HasField
);
USAGE_CHECK_REPEATED
(
FieldSize
);
if
(
field
->
is_extension
())
{
if
(
field
->
is_extension
())
{
return
GetExtensionSet
(
message
).
ExtensionSize
(
field
->
number
());
return
GetExtensionSet
(
message
).
ExtensionSize
(
field
->
number
());
...
@@ -350,6 +405,36 @@ void GeneratedMessageReflection::ClearField(
...
@@ -350,6 +405,36 @@ void GeneratedMessageReflection::ClearField(
}
}
}
}
void
GeneratedMessageReflection
::
RemoveLast
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
{
USAGE_CHECK_MESSAGE_TYPE
(
RemoveLast
);
USAGE_CHECK_REPEATED
(
RemoveLast
);
if
(
field
->
is_extension
())
{
MutableExtensionSet
(
message
)
->
RemoveLast
(
field
->
number
());
}
else
{
MutableRaw
<
GenericRepeatedField
>
(
message
,
field
)
->
GenericRemoveLast
();
}
}
void
GeneratedMessageReflection
::
SwapElements
(
Message
*
message
,
const
FieldDescriptor
*
field
,
int
index1
,
int
index2
)
const
{
USAGE_CHECK_MESSAGE_TYPE
(
Swap
);
USAGE_CHECK_REPEATED
(
Swap
);
if
(
field
->
is_extension
())
{
MutableExtensionSet
(
message
)
->
SwapElements
(
field
->
number
(),
index1
,
index2
);
}
else
{
MutableRaw
<
GenericRepeatedField
>
(
message
,
field
)
->
GenericSwapElements
(
index1
,
index2
);
}
}
namespace
{
namespace
{
// Comparison functor for sorting FieldDescriptors by field number.
// Comparison functor for sorting FieldDescriptors by field number.
struct
FieldNumberSorter
{
struct
FieldNumberSorter
{
...
...
src/google/protobuf/generated_message_reflection.h
View file @
ceb561d6
...
@@ -140,6 +140,10 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
...
@@ -140,6 +140,10 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
bool
HasField
(
const
Message
&
message
,
const
FieldDescriptor
*
field
)
const
;
bool
HasField
(
const
Message
&
message
,
const
FieldDescriptor
*
field
)
const
;
int
FieldSize
(
const
Message
&
message
,
const
FieldDescriptor
*
field
)
const
;
int
FieldSize
(
const
Message
&
message
,
const
FieldDescriptor
*
field
)
const
;
void
ClearField
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
;
void
ClearField
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
;
void
RemoveLast
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
;
void
Swap
(
Message
*
message1
,
Message
*
message2
)
const
;
void
SwapElements
(
Message
*
message
,
const
FieldDescriptor
*
field
,
int
index1
,
int
index2
)
const
;
void
ListFields
(
const
Message
&
message
,
void
ListFields
(
const
Message
&
message
,
vector
<
const
FieldDescriptor
*>*
output
)
const
;
vector
<
const
FieldDescriptor
*>*
output
)
const
;
...
...
src/google/protobuf/generated_message_reflection_unittest.cc
View file @
ceb561d6
...
@@ -146,6 +146,122 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
...
@@ -146,6 +146,122 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
&
reflection
->
GetMessage
(
message
,
F
(
"optional_import_message"
)));
&
reflection
->
GetMessage
(
message
,
F
(
"optional_import_message"
)));
}
}
TEST
(
GeneratedMessageReflectionTest
,
Swap
)
{
unittest
::
TestAllTypes
message1
;
unittest
::
TestAllTypes
message2
;
TestUtil
::
SetAllFields
(
&
message1
);
const
Reflection
*
reflection
=
message1
.
GetReflection
();
reflection
->
Swap
(
&
message1
,
&
message2
);
TestUtil
::
ExpectClear
(
message1
);
TestUtil
::
ExpectAllFieldsSet
(
message2
);
}
TEST
(
GeneratedMessageReflectionTest
,
SwapWithBothSet
)
{
unittest
::
TestAllTypes
message1
;
unittest
::
TestAllTypes
message2
;
TestUtil
::
SetAllFields
(
&
message1
);
TestUtil
::
SetAllFields
(
&
message2
);
TestUtil
::
ModifyRepeatedFields
(
&
message2
);
const
Reflection
*
reflection
=
message1
.
GetReflection
();
reflection
->
Swap
(
&
message1
,
&
message2
);
TestUtil
::
ExpectRepeatedFieldsModified
(
message1
);
TestUtil
::
ExpectAllFieldsSet
(
message2
);
message1
.
set_optional_int32
(
532819
);
reflection
->
Swap
(
&
message1
,
&
message2
);
EXPECT_EQ
(
532819
,
message2
.
optional_int32
());
}
TEST
(
GeneratedMessageReflectionTest
,
SwapExtensions
)
{
unittest
::
TestAllExtensions
message1
;
unittest
::
TestAllExtensions
message2
;
TestUtil
::
SetAllExtensions
(
&
message1
);
const
Reflection
*
reflection
=
message1
.
GetReflection
();
reflection
->
Swap
(
&
message1
,
&
message2
);
TestUtil
::
ExpectExtensionsClear
(
message1
);
TestUtil
::
ExpectAllExtensionsSet
(
message2
);
}
TEST
(
GeneratedMessageReflectionTest
,
SwapUnknown
)
{
unittest
::
TestEmptyMessage
message1
,
message2
;
message1
.
mutable_unknown_fields
()
->
AddVarint
(
1234
,
1
);
EXPECT_EQ
(
1
,
message1
.
unknown_fields
().
field_count
());
EXPECT_EQ
(
0
,
message2
.
unknown_fields
().
field_count
());
const
Reflection
*
reflection
=
message1
.
GetReflection
();
reflection
->
Swap
(
&
message1
,
&
message2
);
EXPECT_EQ
(
0
,
message1
.
unknown_fields
().
field_count
());
EXPECT_EQ
(
1
,
message2
.
unknown_fields
().
field_count
());
}
TEST
(
GeneratedMessageReflectionTest
,
RemoveLast
)
{
unittest
::
TestAllTypes
message
;
TestUtil
::
ReflectionTester
reflection_tester
(
unittest
::
TestAllTypes
::
descriptor
());
TestUtil
::
SetAllFields
(
&
message
);
reflection_tester
.
RemoveLastRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectLastRepeatedsRemoved
(
message
);
}
TEST
(
GeneratedMessageReflectionTest
,
RemoveLastExtensions
)
{
unittest
::
TestAllExtensions
message
;
TestUtil
::
ReflectionTester
reflection_tester
(
unittest
::
TestAllExtensions
::
descriptor
());
TestUtil
::
SetAllExtensions
(
&
message
);
reflection_tester
.
RemoveLastRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectLastRepeatedExtensionsRemoved
(
message
);
}
TEST
(
GeneratedMessageReflectionTest
,
SwapRepeatedElements
)
{
unittest
::
TestAllTypes
message
;
TestUtil
::
ReflectionTester
reflection_tester
(
unittest
::
TestAllTypes
::
descriptor
());
TestUtil
::
SetAllFields
(
&
message
);
// Swap and test that fields are all swapped.
reflection_tester
.
SwapRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectRepeatedsSwapped
(
message
);
// Swap back and test that fields are all back to original values.
reflection_tester
.
SwapRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectAllFieldsSet
(
message
);
}
TEST
(
GeneratedMessageReflectionTest
,
SwapRepeatedElementsExtension
)
{
unittest
::
TestAllExtensions
message
;
TestUtil
::
ReflectionTester
reflection_tester
(
unittest
::
TestAllExtensions
::
descriptor
());
TestUtil
::
SetAllExtensions
(
&
message
);
// Swap and test that fields are all swapped.
reflection_tester
.
SwapRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectRepeatedExtensionsSwapped
(
message
);
// Swap back and test that fields are all back to original values.
reflection_tester
.
SwapRepeatedsViaReflection
(
&
message
);
TestUtil
::
ExpectAllExtensionsSet
(
message
);
}
TEST
(
GeneratedMessageReflectionTest
,
Extensions
)
{
TEST
(
GeneratedMessageReflectionTest
,
Extensions
)
{
// Set every extension to a unique value then go back and check all those
// Set every extension to a unique value then go back and check all those
// values.
// values.
...
...
src/google/protobuf/message.h
View file @
ceb561d6
...
@@ -97,7 +97,7 @@
...
@@ -97,7 +97,7 @@
// // Use the reflection interface to examine the contents.
// // Use the reflection interface to examine the contents.
// const Reflection* reflection = foo->GetReflection();
// const Reflection* reflection = foo->GetReflection();
// assert(reflection->GetString(foo, text_field) == "Hello World!");
// assert(reflection->GetString(foo, text_field) == "Hello World!");
// assert(reflection->
CountField
(foo, numbers_field) == 3);
// assert(reflection->
FieldSize
(foo, numbers_field) == 3);
// assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
// assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
// assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
// assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
// assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
// assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
...
@@ -494,6 +494,25 @@ class LIBPROTOBUF_EXPORT Reflection {
...
@@ -494,6 +494,25 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual
void
ClearField
(
Message
*
message
,
virtual
void
ClearField
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
=
0
;
const
FieldDescriptor
*
field
)
const
=
0
;
// Remove the last element of a repeated field.
// We don't provide a way to remove any element other than the last
// because it invites inefficient use, such as O(n^2) filtering loops
// that should have been O(n). If you want to remove an element other
// than the last, the best way to do it is to re-arrange the elements
// (using Swap()) so that the one you want removed is at the end, then
// call RemoveLast().
virtual
void
RemoveLast
(
Message
*
message
,
const
FieldDescriptor
*
field
)
const
=
0
;
// Swap the complete contents of two messages.
virtual
void
Swap
(
Message
*
message1
,
Message
*
message2
)
const
=
0
;
// Swap two elements of a repeated field.
virtual
void
SwapElements
(
Message
*
message
,
const
FieldDescriptor
*
field
,
int
index1
,
int
index2
)
const
=
0
;
// List all fields of the message which are currently set. This includes
// List all fields of the message which are currently set. This includes
// extensions. Singular fields will only be listed if HasField(field) would
// extensions. Singular fields will only be listed if HasField(field) would
// return true and repeated fields will only be listed if FieldSize(field)
// return true and repeated fields will only be listed if FieldSize(field)
...
...
src/google/protobuf/repeated_field.h
View file @
ceb561d6
...
@@ -86,6 +86,9 @@ class LIBPROTOBUF_EXPORT GenericRepeatedField {
...
@@ -86,6 +86,9 @@ class LIBPROTOBUF_EXPORT GenericRepeatedField {
virtual
void
*
GenericMutable
(
int
index
)
=
0
;
virtual
void
*
GenericMutable
(
int
index
)
=
0
;
virtual
void
*
GenericAdd
()
=
0
;
virtual
void
*
GenericAdd
()
=
0
;
virtual
void
GenericClear
()
=
0
;
virtual
void
GenericClear
()
=
0
;
virtual
void
GenericRemoveLast
()
=
0
;
virtual
void
GenericSwap
(
GenericRepeatedField
*
other
)
=
0
;
virtual
void
GenericSwapElements
(
int
index1
,
int
index2
)
=
0
;
virtual
int
GenericSize
()
const
=
0
;
virtual
int
GenericSize
()
const
=
0
;
virtual
int
GenericSpaceUsedExcludingSelf
()
const
=
0
;
virtual
int
GenericSpaceUsedExcludingSelf
()
const
=
0
;
...
@@ -135,6 +138,9 @@ class RepeatedField : public internal::GenericRepeatedField {
...
@@ -135,6 +138,9 @@ class RepeatedField : public internal::GenericRepeatedField {
// Swap entire contents with "other".
// Swap entire contents with "other".
void
Swap
(
RepeatedField
*
other
);
void
Swap
(
RepeatedField
*
other
);
// Swap two elements of a repeated field.
void
SwapElements
(
int
index1
,
int
index2
);
// STL-like iterator support
// STL-like iterator support
typedef
Element
*
iterator
;
typedef
Element
*
iterator
;
typedef
const
Element
*
const_iterator
;
typedef
const
Element
*
const_iterator
;
...
@@ -154,6 +160,9 @@ class RepeatedField : public internal::GenericRepeatedField {
...
@@ -154,6 +160,9 @@ class RepeatedField : public internal::GenericRepeatedField {
void
*
GenericMutable
(
int
index
);
void
*
GenericMutable
(
int
index
);
void
*
GenericAdd
();
void
*
GenericAdd
();
void
GenericClear
();
void
GenericClear
();
void
GenericRemoveLast
();
void
GenericSwap
(
GenericRepeatedField
*
other
);
void
GenericSwapElements
(
int
index1
,
int
index2
);
int
GenericSize
()
const
;
int
GenericSize
()
const
;
int
GenericSpaceUsedExcludingSelf
()
const
;
int
GenericSpaceUsedExcludingSelf
()
const
;
...
@@ -214,6 +223,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
...
@@ -214,6 +223,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
// Swap entire contents with "other".
// Swap entire contents with "other".
void
Swap
(
RepeatedPtrField
*
other
);
void
Swap
(
RepeatedPtrField
*
other
);
// Swap two elements of a repeated field.
void
SwapElements
(
int
index1
,
int
index2
);
// STL-like iterator support
// STL-like iterator support
typedef
internal
::
RepeatedPtrIterator
<
Element
**>
iterator
;
typedef
internal
::
RepeatedPtrIterator
<
Element
**>
iterator
;
typedef
internal
::
RepeatedPtrIterator
<
const
Element
*
const
*>
const_iterator
;
typedef
internal
::
RepeatedPtrIterator
<
const
Element
*
const
*>
const_iterator
;
...
@@ -266,6 +278,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
...
@@ -266,6 +278,9 @@ class RepeatedPtrField : public internal::GenericRepeatedField {
void
*
GenericMutable
(
int
index
);
void
*
GenericMutable
(
int
index
);
void
*
GenericAdd
();
void
*
GenericAdd
();
void
GenericClear
();
void
GenericClear
();
void
GenericRemoveLast
();
void
GenericSwap
(
GenericRepeatedField
*
other
);
void
GenericSwapElements
(
int
index1
,
int
index2
);
int
GenericSize
()
const
;
int
GenericSize
()
const
;
int
GenericSpaceUsedExcludingSelf
()
const
;
int
GenericSpaceUsedExcludingSelf
()
const
;
...
@@ -395,6 +410,11 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
...
@@ -395,6 +410,11 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
}
}
}
}
template
<
typename
Element
>
void
RepeatedField
<
Element
>::
SwapElements
(
int
index1
,
int
index2
)
{
swap
(
*
Mutable
(
index1
),
*
Mutable
(
index2
));
}
template
<
typename
Element
>
template
<
typename
Element
>
inline
typename
RepeatedField
<
Element
>::
iterator
inline
typename
RepeatedField
<
Element
>::
iterator
RepeatedField
<
Element
>::
begin
()
{
RepeatedField
<
Element
>::
begin
()
{
...
@@ -443,6 +463,21 @@ void RepeatedField<Element>::GenericClear() {
...
@@ -443,6 +463,21 @@ void RepeatedField<Element>::GenericClear() {
Clear
();
Clear
();
}
}
template
<
typename
Element
>
void
RepeatedField
<
Element
>::
GenericRemoveLast
()
{
RemoveLast
();
}
template
<
typename
Element
>
void
RepeatedField
<
Element
>::
GenericSwap
(
GenericRepeatedField
*
other
)
{
Swap
(
down_cast
<
RepeatedField
<
Element
>*>
(
other
));
}
template
<
typename
Element
>
void
RepeatedField
<
Element
>::
GenericSwapElements
(
int
index1
,
int
index2
)
{
SwapElements
(
index1
,
index2
);
}
template
<
typename
Element
>
template
<
typename
Element
>
int
RepeatedField
<
Element
>::
GenericSize
()
const
{
int
RepeatedField
<
Element
>::
GenericSize
()
const
{
return
size
();
return
size
();
...
@@ -622,6 +657,11 @@ void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
...
@@ -622,6 +657,11 @@ void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
}
}
}
}
template
<
typename
Element
>
void
RepeatedPtrField
<
Element
>::
SwapElements
(
int
index1
,
int
index2
)
{
swap
(
elements_
[
index1
],
elements_
[
index2
]);
}
template
<
typename
Element
>
template
<
typename
Element
>
inline
int
RepeatedPtrField
<
Element
>::
SpaceUsedExcludingSelf
()
const
{
inline
int
RepeatedPtrField
<
Element
>::
SpaceUsedExcludingSelf
()
const
{
int
allocated_bytes
=
int
allocated_bytes
=
...
@@ -707,6 +747,21 @@ void RepeatedPtrField<Element>::GenericClear() {
...
@@ -707,6 +747,21 @@ void RepeatedPtrField<Element>::GenericClear() {
Clear
();
Clear
();
}
}
template
<
typename
Element
>
void
RepeatedPtrField
<
Element
>::
GenericRemoveLast
()
{
RemoveLast
();
}
template
<
typename
Element
>
void
RepeatedPtrField
<
Element
>::
GenericSwap
(
GenericRepeatedField
*
other
)
{
Swap
(
down_cast
<
RepeatedPtrField
<
Element
>*>
(
other
));
}
template
<
typename
Element
>
void
RepeatedPtrField
<
Element
>::
GenericSwapElements
(
int
index1
,
int
index2
)
{
SwapElements
(
index1
,
index2
);
}
template
<
typename
Element
>
template
<
typename
Element
>
int
RepeatedPtrField
<
Element
>::
GenericSize
()
const
{
int
RepeatedPtrField
<
Element
>::
GenericSize
()
const
{
return
size
();
return
size
();
...
@@ -736,7 +791,7 @@ inline Element* RepeatedPtrField<Element>::NewElement() {
...
@@ -736,7 +791,7 @@ inline Element* RepeatedPtrField<Element>::NewElement() {
return
new
Element
;
return
new
Element
;
}
}
// RepeatedPtrField<Message> is alowed but requires a prototype since Message
// RepeatedPtrField<Message> is al
l
owed but requires a prototype since Message
// is abstract.
// is abstract.
template
<>
template
<>
inline
Message
*
RepeatedPtrField
<
Message
>::
NewElement
()
{
inline
Message
*
RepeatedPtrField
<
Message
>::
NewElement
()
{
...
...
src/google/protobuf/test_util.cc
View file @
ceb561d6
This diff is collapsed.
Click to expand it.
src/google/protobuf/test_util.h
View file @
ceb561d6
...
@@ -96,6 +96,17 @@ class TestUtil {
...
@@ -96,6 +96,17 @@ class TestUtil {
// SetAllFieldsAndExtensions().
// SetAllFieldsAndExtensions().
static
void
ExpectAllFieldsAndExtensionsInOrder
(
const
string
&
serialized
);
static
void
ExpectAllFieldsAndExtensionsInOrder
(
const
string
&
serialized
);
// Check that all repeated fields have had their last elements removed.
static
void
ExpectLastRepeatedsRemoved
(
const
unittest
::
TestAllTypes
&
message
);
static
void
ExpectLastRepeatedExtensionsRemoved
(
const
unittest
::
TestAllExtensions
&
message
);
// Check that all repeated fields have had their first and last elements swapped.
static
void
ExpectRepeatedsSwapped
(
const
unittest
::
TestAllTypes
&
message
);
static
void
ExpectRepeatedExtensionsSwapped
(
const
unittest
::
TestAllExtensions
&
message
);
// Like above, but use the reflection interface.
// Like above, but use the reflection interface.
class
ReflectionTester
{
class
ReflectionTester
{
public
:
public
:
...
@@ -116,6 +127,9 @@ class TestUtil {
...
@@ -116,6 +127,9 @@ class TestUtil {
void
ExpectPackedFieldsSetViaReflection
(
const
Message
&
message
);
void
ExpectPackedFieldsSetViaReflection
(
const
Message
&
message
);
void
ExpectPackedClearViaReflection
(
const
Message
&
message
);
void
ExpectPackedClearViaReflection
(
const
Message
&
message
);
void
RemoveLastRepeatedsViaReflection
(
Message
*
message
);
void
SwapRepeatedsViaReflection
(
Message
*
message
);
private
:
private
:
const
FieldDescriptor
*
F
(
const
string
&
name
);
const
FieldDescriptor
*
F
(
const
string
&
name
);
...
...
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