Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 34 additions & 32 deletions src/google/protobuf/text_format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "absl/base/macros.h"
#include "absl/container/btree_set.h"
#include "absl/log/absl_check.h"
#include "absl/memory/memory.h"
#include "absl/strings/ascii.h"
#include "absl/strings/cord.h"
#include "absl/strings/escaping.h"
Expand All @@ -44,6 +45,7 @@
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/dynamic_message.h"
#include "google/protobuf/internal_visibility.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/strtod.h"
#include "google/protobuf/io/tokenizer.h"
Expand Down Expand Up @@ -2459,32 +2461,38 @@ class MapEntryMessageComparator {
};

namespace internal {

struct MapEntries {
std::vector<std::unique_ptr<const Message>> owned_entries;
std::vector<const Message*> all_entries;
};

class MapFieldPrinterHelper {
public:
// DynamicMapSorter::Sort cannot be used because it enforces syncing with
// repeated field.
static bool SortMap(const Message& message, const Reflection* reflection,
const FieldDescriptor* field,
std::vector<const Message*>* sorted_map_field);
static MapEntries SortMap(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field);
static void CopyKey(const MapKey& key, Message* message,
const FieldDescriptor* field_desc);
static void CopyValue(const MapValueRef& value, Message* message,
const FieldDescriptor* field_desc);
};

// Returns true if elements contained in sorted_map_field need to be released.
bool MapFieldPrinterHelper::SortMap(
const Message& message, const Reflection* reflection,
const FieldDescriptor* field,
std::vector<const Message*>* sorted_map_field) {
bool need_release = false;
MapEntries MapFieldPrinterHelper::SortMap(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field) {
const MapFieldBase& base = *reflection->GetMapData(message, field);

std::vector<const Message*> all_entries;
std::vector<std::unique_ptr<const Message>> owned_entries;
if (base.IsRepeatedFieldValid()) {
const RepeatedPtrField<Message>& map_field =
reflection->GetRepeatedPtrFieldInternal<Message>(message, field);
all_entries.reserve(map_field.size());
for (int i = 0; i < map_field.size(); ++i) {
sorted_map_field->push_back(
all_entries.push_back(
const_cast<RepeatedPtrField<Message>*>(&map_field)->Mutable(i));
}
} else {
Expand All @@ -2493,23 +2501,25 @@ bool MapFieldPrinterHelper::SortMap(
const Descriptor* map_entry_desc = field->message_type();
const Message* prototype =
reflection->GetMessageFactory()->GetPrototype(map_entry_desc);
all_entries.reserve(reflection->MapSize(message, field));
owned_entries.reserve(reflection->MapSize(message, field));
for (MapIterator iter =
reflection->MapBegin(const_cast<Message*>(&message), field);
iter != reflection->MapEnd(const_cast<Message*>(&message), field);
++iter) {
Message* map_entry_message = prototype->New();
CopyKey(iter.GetKey(), map_entry_message, map_entry_desc->field(0));
CopyValue(iter.GetValueRef(), map_entry_message,
std::unique_ptr<Message> map_entry_message =
absl::WrapUnique(prototype->New());
CopyKey(iter.GetKey(), map_entry_message.get(), map_entry_desc->field(0));
CopyValue(iter.GetValueRef(), map_entry_message.get(),
map_entry_desc->field(1));
sorted_map_field->push_back(map_entry_message);
all_entries.push_back(map_entry_message.get());
owned_entries.push_back(std::move(map_entry_message));
}
need_release = true;
}

MapEntryMessageComparator comparator(field->message_type());
std::stable_sort(sorted_map_field->begin(), sorted_map_field->end(),
comparator);
return need_release;
std::stable_sort(all_entries.begin(), all_entries.end(),
MapEntryMessageComparator(field->message_type()));
return {std::move(owned_entries), std::move(all_entries)};
}

void MapFieldPrinterHelper::CopyKey(const MapKey& key, Message* message,
Expand Down Expand Up @@ -2607,13 +2617,11 @@ void TextFormat::Printer::PrintField(const Message& message,
count = 1;
}

std::vector<const Message*> sorted_map_field;
bool need_release = false;
bool is_map = field->is_map();
if (is_map) {
need_release = internal::MapFieldPrinterHelper::SortMap(
message, reflection, field, &sorted_map_field);
}
const internal::MapEntries map_entries =
is_map
? internal::MapFieldPrinterHelper::SortMap(message, reflection, field)
: internal::MapEntries();

for (int j = 0; j < count; ++j) {
const int field_index = field->is_repeated() ? j : -1;
Expand All @@ -2628,7 +2636,7 @@ void TextFormat::Printer::PrintField(const Message& message,
const FastFieldValuePrinter* printer = GetFieldPrinter(field);
const Message& sub_message =
field->is_repeated()
? (is_map ? *sorted_map_field[j]
? (is_map ? *map_entries.all_entries[j]
: reflection->GetRepeatedMessage(message, field, j))
: reflection->GetMessage(message, field);
printer->PrintMessageStart(sub_message, field_index, count,
Expand All @@ -2652,12 +2660,6 @@ void TextFormat::Printer::PrintField(const Message& message,
}
}
}

if (need_release) {
for (const Message* message_to_delete : sorted_map_field) {
delete message_to_delete;
}
}
}

void TextFormat::Printer::PrintShortRepeatedField(
Expand Down
Loading