|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
|
|
|
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
|
|
|
|
|
|
#include <google/protobuf/stubs/atomicops.h>
|
|
|
#include <google/protobuf/stubs/mutex.h>
|
|
|
#include <google/protobuf/stubs/common.h>
|
|
|
#include <google/protobuf/generated_message_reflection.h>
|
|
|
#include <google/protobuf/arena.h>
|
|
|
#include <google/protobuf/descriptor.h>
|
|
|
#include <google/protobuf/map_entry.h>
|
|
|
#include <google/protobuf/map_field_lite.h>
|
|
|
#include <google/protobuf/map_type_handler.h>
|
|
|
#include <google/protobuf/message.h>
|
|
|
#include <google/protobuf/repeated_field.h>
|
|
|
#include <google/protobuf/unknown_field_set.h>
|
|
|
|
|
|
|
|
|
namespace google {
|
|
|
namespace protobuf {
|
|
|
class DynamicMessage;
|
|
|
class MapKey;
|
|
|
namespace internal {
|
|
|
|
|
|
class ContendedMapCleanTest;
|
|
|
class GeneratedMessageReflection;
|
|
|
class MapFieldAccessor;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LIBPROTOBUF_EXPORT MapFieldBase {
|
|
|
public:
|
|
|
MapFieldBase()
|
|
|
: arena_(NULL),
|
|
|
repeated_field_(NULL),
|
|
|
state_(STATE_MODIFIED_MAP) {}
|
|
|
explicit MapFieldBase(Arena* arena)
|
|
|
: arena_(arena),
|
|
|
repeated_field_(NULL),
|
|
|
state_(STATE_MODIFIED_MAP) {
|
|
|
|
|
|
|
|
|
arena->OwnDestructor(&mutex_);
|
|
|
}
|
|
|
virtual ~MapFieldBase();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const RepeatedPtrFieldBase& GetRepeatedField() const;
|
|
|
|
|
|
|
|
|
RepeatedPtrFieldBase* MutableRepeatedField();
|
|
|
|
|
|
|
|
|
virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
|
|
|
virtual bool InsertOrLookupMapValue(
|
|
|
const MapKey& map_key, MapValueRef* val) = 0;
|
|
|
|
|
|
bool IsMapValid() const;
|
|
|
virtual bool DeleteMapValue(const MapKey& map_key) = 0;
|
|
|
virtual bool EqualIterator(const MapIterator& a,
|
|
|
const MapIterator& b) const = 0;
|
|
|
virtual void MapBegin(MapIterator* map_iter) const = 0;
|
|
|
virtual void MapEnd(MapIterator* map_iter) const = 0;
|
|
|
|
|
|
virtual int size() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
size_t SpaceUsedExcludingSelfLong() const;
|
|
|
|
|
|
int SpaceUsedExcludingSelf() const {
|
|
|
return internal::ToIntSize(SpaceUsedExcludingSelfLong());
|
|
|
}
|
|
|
|
|
|
protected:
|
|
|
|
|
|
virtual size_t SpaceUsedExcludingSelfNoLock() const;
|
|
|
|
|
|
|
|
|
|
|
|
void SyncRepeatedFieldWithMap() const;
|
|
|
virtual void SyncRepeatedFieldWithMapNoLock() const;
|
|
|
|
|
|
|
|
|
|
|
|
void SyncMapWithRepeatedField() const;
|
|
|
virtual void SyncMapWithRepeatedFieldNoLock() const {}
|
|
|
|
|
|
|
|
|
void SetMapDirty();
|
|
|
|
|
|
|
|
|
void SetRepeatedDirty();
|
|
|
|
|
|
|
|
|
void* MutableRepeatedPtrField() const;
|
|
|
|
|
|
enum State {
|
|
|
STATE_MODIFIED_MAP = 0,
|
|
|
|
|
|
STATE_MODIFIED_REPEATED = 1,
|
|
|
|
|
|
CLEAN = 2,
|
|
|
};
|
|
|
|
|
|
Arena* arena_;
|
|
|
mutable RepeatedPtrField<Message>* repeated_field_;
|
|
|
|
|
|
mutable Mutex mutex_;
|
|
|
|
|
|
mutable volatile Atomic32 state_;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
friend class ContendedMapCleanTest;
|
|
|
friend class GeneratedMessageReflection;
|
|
|
friend class MapFieldAccessor;
|
|
|
friend class ::google::protobuf::DynamicMessage;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
friend class ::google::protobuf::MapIterator;
|
|
|
|
|
|
virtual void InitializeIterator(MapIterator* map_iter) const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void DeleteIterator(MapIterator* map_iter) const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void CopyIterator(MapIterator* this_iterator,
|
|
|
const MapIterator& other_iterator) const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
|
|
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase);
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<typename Key, typename T>
|
|
|
class TypeDefinedMapFieldBase : public MapFieldBase {
|
|
|
public:
|
|
|
TypeDefinedMapFieldBase() {}
|
|
|
explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
|
|
|
~TypeDefinedMapFieldBase() {}
|
|
|
void MapBegin(MapIterator* map_iter) const;
|
|
|
void MapEnd(MapIterator* map_iter) const;
|
|
|
bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
|
|
|
|
|
|
virtual const Map<Key, T>& GetMap() const = 0;
|
|
|
virtual Map<Key, T>* MutableMap() = 0;
|
|
|
|
|
|
protected:
|
|
|
typename Map<Key, T>::const_iterator& InternalGetIterator(
|
|
|
const MapIterator* map_iter) const;
|
|
|
|
|
|
private:
|
|
|
void InitializeIterator(MapIterator* map_iter) const;
|
|
|
void DeleteIterator(MapIterator* map_iter) const;
|
|
|
void CopyIterator(MapIterator* this_iteratorm,
|
|
|
const MapIterator& that_iterator) const;
|
|
|
void IncreaseIterator(MapIterator* map_iter) const;
|
|
|
|
|
|
virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
|
|
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase);
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Derived, typename Key, typename T,
|
|
|
WireFormatLite::FieldType kKeyFieldType,
|
|
|
WireFormatLite::FieldType kValueFieldType, int default_enum_value = 0>
|
|
|
class MapField : public TypeDefinedMapFieldBase<Key, T> {
|
|
|
|
|
|
|
|
|
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
|
|
typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
|
|
|
|
|
|
|
|
|
typedef Derived EntryType;
|
|
|
typedef MapEntryLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
|
|
default_enum_value>
|
|
|
EntryLiteType;
|
|
|
|
|
|
|
|
|
typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
|
|
default_enum_value>
|
|
|
MapFieldLiteType;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
|
|
|
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
|
|
|
|
|
|
public:
|
|
|
typedef typename Derived::SuperType EntryTypeTrait;
|
|
|
typedef Map<Key, T> MapType;
|
|
|
|
|
|
MapField() {}
|
|
|
explicit MapField(Arena* arena)
|
|
|
: TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
|
|
|
|
|
|
|
|
|
bool ContainsMapKey(const MapKey& map_key) const;
|
|
|
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
|
|
|
bool DeleteMapValue(const MapKey& map_key);
|
|
|
|
|
|
const Map<Key, T>& GetMap() const {
|
|
|
MapFieldBase::SyncMapWithRepeatedField();
|
|
|
return impl_.GetMap();
|
|
|
}
|
|
|
|
|
|
Map<Key, T>* MutableMap() {
|
|
|
MapFieldBase::SyncMapWithRepeatedField();
|
|
|
Map<Key, T>* result = impl_.MutableMap();
|
|
|
MapFieldBase::SetMapDirty();
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
|
|
|
int size() const;
|
|
|
void Clear();
|
|
|
void MergeFrom(const MapField& other);
|
|
|
void Swap(MapField* other);
|
|
|
|
|
|
|
|
|
|
|
|
EntryType* NewEntry() const { return impl_.NewEntry(); }
|
|
|
|
|
|
|
|
|
EntryType* NewEnumEntryWrapper(const Key& key, const T t) const {
|
|
|
return impl_.NewEnumEntryWrapper(key, t);
|
|
|
}
|
|
|
|
|
|
|
|
|
EntryType* NewEntryWrapper(const Key& key, const T& t) const {
|
|
|
return impl_.NewEntryWrapper(key, t);
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
MapFieldLiteType impl_;
|
|
|
|
|
|
typedef void InternalArenaConstructable_;
|
|
|
typedef void DestructorSkippable_;
|
|
|
|
|
|
|
|
|
void SyncRepeatedFieldWithMapNoLock() const;
|
|
|
void SyncMapWithRepeatedFieldNoLock() const;
|
|
|
size_t SpaceUsedExcludingSelfNoLock() const;
|
|
|
|
|
|
void SetMapIteratorValue(MapIterator* map_iter) const;
|
|
|
|
|
|
friend class ::google::protobuf::Arena;
|
|
|
friend class MapFieldStateTest;
|
|
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField);
|
|
|
};
|
|
|
|
|
|
template <typename T, typename Key, typename Value,
|
|
|
WireFormatLite::FieldType kKeyFieldType,
|
|
|
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
|
|
struct MapEntryToMapField<MapEntry<T, Key, Value, kKeyFieldType,
|
|
|
kValueFieldType, default_enum_value> > {
|
|
|
typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType,
|
|
|
default_enum_value>
|
|
|
MapFieldType;
|
|
|
};
|
|
|
|
|
|
class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
|
|
|
public:
|
|
|
explicit DynamicMapField(const Message* default_entry);
|
|
|
DynamicMapField(const Message* default_entry, Arena* arena);
|
|
|
~DynamicMapField();
|
|
|
|
|
|
|
|
|
bool ContainsMapKey(const MapKey& map_key) const;
|
|
|
bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
|
|
|
bool DeleteMapValue(const MapKey& map_key);
|
|
|
|
|
|
const Map<MapKey, MapValueRef>& GetMap() const;
|
|
|
Map<MapKey, MapValueRef>* MutableMap();
|
|
|
|
|
|
int size() const;
|
|
|
|
|
|
private:
|
|
|
Map<MapKey, MapValueRef> map_;
|
|
|
const Message* default_entry_;
|
|
|
|
|
|
|
|
|
void SyncRepeatedFieldWithMapNoLock() const;
|
|
|
void SyncMapWithRepeatedFieldNoLock() const;
|
|
|
size_t SpaceUsedExcludingSelfNoLock() const;
|
|
|
void SetMapIteratorValue(MapIterator* map_iter) const;
|
|
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField);
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
|
|
|
if (type() != EXPECTEDTYPE) { \
|
|
|
GOOGLE_LOG(FATAL) \
|
|
|
<< "Protocol Buffer map usage error:\n" \
|
|
|
<< METHOD << " type does not match\n" \
|
|
|
<< " Expected : " \
|
|
|
<< FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
|
|
|
<< " Actual : " \
|
|
|
<< FieldDescriptor::CppTypeName(type()); \
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class LIBPROTOBUF_EXPORT MapKey {
|
|
|
public:
|
|
|
MapKey() : type_(0) {
|
|
|
}
|
|
|
MapKey(const MapKey& other) : type_(0) {
|
|
|
CopyFrom(other);
|
|
|
}
|
|
|
MapKey& operator=(const MapKey& other) {
|
|
|
CopyFrom(other);
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
~MapKey() {
|
|
|
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
|
|
delete val_.string_value_;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
FieldDescriptor::CppType type() const {
|
|
|
if (type_ == 0) {
|
|
|
GOOGLE_LOG(FATAL)
|
|
|
<< "Protocol Buffer map usage error:\n"
|
|
|
<< "MapKey::type MapKey is not initialized. "
|
|
|
<< "Call set methods to initialize MapKey.";
|
|
|
}
|
|
|
return (FieldDescriptor::CppType)type_;
|
|
|
}
|
|
|
|
|
|
void SetInt64Value(int64 value) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_INT64);
|
|
|
val_.int64_value_ = value;
|
|
|
}
|
|
|
void SetUInt64Value(uint64 value) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_UINT64);
|
|
|
val_.uint64_value_ = value;
|
|
|
}
|
|
|
void SetInt32Value(int32 value) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_INT32);
|
|
|
val_.int32_value_ = value;
|
|
|
}
|
|
|
void SetUInt32Value(uint32 value) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_UINT32);
|
|
|
val_.uint32_value_ = value;
|
|
|
}
|
|
|
void SetBoolValue(bool value) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_BOOL);
|
|
|
val_.bool_value_ = value;
|
|
|
}
|
|
|
void SetStringValue(const string& val) {
|
|
|
SetType(FieldDescriptor::CPPTYPE_STRING);
|
|
|
*val_.string_value_ = val;
|
|
|
}
|
|
|
|
|
|
int64 GetInt64Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
|
|
|
"MapKey::GetInt64Value");
|
|
|
return val_.int64_value_;
|
|
|
}
|
|
|
uint64 GetUInt64Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
|
|
|
"MapKey::GetUInt64Value");
|
|
|
return val_.uint64_value_;
|
|
|
}
|
|
|
int32 GetInt32Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
|
|
|
"MapKey::GetInt32Value");
|
|
|
return val_.int32_value_;
|
|
|
}
|
|
|
uint32 GetUInt32Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
|
|
|
"MapKey::GetUInt32Value");
|
|
|
return val_.uint32_value_;
|
|
|
}
|
|
|
bool GetBoolValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
|
|
|
"MapKey::GetBoolValue");
|
|
|
return val_.bool_value_;
|
|
|
}
|
|
|
const string& GetStringValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
|
|
|
"MapKey::GetStringValue");
|
|
|
return *val_.string_value_;
|
|
|
}
|
|
|
|
|
|
bool operator<(const MapKey& other) const {
|
|
|
if (type_ != other.type_) {
|
|
|
|
|
|
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
|
|
}
|
|
|
switch (type()) {
|
|
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
|
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
case FieldDescriptor::CPPTYPE_ENUM:
|
|
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported";
|
|
|
return false;
|
|
|
case FieldDescriptor::CPPTYPE_STRING:
|
|
|
return *val_.string_value_ < *other.val_.string_value_;
|
|
|
case FieldDescriptor::CPPTYPE_INT64:
|
|
|
return val_.int64_value_ < other.val_.int64_value_;
|
|
|
case FieldDescriptor::CPPTYPE_INT32:
|
|
|
return val_.int32_value_ < other.val_.int32_value_;
|
|
|
case FieldDescriptor::CPPTYPE_UINT64:
|
|
|
return val_.uint64_value_ < other.val_.uint64_value_;
|
|
|
case FieldDescriptor::CPPTYPE_UINT32:
|
|
|
return val_.uint32_value_ < other.val_.uint32_value_;
|
|
|
case FieldDescriptor::CPPTYPE_BOOL:
|
|
|
return val_.bool_value_ < other.val_.bool_value_;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool operator==(const MapKey& other) const {
|
|
|
if (type_ != other.type_) {
|
|
|
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
|
|
|
}
|
|
|
switch (type()) {
|
|
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
|
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
case FieldDescriptor::CPPTYPE_ENUM:
|
|
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported";
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_STRING:
|
|
|
return *val_.string_value_ == *other.val_.string_value_;
|
|
|
case FieldDescriptor::CPPTYPE_INT64:
|
|
|
return val_.int64_value_ == other.val_.int64_value_;
|
|
|
case FieldDescriptor::CPPTYPE_INT32:
|
|
|
return val_.int32_value_ == other.val_.int32_value_;
|
|
|
case FieldDescriptor::CPPTYPE_UINT64:
|
|
|
return val_.uint64_value_ == other.val_.uint64_value_;
|
|
|
case FieldDescriptor::CPPTYPE_UINT32:
|
|
|
return val_.uint32_value_ == other.val_.uint32_value_;
|
|
|
case FieldDescriptor::CPPTYPE_BOOL:
|
|
|
return val_.bool_value_ == other.val_.bool_value_;
|
|
|
}
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
void CopyFrom(const MapKey& other) {
|
|
|
SetType(other.type());
|
|
|
switch (type_) {
|
|
|
case FieldDescriptor::CPPTYPE_DOUBLE:
|
|
|
case FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
case FieldDescriptor::CPPTYPE_ENUM:
|
|
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported";
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_STRING:
|
|
|
*val_.string_value_ = *other.val_.string_value_;
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_INT64:
|
|
|
val_.int64_value_ = other.val_.int64_value_;
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_INT32:
|
|
|
val_.int32_value_ = other.val_.int32_value_;
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_UINT64:
|
|
|
val_.uint64_value_ = other.val_.uint64_value_;
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_UINT32:
|
|
|
val_.uint32_value_ = other.val_.uint32_value_;
|
|
|
break;
|
|
|
case FieldDescriptor::CPPTYPE_BOOL:
|
|
|
val_.bool_value_ = other.val_.bool_value_;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
template <typename K, typename V>
|
|
|
friend class internal::TypeDefinedMapFieldBase;
|
|
|
friend class MapIterator;
|
|
|
friend class internal::DynamicMapField;
|
|
|
|
|
|
union KeyValue {
|
|
|
KeyValue() {}
|
|
|
string* string_value_;
|
|
|
int64 int64_value_;
|
|
|
int32 int32_value_;
|
|
|
uint64 uint64_value_;
|
|
|
uint32 uint32_value_;
|
|
|
bool bool_value_;
|
|
|
} val_;
|
|
|
|
|
|
void SetType(FieldDescriptor::CppType type) {
|
|
|
if (type_ == type) return;
|
|
|
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
|
|
delete val_.string_value_;
|
|
|
}
|
|
|
type_ = type;
|
|
|
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
|
|
|
val_.string_value_ = new string;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
int type_;
|
|
|
};
|
|
|
|
|
|
|
|
|
class LIBPROTOBUF_EXPORT MapValueRef {
|
|
|
public:
|
|
|
MapValueRef() : data_(NULL), type_(0) {}
|
|
|
|
|
|
void SetInt64Value(int64 value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
|
|
|
"MapValueRef::SetInt64Value");
|
|
|
*reinterpret_cast<int64*>(data_) = value;
|
|
|
}
|
|
|
void SetUInt64Value(uint64 value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
|
|
|
"MapValueRef::SetUInt64Value");
|
|
|
*reinterpret_cast<uint64*>(data_) = value;
|
|
|
}
|
|
|
void SetInt32Value(int32 value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
|
|
|
"MapValueRef::SetInt32Value");
|
|
|
*reinterpret_cast<int32*>(data_) = value;
|
|
|
}
|
|
|
void SetUInt32Value(uint32 value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
|
|
|
"MapValueRef::SetUInt32Value");
|
|
|
*reinterpret_cast<uint32*>(data_) = value;
|
|
|
}
|
|
|
void SetBoolValue(bool value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
|
|
|
"MapValueRef::SetBoolValue");
|
|
|
*reinterpret_cast<bool*>(data_) = value;
|
|
|
}
|
|
|
|
|
|
void SetEnumValue(int value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
|
|
|
"MapValueRef::SetEnumValue");
|
|
|
*reinterpret_cast<int*>(data_) = value;
|
|
|
}
|
|
|
void SetStringValue(const string& value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
|
|
|
"MapValueRef::SetStringValue");
|
|
|
*reinterpret_cast<string*>(data_) = value;
|
|
|
}
|
|
|
void SetFloatValue(float value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
|
|
|
"MapValueRef::SetFloatValue");
|
|
|
*reinterpret_cast<float*>(data_) = value;
|
|
|
}
|
|
|
void SetDoubleValue(double value) {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
|
|
|
"MapValueRef::SetDoubleValue");
|
|
|
*reinterpret_cast<double*>(data_) = value;
|
|
|
}
|
|
|
|
|
|
int64 GetInt64Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
|
|
|
"MapValueRef::GetInt64Value");
|
|
|
return *reinterpret_cast<int64*>(data_);
|
|
|
}
|
|
|
uint64 GetUInt64Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
|
|
|
"MapValueRef::GetUInt64Value");
|
|
|
return *reinterpret_cast<uint64*>(data_);
|
|
|
}
|
|
|
int32 GetInt32Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
|
|
|
"MapValueRef::GetInt32Value");
|
|
|
return *reinterpret_cast<int32*>(data_);
|
|
|
}
|
|
|
uint32 GetUInt32Value() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
|
|
|
"MapValueRef::GetUInt32Value");
|
|
|
return *reinterpret_cast<uint32*>(data_);
|
|
|
}
|
|
|
bool GetBoolValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
|
|
|
"MapValueRef::GetBoolValue");
|
|
|
return *reinterpret_cast<bool*>(data_);
|
|
|
}
|
|
|
int GetEnumValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
|
|
|
"MapValueRef::GetEnumValue");
|
|
|
return *reinterpret_cast<int*>(data_);
|
|
|
}
|
|
|
const string& GetStringValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
|
|
|
"MapValueRef::GetStringValue");
|
|
|
return *reinterpret_cast<string*>(data_);
|
|
|
}
|
|
|
float GetFloatValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
|
|
|
"MapValueRef::GetFloatValue");
|
|
|
return *reinterpret_cast<float*>(data_);
|
|
|
}
|
|
|
double GetDoubleValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
|
|
|
"MapValueRef::GetDoubleValue");
|
|
|
return *reinterpret_cast<double*>(data_);
|
|
|
}
|
|
|
|
|
|
const Message& GetMessageValue() const {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
|
|
"MapValueRef::GetMessageValue");
|
|
|
return *reinterpret_cast<Message*>(data_);
|
|
|
}
|
|
|
|
|
|
Message* MutableMessageValue() {
|
|
|
TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
|
|
|
"MapValueRef::MutableMessageValue");
|
|
|
return reinterpret_cast<Message*>(data_);
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
template <typename Derived, typename K, typename V,
|
|
|
internal::WireFormatLite::FieldType key_wire_type,
|
|
|
internal::WireFormatLite::FieldType value_wire_type,
|
|
|
int default_enum_value>
|
|
|
friend class internal::MapField;
|
|
|
template <typename K, typename V>
|
|
|
friend class internal::TypeDefinedMapFieldBase;
|
|
|
friend class MapIterator;
|
|
|
friend class internal::GeneratedMessageReflection;
|
|
|
friend class internal::DynamicMapField;
|
|
|
|
|
|
void SetType(FieldDescriptor::CppType type) {
|
|
|
type_ = type;
|
|
|
}
|
|
|
|
|
|
FieldDescriptor::CppType type() const {
|
|
|
if (type_ == 0 || data_ == NULL) {
|
|
|
GOOGLE_LOG(FATAL)
|
|
|
<< "Protocol Buffer map usage error:\n"
|
|
|
<< "MapValueRef::type MapValueRef is not initialized.";
|
|
|
}
|
|
|
return (FieldDescriptor::CppType)type_;
|
|
|
}
|
|
|
void SetValue(const void* val) {
|
|
|
data_ = const_cast<void*>(val);
|
|
|
}
|
|
|
void CopyFrom(const MapValueRef& other) {
|
|
|
type_ = other.type_;
|
|
|
data_ = other.data_;
|
|
|
}
|
|
|
|
|
|
void DeleteData() {
|
|
|
switch (type_) {
|
|
|
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
|
|
|
delete reinterpret_cast<TYPE*>(data_); \
|
|
|
break; \
|
|
|
}
|
|
|
HANDLE_TYPE(INT32, int32);
|
|
|
HANDLE_TYPE(INT64, int64);
|
|
|
HANDLE_TYPE(UINT32, uint32);
|
|
|
HANDLE_TYPE(UINT64, uint64);
|
|
|
HANDLE_TYPE(DOUBLE, double);
|
|
|
HANDLE_TYPE(FLOAT, float);
|
|
|
HANDLE_TYPE(BOOL, bool);
|
|
|
HANDLE_TYPE(STRING, string);
|
|
|
HANDLE_TYPE(ENUM, int32);
|
|
|
HANDLE_TYPE(MESSAGE, Message);
|
|
|
#undef HANDLE_TYPE
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void* data_;
|
|
|
|
|
|
int type_;
|
|
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapValueRef);
|
|
|
};
|
|
|
|
|
|
#undef TYPE_CHECK
|
|
|
|
|
|
class LIBPROTOBUF_EXPORT MapIterator {
|
|
|
public:
|
|
|
MapIterator(Message* message, const FieldDescriptor* field) {
|
|
|
const Reflection* reflection = message->GetReflection();
|
|
|
map_ = reflection->MapData(message, field);
|
|
|
key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
|
|
|
value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
|
|
|
map_->InitializeIterator(this);
|
|
|
}
|
|
|
MapIterator(const MapIterator& other) {
|
|
|
map_ = other.map_;
|
|
|
map_->InitializeIterator(this);
|
|
|
map_->CopyIterator(this, other);
|
|
|
}
|
|
|
~MapIterator() {
|
|
|
map_->DeleteIterator(this);
|
|
|
}
|
|
|
MapIterator& operator=(const MapIterator& other) {
|
|
|
map_ = other.map_;
|
|
|
map_->CopyIterator(this, other);
|
|
|
return *this;
|
|
|
}
|
|
|
friend bool operator==(const MapIterator& a, const MapIterator& b) {
|
|
|
return a.map_->EqualIterator(a, b);
|
|
|
}
|
|
|
friend bool operator!=(const MapIterator& a, const MapIterator& b) {
|
|
|
return !a.map_->EqualIterator(a, b);
|
|
|
}
|
|
|
MapIterator& operator++() {
|
|
|
map_->IncreaseIterator(this);
|
|
|
return *this;
|
|
|
}
|
|
|
MapIterator operator++(int) {
|
|
|
|
|
|
|
|
|
|
|
|
map_->IncreaseIterator(this);
|
|
|
return *this;
|
|
|
}
|
|
|
const MapKey& GetKey() {
|
|
|
return key_;
|
|
|
}
|
|
|
const MapValueRef& GetValueRef() {
|
|
|
return value_;
|
|
|
}
|
|
|
MapValueRef* MutableValueRef() {
|
|
|
map_->SetMapDirty();
|
|
|
return &value_;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
template <typename Key, typename T>
|
|
|
friend class internal::TypeDefinedMapFieldBase;
|
|
|
friend class internal::DynamicMapField;
|
|
|
template <typename Derived, typename Key, typename T,
|
|
|
internal::WireFormatLite::FieldType kKeyFieldType,
|
|
|
internal::WireFormatLite::FieldType kValueFieldType,
|
|
|
int default_enum_value>
|
|
|
friend class internal::MapField;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void* iter_;
|
|
|
|
|
|
|
|
|
internal::MapFieldBase* map_;
|
|
|
MapKey key_;
|
|
|
MapValueRef value_;
|
|
|
};
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
|
|
|
template<>
|
|
|
struct hash<google::protobuf::MapKey> {
|
|
|
size_t
|
|
|
operator()(const google::protobuf::MapKey& map_key) const {
|
|
|
switch (map_key.type()) {
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
|
|
|
GOOGLE_LOG(FATAL) << "Unsupported";
|
|
|
break;
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
|
|
|
return hash<string>()(map_key.GetStringValue());
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
|
return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
|
|
|
return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
|
return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
|
|
|
return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
|
|
|
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
|
|
|
return hash<bool>()(map_key.GetBoolValue());
|
|
|
}
|
|
|
GOOGLE_LOG(FATAL) << "Can't get here.";
|
|
|
return 0;
|
|
|
}
|
|
|
bool
|
|
|
operator()(const google::protobuf::MapKey& map_key1,
|
|
|
const google::protobuf::MapKey& map_key2) const {
|
|
|
return map_key1 < map_key2;
|
|
|
}
|
|
|
};
|
|
|
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
|
|
|
|
|
|
#endif
|
|
|
|