Migrate std::operator+ to Abseil helpers in utility code.

This also opportunistically migrates many C-style and STL strings to string_view in touched code.

PiperOrigin-RevId: 502655455
pull/11520/head
Mike Kruskal 2 years ago committed by Copybara-Service
parent 6379624149
commit b80cc536de
  1. 1905
      conformance/binary_json_conformance_suite.cc
  2. 26
      conformance/text_format_conformance_suite.cc
  3. 32
      src/google/protobuf/io/zero_copy_stream_unittest.cc
  4. 8
      src/google/protobuf/testing/file.cc
  5. 20
      src/google/protobuf/testing/googletest.cc
  6. 61
      src/google/protobuf/util/field_mask_util.cc
  7. 19
      src/google/protobuf/util/message_differencer_unittest.cc
  8. 28
      src/google/protobuf/util/time_util.cc
  9. 4
      src/google/protobuf/util/time_util.h
  10. 26
      src/google/protobuf/util/type_resolver_util.cc
  11. 4
      src/google/protobuf/util/type_resolver_util.h

File diff suppressed because it is too large Load Diff

@ -33,6 +33,7 @@
#include "google/protobuf/any.pb.h"
#include "google/protobuf/text_format.h"
#include "google/protobuf/stubs/logging.h"
#include "absl/strings/str_cat.h"
#include "conformance_test.h"
#include "google/protobuf/test_messages_proto2.pb.h"
#include "google/protobuf/test_messages_proto3.pb.h"
@ -220,15 +221,15 @@ void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest(
TestAllTypesProto3 prototype;
ConformanceRequestSetting setting1(
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Drop",
serialized_input);
conformance::TEXT_FORMAT_TEST, prototype,
absl::StrCat(test_name, "_Drop"), serialized_input);
setting1.SetPrototypeMessageForCompare(message);
RunValidBinaryInputTest(setting1, "");
ConformanceRequestSetting setting2(
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
conformance::TEXT_FORMAT_TEST, prototype, test_name + "_Print",
serialized_input);
conformance::TEXT_FORMAT_TEST, prototype,
absl::StrCat(test_name, "_Print"), serialized_input);
setting2.SetPrototypeMessageForCompare(message);
setting2.SetPrintUnknownFields(true);
RunValidBinaryInputTest(setting2, serialized_input);
@ -532,26 +533,27 @@ void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() {
void TextFormatConformanceTestSuite::
TestTextFormatPerformanceMergeMessageWithRepeatedField(
const string& test_type_name, const string& message_field) {
string recursive_message = "recursive_message { " + message_field + " }";
string recursive_message =
absl::StrCat("recursive_message { ", message_field, " }");
string input;
for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
input.append(recursive_message);
absl::StrAppend(&input, recursive_message);
}
string expected = "recursive_message { ";
for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
expected.append(message_field + " ");
absl::StrAppend(&expected, message_field, " ");
}
expected.append("}");
absl::StrAppend(&expected, "}");
RunValidTextFormatTestProto2WithExpected(
"TestTextFormatPerformanceMergeMessageWithRepeatedField" +
test_type_name + "Proto2",
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField",
test_type_name, "Proto2"),
RECOMMENDED, input, expected);
RunValidTextFormatTestWithExpected(
"TestTextFormatPerformanceMergeMessageWithRepeatedField" +
test_type_name + "Proto3",
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField",
test_type_name, "Proto3"),
RECOMMENDED, input, expected);
}

@ -46,10 +46,6 @@
// "parametized tests" so that one set of tests can be used on all the
// implementations.
#include <algorithm>
#include <chrono>
#include <thread>
#ifndef _WIN32
#include <sys/socket.h>
#include <unistd.h>
@ -60,15 +56,26 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <algorithm>
#include <chrono>
#include <iterator>
#include <memory>
#include <sstream>
#include <thread>
#include <utility>
#include <vector>
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/testing/file.h"
#include "google/protobuf/testing/file.h"
#include "google/protobuf/testing/googletest.h"
#include <gtest/gtest.h>
#include "google/protobuf/stubs/logging.h"
#include "google/protobuf/stubs/logging.h"
#include "absl/status/status.h"
#include "absl/strings/cord.h"
#include "absl/strings/cord_buffer.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/io_win32.h"
@ -79,17 +86,6 @@
#include "google/protobuf/io/gzip_stream.h"
#endif
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/testing/file.h"
#include "google/protobuf/testing/googletest.h"
#include <gtest/gtest.h>
#include "google/protobuf/stubs/logging.h"
#include "google/protobuf/stubs/logging.h"
#include "absl/status/status.h"
#include "absl/strings/cord.h"
#include "absl/strings/cord_buffer.h"
#include "absl/strings/string_view.h"
// Must be included last.
#include "google/protobuf/port_def.inc"
@ -1447,7 +1443,8 @@ TEST_F(IoTest, CordOutputBufferEndsAtSizeHint) {
// To test files, we create a temporary file, write, read, truncate, repeat.
TEST_F(IoTest, FileIo) {
std::string filename = TestTempDir() + "/zero_copy_stream_test_file";
std::string filename =
absl::StrCat(TestTempDir(), "/zero_copy_stream_test_file");
for (int i = 0; i < kBlockSizeCount; i++) {
for (int j = 0; j < kBlockSizeCount; j++) {
@ -1544,7 +1541,8 @@ TEST_F(IoTest, BlockingFileIoWithTimeout) {
#if HAVE_ZLIB
TEST_F(IoTest, GzipFileIo) {
std::string filename = TestTempDir() + "/zero_copy_stream_test_file";
std::string filename =
absl::StrCat(TestTempDir(), "/zero_copy_stream_test_file");
for (int i = 0; i < kBlockSizeCount; i++) {
for (int j = 0; j < kBlockSizeCount; j++) {

@ -46,6 +46,7 @@
#endif
#include <errno.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/io_win32.h"
#include "google/protobuf/stubs/logging.h"
@ -158,7 +159,8 @@ void File::DeleteRecursively(const std::string& name, void* dummy1,
#ifdef _MSC_VER
// This interface is so weird.
WIN32_FIND_DATAA find_data;
HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data);
HANDLE find_handle =
FindFirstFileA(absl::StrCat(name, "/*").c_str(), &find_data);
if (find_handle == INVALID_HANDLE_VALUE) {
// Just delete it, whatever it is.
DeleteFileA(name.c_str());
@ -169,7 +171,7 @@ void File::DeleteRecursively(const std::string& name, void* dummy1,
do {
std::string entry_name = find_data.cFileName;
if (entry_name != "." && entry_name != "..") {
std::string path = name + "/" + entry_name;
std::string path = absl::StrCat(name, "/", entry_name);
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
DeleteRecursively(path, NULL, NULL);
RemoveDirectoryA(path.c_str());
@ -195,7 +197,7 @@ void File::DeleteRecursively(const std::string& name, void* dummy1,
if (entry == NULL) break;
std::string entry_name = entry->d_name;
if (entry_name != "." && entry_name != "..") {
DeleteRecursively(name + "/" + entry_name, NULL, NULL);
DeleteRecursively(absl::StrCat(name, "/", entry_name), NULL, NULL);
}
}
}

@ -39,6 +39,7 @@
#include <sys/types.h>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "google/protobuf/io/io_win32.h"
#include "google/protobuf/testing/file.h"
@ -93,15 +94,17 @@ std::string TestSourceDir() {
// src/.../descriptor.cc. It is important to look for a particular file,
// keeping in mind that with Bazel builds the directory structure under
// bazel-bin/ looks similar to the main directory tree in the Git repo.
while (!File::Exists(prefix + "/src/google/protobuf/descriptor.cc")) {
while (!File::Exists(
absl::StrCat(prefix, "/src/google/protobuf/descriptor.cc"))) {
if (!File::Exists(prefix)) {
GOOGLE_LOG(FATAL)
<< "Could not find protobuf source code. Please run tests from "
"somewhere within the protobuf source package.";
}
prefix += "/..";
absl::StrAppend(&prefix, "/..");
}
return prefix + "/src";
absl::StrAppend(&prefix, "/src");
return prefix;
#endif // GOOGLE_PROTOBUF_TEST_SOURCE_PATH
#else
return "third_party/protobuf/src";
@ -113,9 +116,9 @@ namespace {
std::string GetTemporaryDirectoryName() {
// Tests run under Bazel "should not" use /tmp. Bazel sets this environment
// variable for tests to use instead.
char *from_environment = getenv("TEST_TMPDIR");
char* from_environment = getenv("TEST_TMPDIR");
if (from_environment != NULL && from_environment[0] != '\0') {
return std::string(from_environment) + "/protobuf_tmpdir";
return absl::StrCat(from_environment, "/protobuf_tmpdir");
}
// tmpnam() is generally not considered safe but we're only using it for
@ -176,7 +179,8 @@ class TempDirDeleter {
// Stick a file in the directory that tells people what this is, in case
// we abort and don't get a chance to delete it.
File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS");
File::WriteStringToFileOrDie(
"", absl::StrCat(name_, "/TEMP_DIR_FOR_PROTOBUF_TESTS"));
}
return name_;
}
@ -201,7 +205,7 @@ static int original_stderr_ = -1;
void CaptureTestStdout() {
GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing.";
stdout_capture_filename_ = TestTempDir() + "/captured_stdout";
stdout_capture_filename_ = absl::StrCat(TestTempDir(), "/captured_stdout");
int fd = open(stdout_capture_filename_.c_str(),
O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
@ -216,7 +220,7 @@ void CaptureTestStdout() {
void CaptureTestStderr() {
GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing.";
stderr_capture_filename_ = TestTempDir() + "/captured_stderr";
stderr_capture_filename_ = absl::StrCat(TestTempDir(), "/captured_stderr");
int fd = open(stderr_capture_filename_.c_str(),
O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);

@ -41,6 +41,8 @@
#include "absl/memory/memory.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "google/protobuf/message.h"
// Must be included last.
@ -58,8 +60,8 @@ std::string FieldMaskUtil::ToString(const FieldMask& mask) {
void FieldMaskUtil::FromString(absl::string_view str, FieldMask* out) {
out->Clear();
std::vector<std::string> paths = absl::StrSplit(str, ',');
for (const std::string& path : paths) {
std::vector<absl::string_view> paths = absl::StrSplit(str, ',');
for (absl::string_view path : paths) {
if (path.empty()) continue;
out->add_paths(path);
}
@ -116,7 +118,7 @@ bool FieldMaskUtil::CamelCaseToSnakeCase(absl::string_view input,
bool FieldMaskUtil::ToJsonString(const FieldMask& mask, std::string* out) {
out->clear();
for (int i = 0; i < mask.paths_size(); ++i) {
const std::string& path = mask.paths(i);
absl::string_view path = mask.paths(i);
std::string camelcase_path;
if (!SnakeCaseToCamelCase(path, &camelcase_path)) {
return false;
@ -131,8 +133,8 @@ bool FieldMaskUtil::ToJsonString(const FieldMask& mask, std::string* out) {
bool FieldMaskUtil::FromJsonString(absl::string_view str, FieldMask* out) {
out->Clear();
std::vector<std::string> paths = absl::StrSplit(str, ',');
for (const std::string& path : paths) {
std::vector<absl::string_view> paths = absl::StrSplit(str, ',');
for (absl::string_view path : paths) {
if (path.empty()) continue;
std::string snakecase_path;
if (!CamelCaseToSnakeCase(path, &snakecase_path)) {
@ -149,8 +151,8 @@ bool FieldMaskUtil::GetFieldDescriptors(
if (field_descriptors != nullptr) {
field_descriptors->clear();
}
std::vector<std::string> parts = absl::StrSplit(path, '.');
for (const std::string& field_name : parts) {
std::vector<absl::string_view> parts = absl::StrSplit(path, '.');
for (absl::string_view field_name : parts) {
if (descriptor == nullptr) {
return false;
}
@ -206,18 +208,18 @@ class FieldMaskTree {
// be added to the tree. If the path matches an existing non-leaf node in the
// tree, that non-leaf node will be turned into a leaf node with all its
// children removed because the path matches all the node's children.
void AddPath(const std::string& path);
void AddPath(absl::string_view path);
// Remove a path from the tree.
// If the path is a sub-path of an existing field path in the tree, it means
// we need remove the existing field path and add all sub-paths except
// specified path. If the path matches an existing node in the tree, this node
// will be moved.
void RemovePath(const std::string& path, const Descriptor* descriptor);
void RemovePath(absl::string_view path, const Descriptor* descriptor);
// Calculate the intersection part of a field path with this tree and add
// the intersection field path into out.
void IntersectPath(const std::string& path, FieldMaskTree* out);
void IntersectPath(absl::string_view path, FieldMaskTree* out);
// Merge all fields specified by this tree from one message to another.
void MergeMessage(const Message& source,
@ -269,11 +271,11 @@ class FieldMaskTree {
// Merge a sub-tree to mask. This method adds the field paths represented
// by all leaf nodes descended from "node" to mask.
void MergeToFieldMask(const std::string& prefix, const Node* node,
void MergeToFieldMask(absl::string_view prefix, const Node* node,
FieldMask* out);
// Merge all leaf nodes of a sub-tree to another tree.
void MergeLeafNodesToTree(const std::string& prefix, const Node* node,
void MergeLeafNodesToTree(absl::string_view prefix, const Node* node,
FieldMaskTree* out);
// Merge all fields specified by a sub-tree from one message to another.
@ -308,8 +310,8 @@ void FieldMaskTree::MergeToFieldMask(FieldMask* mask) {
MergeToFieldMask("", &root_, mask);
}
void FieldMaskTree::MergeToFieldMask(const std::string& prefix,
const Node* node, FieldMask* out) {
void FieldMaskTree::MergeToFieldMask(absl::string_view prefix, const Node* node,
FieldMask* out) {
if (node->children.empty()) {
if (prefix.empty()) {
// This is the root node.
@ -325,7 +327,7 @@ void FieldMaskTree::MergeToFieldMask(const std::string& prefix,
}
}
void FieldMaskTree::AddPath(const std::string& path) {
void FieldMaskTree::AddPath(absl::string_view path) {
std::vector<absl::string_view> parts = absl::StrSplit(path, '.');
if (parts.empty()) {
return;
@ -351,7 +353,7 @@ void FieldMaskTree::AddPath(const std::string& path) {
}
}
void FieldMaskTree::RemovePath(const std::string& path,
void FieldMaskTree::RemovePath(absl::string_view path,
const Descriptor* descriptor) {
if (root_.children.empty()) {
// Nothing to be removed from an empty tree. We shortcut it here so an empty
@ -407,13 +409,13 @@ void FieldMaskTree::RemovePath(const std::string& path,
}
}
void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) {
std::vector<std::string> parts = absl::StrSplit(path, '.');
void FieldMaskTree::IntersectPath(absl::string_view path, FieldMaskTree* out) {
std::vector<absl::string_view> parts = absl::StrSplit(path, '.');
if (parts.empty()) {
return;
}
const Node* node = &root_;
for (const std::string& node_name : parts) {
for (absl::string_view node_name : parts) {
if (node->children.empty()) {
if (node != &root_) {
out->AddPath(path);
@ -432,7 +434,7 @@ void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) {
MergeLeafNodesToTree(path, node, out);
}
void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix,
void FieldMaskTree::MergeLeafNodesToTree(absl::string_view prefix,
const Node* node, FieldMaskTree* out) {
if (node->children.empty()) {
out->AddPath(prefix);
@ -452,7 +454,7 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
const Reflection* destination_reflection = destination->GetReflection();
const Descriptor* descriptor = source.GetDescriptor();
for (const auto& kv : node->children) {
const std::string& field_name = kv.first;
absl::string_view field_name = kv.first;
const Node* child = kv.second.get();
const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
if (field == nullptr) {
@ -552,7 +554,7 @@ void FieldMaskTree::AddRequiredFieldPath(Node* node,
for (int index = 0; index < field_count; ++index) {
const FieldDescriptor* field = descriptor->field(index);
if (field->is_required()) {
const std::string& node_name = field->name();
absl::string_view node_name = field->name();
std::unique_ptr<Node>& child = node->children[node_name];
if (child == nullptr) {
// Add required field path to the tree
@ -662,15 +664,16 @@ void FieldMaskUtil::Subtract(const Descriptor* descriptor,
bool FieldMaskUtil::IsPathInFieldMask(absl::string_view path,
const FieldMask& mask) {
for (int i = 0; i < mask.paths_size(); ++i) {
const std::string& mask_path = mask.paths(i);
if (path == mask_path) {
absl::string_view current = path;
absl::string_view mask_path = mask.paths(i);
if (current == mask_path) {
return true;
} else if (mask_path.length() < path.length()) {
}
// Also check whether mask.paths(i) is a prefix of path.
if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") ==
0) {
return true;
}
if (mask_path.length() < current.length() &&
absl::ConsumePrefix(&current, mask_path) &&
absl::ConsumePrefix(&current, ".")) {
return true;
}
}
return false;

@ -47,7 +47,9 @@
#include <gtest/gtest.h>
#include "absl/functional/bind_front.h"
#include "google/protobuf/stubs/logging.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/any_test.pb.h"
#include "google/protobuf/map_test_util.h"
#include "google/protobuf/map_unittest.pb.h"
@ -1856,7 +1858,7 @@ TEST(MessageDifferencerTest, PrintMapKeysTest) {
diff_with_any);
}
static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"};
static constexpr absl::string_view kIgnoredFields[] = {"rm.b", "rm.m.b"};
class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
public:
@ -1865,12 +1867,12 @@ class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
const std::vector<util::MessageDifferencer::SpecificField>&
parent_fields) override {
std::string name = "";
for (int i = 0; i < parent_fields.size(); ++i) {
name += parent_fields[i].field->name() + ".";
for (size_t i = 0; i < parent_fields.size(); ++i) {
absl::StrAppend(&name, parent_fields[i].field->name(), ".");
}
name += field->name();
for (int i = 0; i < ABSL_ARRAYSIZE(kIgnoredFields); ++i) {
if (name.compare(kIgnoredFields[i]) == 0) {
absl::StrAppend(&name, field->name());
for (size_t i = 0; i < ABSL_ARRAYSIZE(kIgnoredFields); ++i) {
if (name == kIgnoredFields[i]) {
return true;
}
}
@ -2440,8 +2442,9 @@ class ComparisonTest : public testing::Test {
}
if (!map_field_.empty() && !map_key_.empty()) {
d->TreatAsMap(GetFieldDescriptor(message, map_field_),
GetFieldDescriptor(message, map_field_ + "." + map_key_));
d->TreatAsMap(
GetFieldDescriptor(message, map_field_),
GetFieldDescriptor(message, absl::StrCat(map_field_, ".", map_key_)));
}
}

@ -39,6 +39,7 @@
#include "absl/numeric/int128.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
@ -137,7 +138,7 @@ std::string FormatNanos(int32_t nanos) {
}
std::string FormatTime(int64_t seconds, int32_t nanos) {
static const char kTimestampFormat[] = "%E4Y-%m-%dT%H:%M:%S";
static constexpr absl::string_view kTimestampFormat = "%E4Y-%m-%dT%H:%M:%S";
timespec spec;
spec.tv_sec = seconds;
@ -149,13 +150,13 @@ std::string FormatTime(int64_t seconds, int32_t nanos) {
// We format the nanoseconds part separately to meet the precision
// requirement.
if (nanos != 0) {
result += "." + FormatNanos(nanos);
absl::StrAppend(&result, ".", FormatNanos(nanos));
}
result += "Z";
absl::StrAppend(&result, "Z");
return result;
}
bool ParseTime(const std::string& value, int64_t* seconds, int32_t* nanos) {
bool ParseTime(absl::string_view value, int64_t* seconds, int32_t* nanos) {
absl::Time result;
if (!absl::ParseTime(absl::RFC3339_full, value, &result, nullptr)) {
return false;
@ -207,7 +208,7 @@ std::string TimeUtil::ToString(const Timestamp& timestamp) {
return FormatTime(timestamp.seconds(), timestamp.nanos());
}
bool TimeUtil::FromString(const std::string& value, Timestamp* timestamp) {
bool TimeUtil::FromString(absl::string_view value, Timestamp* timestamp) {
int64_t seconds;
int32_t nanos;
if (!ParseTime(value, &seconds, &nanos)) {
@ -231,15 +232,15 @@ std::string TimeUtil::ToString(const Duration& duration) {
int64_t seconds = duration.seconds();
int32_t nanos = duration.nanos();
if (seconds < 0 || nanos < 0) {
result += "-";
result = "-";
seconds = -seconds;
nanos = -nanos;
}
result += absl::StrCat(seconds);
absl::StrAppend(&result, seconds);
if (nanos != 0) {
result += "." + FormatNanos(nanos);
absl::StrAppend(&result, ".", FormatNanos(nanos));
}
result += "s";
absl::StrAppend(&result, "s");
return result;
}
@ -251,7 +252,7 @@ static int64_t Pow(int64_t x, int y) {
return result;
}
bool TimeUtil::FromString(const std::string& value, Duration* duration) {
bool TimeUtil::FromString(absl::string_view value, Duration* duration) {
if (value.length() <= 1 || value[value.length() - 1] != 's') {
return false;
}
@ -262,11 +263,12 @@ bool TimeUtil::FromString(const std::string& value, Duration* duration) {
std::string seconds_part, nanos_part;
size_t pos = value.find_last_of('.');
if (pos == std::string::npos) {
seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
seconds_part = std::string(
value.substr(sign_length, value.length() - 1 - sign_length));
nanos_part = "0";
} else {
seconds_part = value.substr(sign_length, pos - sign_length);
nanos_part = value.substr(pos + 1, value.length() - pos - 2);
seconds_part = std::string(value.substr(sign_length, pos - sign_length));
nanos_part = std::string(value.substr(pos + 1, value.length() - pos - 2));
}
char* end;
static_assert(sizeof(int64_t) == sizeof(long long),

@ -111,7 +111,7 @@ class PROTOBUF_EXPORT TimeUtil {
// Example of accepted format:
// "1972-01-01T10:00:20.021-05:00"
static std::string ToString(const Timestamp& timestamp);
static bool FromString(const std::string& value, Timestamp* timestamp);
static bool FromString(absl::string_view value, Timestamp* timestamp);
// Converts Duration to/from string format. The string format will contains
// 3, 6, or 9 fractional digits depending on the precision required to
@ -120,7 +120,7 @@ class PROTOBUF_EXPORT TimeUtil {
// The range that can be represented by Duration is from -315,576,000,000
// to +315,576,000,000 inclusive (in seconds).
static std::string ToString(const Duration& duration);
static bool FromString(const std::string& value, Duration* timestamp);
static bool FromString(absl::string_view value, Duration* duration);
// Gets the current UTC time.
static Timestamp GetCurrentTime();

@ -38,6 +38,8 @@
#include "absl/status/status.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "google/protobuf/io/strtod.h"
#include "google/protobuf/util/type_resolver.h"
@ -67,7 +69,7 @@ using google::protobuf::UInt64Value;
class DescriptorPoolTypeResolver : public TypeResolver {
public:
DescriptorPoolTypeResolver(const std::string& url_prefix,
DescriptorPoolTypeResolver(absl::string_view url_prefix,
const DescriptorPool* pool)
: url_prefix_(url_prefix), pool_(pool) {}
@ -81,8 +83,8 @@ class DescriptorPoolTypeResolver : public TypeResolver {
const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
if (descriptor == NULL) {
return absl::NotFoundError("Invalid type URL, unknown type: " +
type_name);
return absl::NotFoundError(
absl::StrCat("Invalid type URL, unknown type: ", type_name));
}
ConvertDescriptor(descriptor, type);
return absl::Status();
@ -98,8 +100,8 @@ class DescriptorPoolTypeResolver : public TypeResolver {
const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
if (descriptor == NULL) {
return absl::InvalidArgumentError("Invalid type URL, unknown type: " +
type_name);
return absl::InvalidArgumentError(
absl::StrCat("Invalid type URL, unknown type: ", type_name));
}
ConvertEnumDescriptor(descriptor, enum_type);
return absl::Status();
@ -297,21 +299,23 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
std::string GetTypeUrl(const Descriptor* descriptor) {
return url_prefix_ + "/" + descriptor->full_name();
return absl::StrCat(url_prefix_, "/", descriptor->full_name());
}
std::string GetTypeUrl(const EnumDescriptor* descriptor) {
return url_prefix_ + "/" + descriptor->full_name();
return absl::StrCat(url_prefix_, "/", descriptor->full_name());
}
absl::Status ParseTypeUrl(const std::string& type_url,
absl::Status ParseTypeUrl(absl::string_view type_url,
std::string* type_name) {
if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
absl::string_view stripped = type_url;
if (!absl::ConsumePrefix(&stripped, url_prefix_) ||
!absl::ConsumePrefix(&stripped, "/")) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid type URL, type URLs must be of the form '",
url_prefix_, "/<typename>', got: ", type_url));
}
*type_name = type_url.substr(url_prefix_.size() + 1);
*type_name = std::string(stripped);
return absl::Status();
}
@ -361,7 +365,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
} // namespace
TypeResolver* NewTypeResolverForDescriptorPool(const std::string& url_prefix,
TypeResolver* NewTypeResolverForDescriptorPool(absl::string_view url_prefix,
const DescriptorPool* pool) {
return new DescriptorPoolTypeResolver(url_prefix, pool);
}

@ -33,7 +33,7 @@
#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
#include <string>
#include "absl/strings/string_view.h"
// Must be included last.
#include "google/protobuf/port_def.inc"
@ -47,7 +47,7 @@ class TypeResolver;
// Creates a TypeResolver that serves type information in the given descriptor
// pool. Caller takes ownership of the returned TypeResolver.
PROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
const std::string& url_prefix, const DescriptorPool* pool);
absl::string_view url_prefix, const DescriptorPool* pool);
} // namespace util
} // namespace protobuf

Loading…
Cancel
Save