aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/dynamic_message.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/dynamic_message.h')
-rw-r--r--src/google/protobuf/dynamic_message.h86
1 files changed, 85 insertions, 1 deletions
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 7ff80f26..816170ea 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -38,12 +38,15 @@
#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
+#include <algorithm>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <vector>
#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/mutex.h>
@@ -141,11 +144,92 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// Delete default oneof instance. Called by ~DynamicMessageFactory.
static void DeleteDefaultOneofInstance(const Descriptor* type,
const uint32 offsets[],
- void* default_oneof_instance);
+ const void* default_oneof_instance);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
};
+// Helper for computing a sorted list of map entries via reflection.
+class LIBPROTOBUF_EXPORT DynamicMapSorter {
+ public:
+ static std::vector<const Message*> Sort(const Message& message,
+ int map_size,
+ const Reflection* reflection,
+ const FieldDescriptor* field) {
+ std::vector<const Message*> result(map_size);
+ const RepeatedPtrField<Message>& map_field =
+ reflection->GetRepeatedPtrField<Message>(message, field);
+ int i = 0;
+ for (RepeatedPtrField<Message>::const_pointer_iterator it =
+ map_field.pointer_begin(); it != map_field.pointer_end(); ) {
+ result[i++] = *it++;
+ }
+ GOOGLE_DCHECK_EQ(result.size(), static_cast<size_t>(i));
+ MapEntryMessageComparator comparator(field->message_type());
+ std::sort(result.begin(), result.end(), comparator);
+ // Complain if the keys aren't in ascending order.
+#ifndef NDEBUG
+ for (int j = 1; j < map_size; j++) {
+ if (!comparator(result[j - 1], result[j])) {
+ GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) ?
+ "internal error in map key sorting" :
+ "map keys are not unique");
+ }
+ }
+#endif
+ return result;
+ }
+
+ private:
+ class LIBPROTOBUF_EXPORT MapEntryMessageComparator {
+ public:
+ explicit MapEntryMessageComparator(const Descriptor* descriptor)
+ : field_(descriptor->field(0)) {}
+
+ bool operator()(const Message* a, const Message* b) {
+ const Reflection* reflection = a->GetReflection();
+ switch (field_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL: {
+ bool first = reflection->GetBool(*a, field_);
+ bool second = reflection->GetBool(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT32: {
+ int32 first = reflection->GetInt32(*a, field_);
+ int32 second = reflection->GetInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT64: {
+ int64 first = reflection->GetInt64(*a, field_);
+ int64 second = reflection->GetInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT32: {
+ uint32 first = reflection->GetUInt32(*a, field_);
+ uint32 second = reflection->GetUInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT64: {
+ uint64 first = reflection->GetUInt64(*a, field_);
+ uint64 second = reflection->GetUInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_STRING: {
+ string first = reflection->GetString(*a, field_);
+ string second = reflection->GetString(*b, field_);
+ return first < second;
+ }
+ default:
+ GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
+ return true;
+ }
+ }
+
+ private:
+ const FieldDescriptor* field_;
+ };
+};
+
} // namespace protobuf
} // namespace google