aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/map_entry_lite.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/map_entry_lite.h')
-rw-r--r--src/google/protobuf/map_entry_lite.h145
1 files changed, 94 insertions, 51 deletions
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 85a0bed7..98b2acae 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -32,15 +32,26 @@
#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
#include <assert.h>
+#include <string>
#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/map.h>
#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/port.h>
+#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/port_def.inc>
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+#include <google/protobuf/parse_context.h>
+#endif
+
+#ifdef SWIG
+#error "You cannot SWIG proto headers"
+#endif
+
namespace google {
namespace protobuf {
namespace internal {
@@ -54,7 +65,9 @@ template <typename Derived, typename Key, typename Value,
class MapFieldLite;
} // namespace internal
} // namespace protobuf
+} // namespace google
+namespace google {
namespace protobuf {
namespace internal {
@@ -177,13 +190,13 @@ class MapEntryImpl : public Base {
// MapEntryImpl is for implementation only and this function isn't called
// anywhere. Just provide a fake implementation here for MessageLite.
- string GetTypeName() const { return ""; }
+ std::string GetTypeName() const override { return ""; }
- void CheckTypeAndMergeFrom(const MessageLite& other) {
+ void CheckTypeAndMergeFrom(const MessageLite& other) override {
MergeFromInternal(*::google::protobuf::down_cast<const Derived*>(&other));
}
- bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+ bool MergePartialFromCodedStream(io::CodedInputStream* input) override {
uint32 tag;
for (;;) {
@@ -224,7 +237,7 @@ class MapEntryImpl : public Base {
}
}
- size_t ByteSizeLong() const {
+ size_t ByteSizeLong() const override {
size_t size = 0;
size += has_key() ?
kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key())) : 0;
@@ -233,13 +246,13 @@ class MapEntryImpl : public Base {
return size;
}
- void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+ void SerializeWithCachedSizes(io::CodedOutputStream* output) const override {
KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
ValueTypeHandler::Write(kValueFieldNumber, value(), output);
}
- ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool deterministic,
- ::google::protobuf::uint8* output) const {
+ ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+ bool deterministic, ::google::protobuf::uint8* output) const override {
output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(),
deterministic, output);
output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(),
@@ -249,7 +262,7 @@ class MapEntryImpl : public Base {
// Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
- int GetCachedSize() const {
+ int GetCachedSize() const override {
int size = 0;
size += has_key()
? static_cast<int>(kTagSize) + KeyTypeHandler::GetCachedSize(key())
@@ -260,25 +273,20 @@ class MapEntryImpl : public Base {
return size;
}
- bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
+ bool IsInitialized() const override {
+ return ValueTypeHandler::IsInitialized(value_);
+ }
- Base* New() const {
+ Base* New() const override {
Derived* entry = new Derived;
return entry;
}
- Base* New(Arena* arena) const {
+ Base* New(Arena* arena) const override {
Derived* entry = Arena::CreateMessage<Derived>(arena);
return entry;
}
- size_t SpaceUsedLong() const {
- size_t size = sizeof(Derived);
- size += KeyTypeHandler::SpaceUsedInMapEntryLong(key_);
- size += ValueTypeHandler::SpaceUsedInMapEntryLong(value_);
- return size;
- }
-
protected:
// We can't declare this function directly here as it would hide the other
// overload (const Message&).
@@ -298,7 +306,7 @@ class MapEntryImpl : public Base {
}
public:
- void Clear() {
+ void Clear() override {
KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
ValueTypeHandler::ClearMaybeByDefaultEnum(
&value_, GetArenaNoVirtual(), default_enum_value);
@@ -312,20 +320,18 @@ class MapEntryImpl : public Base {
ValueTypeHandler::AssignDefaultValue(&d->value_);
}
- Arena* GetArena() const {
- return GetArenaNoVirtual();
- }
+ Arena* GetArena() const override { return GetArenaNoVirtual(); }
- // Create a MapEntryImpl for given key and value from google::protobuf::Map in
+ // Create a MapEntryImpl for given key and value from Map in
// serialization. This function is only called when value is enum. Enum is
// treated differently because its type in MapEntry is int and its type in
- // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
+ // Map is enum. We cannot create a reference to int from an enum.
static Derived* EnumWrap(const Key& key, const Value value, Arena* arena) {
return Arena::CreateMessage<MapEnumEntryWrapper>(arena, key, value);
}
// Like above, but for all the other types. This avoids value copy to create
- // MapEntryImpl from google::protobuf::Map in serialization.
+ // MapEntryImpl from Map in serialization.
static Derived* Wrap(const Key& key, const Value& value, Arena* arena) {
return Arena::CreateMessage<MapEntryWrapper>(arena, key, value);
}
@@ -336,11 +342,14 @@ class MapEntryImpl : public Base {
class Parser {
public:
explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
+ ~Parser() {
+ if (entry_ != nullptr && entry_->GetArena() == nullptr) delete entry_;
+ }
// This does what the typical MergePartialFromCodedStream() is expected to
// do, with the additional side-effect that if successful (i.e., if true is
// going to be its return value) it inserts the key-value pair into map_.
- bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+ bool MergePartialFromCodedStream(io::CodedInputStream* input) {
// Look for the expected thing: a key and then a value. If it fails,
// invoke the enclosing class's MergePartialFromCodedStream, or return
// false if that would be pointless.
@@ -353,11 +362,11 @@ class MapEntryImpl : public Base {
int size;
input->GetDirectBufferPointerInline(&data, &size);
// We could use memcmp here, but we don't bother. The tag is one byte.
- GOOGLE_COMPILE_ASSERT(kTagSize == 1, tag_size_error);
+ static_assert(kTagSize == 1, "tag size must be 1");
if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) {
typename Map::size_type map_size = map_->size();
value_ptr_ = &(*map_)[key_];
- if (GOOGLE_PREDICT_TRUE(map_size != map_->size())) {
+ if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
// We created a new key-value pair. Fill in the value.
typedef
typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T;
@@ -375,19 +384,53 @@ class MapEntryImpl : public Base {
key_ = Key();
}
- entry_.reset(mf_->NewEntry());
+ NewEntry();
*entry_->mutable_key() = key_;
const bool result = entry_->MergePartialFromCodedStream(input);
if (result) UseKeyAndValueFromEntry();
- if (entry_->GetArena() != NULL) entry_.release();
return result;
}
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+ bool ParseMap(const char* begin, const char* end) {
+ io::CodedInputStream input(reinterpret_cast<const uint8*>(begin),
+ end - begin);
+ return MergePartialFromCodedStream(&input) &&
+ input.ConsumedEntireMessage();
+ }
+ template <typename Metadata>
+ bool ParseMapEnumValidation(const char* begin, const char* end, uint32 num,
+ Metadata* metadata,
+ bool (*validate_enum)(int)) {
+ io::CodedInputStream input(reinterpret_cast<const uint8*>(begin),
+ end - begin);
+ auto entry = NewEntry();
+ // TODO(gerbens) implement _InternalParse for maps. We can't use
+ // ParseFromString as this will call _InternalParse
+ if (!(entry->MergePartialFromCodedStream(&input) &&
+ input.ConsumedEntireMessage()))
+ return false;
+ if (!validate_enum(entry->value())) {
+ auto unknown_fields = metadata->mutable_unknown_fields();
+ WriteLengthDelimited(num, StringPiece(begin, end - begin),
+ unknown_fields);
+ return true;
+ }
+ (*map_)[entry->key()] = static_cast<Value>(entry->value());
+ return true;
+ }
+#endif
+
+ MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }
+
const Key& key() const { return key_; }
const Value& value() const { return *value_ptr_; }
+ const Key& entry_key() const { return entry_->key(); }
+ const Value& entry_value() const { return entry_->value(); }
+
private:
- void UseKeyAndValueFromEntry() GOOGLE_PROTOBUF_ATTRIBUTE_COLD {
+ void UseKeyAndValueFromEntry() PROTOBUF_COLD {
// Update key_ in case we need it later (because key() is called).
// This is potentially inefficient, especially if the key is
// expensive to copy (e.g., a long string), but this is a cold
@@ -404,8 +447,7 @@ class MapEntryImpl : public Base {
// After reading a key and value successfully, and inserting that data
// into map_, we are not at the end of the input. This is unusual, but
// allowed by the spec.
- bool ReadBeyondKeyValuePair(::google::protobuf::io::CodedInputStream* input)
- GOOGLE_PROTOBUF_ATTRIBUTE_COLD {
+ bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
typedef MoveHelper<KeyTypeHandler::kIsEnum,
KeyTypeHandler::kIsMessage,
KeyTypeHandler::kWireType ==
@@ -416,13 +458,12 @@ class MapEntryImpl : public Base {
ValueTypeHandler::kWireType ==
WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
Value> ValueMover;
- entry_.reset(mf_->NewEntry());
+ NewEntry();
ValueMover::Move(value_ptr_, entry_->mutable_value());
map_->erase(key_);
KeyMover::Move(&key_, entry_->mutable_key());
const bool result = entry_->MergePartialFromCodedStream(input);
if (result) UseKeyAndValueFromEntry();
- if (entry_->GetArena() != NULL) entry_.release();
return result;
}
@@ -430,9 +471,7 @@ class MapEntryImpl : public Base {
Map* const map_;
Key key_;
Value* value_ptr_;
- // On the fast path entry_ is not used. And, when entry_ is used, it's set
- // to mf_->NewEntry(), so in the arena case we must call entry_.release.
- std::unique_ptr<MapEntryImpl> entry_;
+ MapEntryImpl* entry_ = nullptr;
};
protected:
@@ -445,9 +484,9 @@ class MapEntryImpl : public Base {
private:
// Serializing a generated message containing map field involves serializing
- // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+ // key-value pairs from Map. The wire format of each key-value pair
// after serialization should be the same as that of a MapEntry message
- // containing the same key and value inside it. However, google::protobuf::Map doesn't
+ // containing the same key and value inside it. However, Map doesn't
// store key and value as MapEntry message, which disables us to use existing
// code to serialize message. In order to use existing code to serialize
// message, we need to construct a MapEntry from key-value pair. But it
@@ -466,14 +505,16 @@ class MapEntryImpl : public Base {
BaseClass::set_has_key();
BaseClass::set_has_value();
}
- inline const KeyMapEntryAccessorType& key() const { return key_; }
- inline const ValueMapEntryAccessorType& value() const { return value_; }
+ inline const KeyMapEntryAccessorType& key() const override { return key_; }
+ inline const ValueMapEntryAccessorType& value() const override {
+ return value_;
+ }
private:
const Key& key_;
const Value& value_;
- friend class ::google::protobuf::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
};
@@ -503,7 +544,7 @@ class MapEntryImpl : public Base {
const KeyMapEntryAccessorType& key_;
const ValueMapEntryAccessorType value_;
- friend class google::protobuf::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void DestructorSkippable_;
};
@@ -518,7 +559,7 @@ class MapEntryImpl : public Base {
uint32 _has_bits_[1];
private:
- friend class ::google::protobuf::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
template <typename C, typename K, typename V, WireFormatLite::FieldType,
@@ -602,20 +643,20 @@ struct FromHelper {
template <>
struct FromHelper<WireFormatLite::TYPE_STRING> {
- static ArenaStringPtr From(const string& x) {
+ static ArenaStringPtr From(const std::string& x) {
ArenaStringPtr res;
TaggedPtr<::std::string> ptr;
- ptr.Set(const_cast<string*>(&x));
+ ptr.Set(const_cast<std::string*>(&x));
res.UnsafeSetTaggedPointer(ptr);
return res;
}
};
template <>
struct FromHelper<WireFormatLite::TYPE_BYTES> {
- static ArenaStringPtr From(const string& x) {
+ static ArenaStringPtr From(const std::string& x) {
ArenaStringPtr res;
TaggedPtr<::std::string> ptr;
- ptr.Set(const_cast<string*>(&x));
+ ptr.Set(const_cast<std::string*>(&x));
res.UnsafeSetTaggedPointer(ptr);
return res;
}
@@ -666,6 +707,8 @@ struct MapEntryHelper<MapEntryLite<T, Key, Value, kKeyFieldType,
} // namespace internal
} // namespace protobuf
-
} // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__