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.h77
1 files changed, 57 insertions, 20 deletions
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 982f0f44..98b2acae 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -40,9 +40,13 @@
#include <google/protobuf/map.h>
#include <google/protobuf/map_type_handler.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"
@@ -186,7 +190,7 @@ 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 override { return ""; }
+ std::string GetTypeName() const override { return ""; }
void CheckTypeAndMergeFrom(const MessageLite& other) override {
MergeFromInternal(*::google::protobuf::down_cast<const Derived*>(&other));
@@ -338,6 +342,9 @@ 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
@@ -355,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;
@@ -377,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
@@ -406,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(io::CodedInputStream* input)
- GOOGLE_PROTOBUF_ATTRIBUTE_COLD {
+ bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
typedef MoveHelper<KeyTypeHandler::kIsEnum,
KeyTypeHandler::kIsMessage,
KeyTypeHandler::kWireType ==
@@ -418,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;
}
@@ -432,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:
@@ -477,7 +514,7 @@ class MapEntryImpl : public Base {
const Key& key_;
const Value& value_;
- friend class ::GOOGLE_PROTOBUF_NAMESPACE_ID::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
};
@@ -507,7 +544,7 @@ class MapEntryImpl : public Base {
const KeyMapEntryAccessorType& key_;
const ValueMapEntryAccessorType value_;
- friend class ::GOOGLE_PROTOBUF_NAMESPACE_ID::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void DestructorSkippable_;
};
@@ -522,7 +559,7 @@ class MapEntryImpl : public Base {
uint32 _has_bits_[1];
private:
- friend class ::GOOGLE_PROTOBUF_NAMESPACE_ID::Arena;
+ friend class ::PROTOBUF_NAMESPACE_ID::Arena;
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
template <typename C, typename K, typename V, WireFormatLite::FieldType,
@@ -606,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;
}