Internal change

PiperOrigin-RevId: 485219994
pull/10861/head
Mike Kruskal 2 years ago committed by Copybara-Service
parent 6e2102c8e3
commit 1c46a3374b
  1. 1
      src/google/protobuf/compiler/BUILD.bazel
  2. 157
      src/google/protobuf/compiler/command_line_interface.cc

@ -83,6 +83,7 @@ cc_library(
":code_generator",
":importer",
"//src/google/protobuf:protobuf_nowkt",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],

@ -34,6 +34,7 @@
#include "google/protobuf/compiler/command_line_interface.h"
#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_map.h"
#include "google/protobuf/stubs/platform_macros.h"
@ -427,7 +428,7 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
// The files_ field maps from path keys to file content values. It's a map
// instead of an unordered_map so that files are written in order (good when
// writing zips).
absl::flat_hash_map<std::string, std::string> files_;
absl::btree_map<std::string, std::string> files_;
const std::vector<const FileDescriptor*>& parsed_files_;
bool had_error_;
};
@ -805,95 +806,95 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
}
it->second.swap(data_);
} else {
// This was an OpenForInsert().
return;
}
// This was an OpenForInsert().
// If the data doesn't end with a clean line break, add one.
if (!data_.empty() && data_[data_.size() - 1] != '\n') {
data_.push_back('\n');
}
// If the data doesn't end with a clean line break, add one.
if (!data_.empty() && data_[data_.size() - 1] != '\n') {
data_.push_back('\n');
}
// Find the file we are going to insert into.
if (!already_present) {
std::cerr << filename_
<< ": Tried to insert into file that doesn't exist."
<< std::endl;
directory_->had_error_ = true;
return;
}
std::string* target = &it->second;
// Find the file we are going to insert into.
if (!already_present) {
std::cerr << filename_ << ": Tried to insert into file that doesn't exist."
<< std::endl;
directory_->had_error_ = true;
return;
}
std::string* target = &it->second;
// Find the insertion point.
std::string magic_string =
absl::Substitute("@@protoc_insertion_point($0)", insertion_point_);
std::string::size_type pos = target->find(magic_string);
// Find the insertion point.
std::string magic_string =
absl::Substitute("@@protoc_insertion_point($0)", insertion_point_);
std::string::size_type pos = target->find(magic_string);
if (pos == std::string::npos) {
std::cerr << filename_ << ": insertion point \"" << insertion_point_
<< "\" not found." << std::endl;
directory_->had_error_ = true;
return;
}
if (pos == std::string::npos) {
std::cerr << filename_ << ": insertion point \"" << insertion_point_
<< "\" not found." << std::endl;
directory_->had_error_ = true;
return;
}
if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
// Support for inline "/* @@protoc_insertion_point() */"
pos = pos - 3;
if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
// Support for inline "/* @@protoc_insertion_point() */"
pos = pos - 3;
} else {
// Seek backwards to the beginning of the line, which is where we will
// insert the data. Note that this has the effect of pushing the
// insertion point down, so the data is inserted before it. This is
// intentional because it means that multiple insertions at the same point
// will end up in the expected order in the final output.
pos = target->find_last_of('\n', pos);
if (pos == std::string::npos) {
// Insertion point is on the first line.
pos = 0;
} else {
// Seek backwards to the beginning of the line, which is where we will
// insert the data. Note that this has the effect of pushing the
// insertion point down, so the data is inserted before it. This is
// intentional because it means that multiple insertions at the same point
// will end up in the expected order in the final output.
pos = target->find_last_of('\n', pos);
if (pos == std::string::npos) {
// Insertion point is on the first line.
pos = 0;
} else {
// Advance to character after '\n'.
++pos;
}
// Advance to character after '\n'.
++pos;
}
}
// Extract indent.
std::string indent_(*target, pos,
target->find_first_not_of(" \t", pos) - pos);
// Extract indent.
std::string indent_(*target, pos,
target->find_first_not_of(" \t", pos) - pos);
if (indent_.empty()) {
// No indent. This makes things easier.
target->insert(pos, data_);
UpdateMetadata(data_, pos, data_.size(), 0);
} else {
// Calculate how much space we need.
int indent_size = 0;
for (int i = 0; i < data_.size(); i++) {
if (data_[i] == '\n') indent_size += indent_.size();
}
if (indent_.empty()) {
// No indent. This makes things easier.
target->insert(pos, data_);
UpdateMetadata(data_, pos, data_.size(), 0);
return;
}
// Calculate how much space we need.
int indent_size = 0;
for (int i = 0; i < data_.size(); i++) {
if (data_[i] == '\n') indent_size += indent_.size();
}
// Make a hole for it.
target->insert(pos, data_.size() + indent_size, '\0');
// Now copy in the data.
std::string::size_type data_pos = 0;
char* target_ptr = &(*target)[pos];
while (data_pos < data_.size()) {
// Copy indent.
memcpy(target_ptr, indent_.data(), indent_.size());
target_ptr += indent_.size();
// Copy line from data_.
// We already guaranteed that data_ ends with a newline (above), so this
// search can't fail.
std::string::size_type line_length =
data_.find_first_of('\n', data_pos) + 1 - data_pos;
memcpy(target_ptr, data_.data() + data_pos, line_length);
target_ptr += line_length;
data_pos += line_length;
}
UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size());
// Make a hole for it.
target->insert(pos, data_.size() + indent_size, '\0');
GOOGLE_CHECK_EQ(target_ptr, &(*target)[pos] + data_.size() + indent_size);
}
// Now copy in the data.
std::string::size_type data_pos = 0;
char* target_ptr = &(*target)[pos];
while (data_pos < data_.size()) {
// Copy indent.
memcpy(target_ptr, indent_.data(), indent_.size());
target_ptr += indent_.size();
// Copy line from data_.
// We already guaranteed that data_ ends with a newline (above), so this
// search can't fail.
std::string::size_type line_length =
data_.find_first_of('\n', data_pos) + 1 - data_pos;
memcpy(target_ptr, data_.data() + data_pos, line_length);
target_ptr += line_length;
data_pos += line_length;
}
GOOGLE_CHECK_EQ(target_ptr, &(*target)[pos] + data_.size() + indent_size);
UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size());
}
// ===================================================================

Loading…
Cancel
Save