Эх сурвалжийг харах

[C++] Refactor StatusOr and StringPiece (#8406)

* [C++] Refactor StatusOr and StringPiece

This change makes `StatusOr` and `StringPiece` more like
`absl::StatusOr` and `{absl,std}::string_view`.

Note that there is more work required before the Abseil types can be
used as drop-in replacement.

Progress on #3688

* Fix more errors

* Fix test

* Remove some asserts

* Delete outdate example
Yannic 4 жил өмнө
parent
commit
4b770cabd7

+ 2 - 6
src/google/protobuf/stubs/bytestream.cc

@@ -173,12 +173,8 @@ size_t LimitByteSource::Available() const {
 }
 
 StringPiece LimitByteSource::Peek() {
-  StringPiece piece(source_->Peek());
-  if (piece.size() > limit_) {
-    piece.set(piece.data(), limit_);
-  }
-
-  return piece;
+  StringPiece piece = source_->Peek();
+  return StringPiece(piece.data(), std::min(piece.size(), limit_));
 }
 
 void LimitByteSource::Skip(size_t n) {

+ 1 - 2
src/google/protobuf/stubs/casts.h

@@ -116,8 +116,7 @@ inline To down_cast(From& f) {
 
 template<typename To, typename From>
 inline To bit_cast(const From& from) {
-  GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
-                        bit_cast_with_different_sizes);
+  static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes");
   To dest;
   memcpy(&dest, &from, sizeof(dest));
   return dest;

+ 0 - 1
src/google/protobuf/stubs/common.h

@@ -123,7 +123,6 @@ std::string PROTOBUF_EXPORT VersionString(int version);
 // ===================================================================
 // from google3/util/utf8/public/unilib.h
 
-class StringPiece;
 namespace internal {
 
 // Checks if the buffer contains structurally-valid UTF-8.  Implemented in

+ 1 - 1
src/google/protobuf/stubs/logging.h

@@ -34,6 +34,7 @@
 #include <google/protobuf/stubs/macros.h>
 #include <google/protobuf/stubs/port.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/stringpiece.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -64,7 +65,6 @@ enum LogLevel {
 #endif
 };
 
-class StringPiece;
 class uint128;
 namespace internal {
 

+ 5 - 32
src/google/protobuf/stubs/macros.h

@@ -31,21 +31,19 @@
 #ifndef GOOGLE_PROTOBUF_MACROS_H__
 #define GOOGLE_PROTOBUF_MACROS_H__
 
-#include <google/protobuf/stubs/port.h>
-
 namespace google {
 namespace protobuf {
 
 #undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
 #define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
-  TypeName(const TypeName&);                           \
-  void operator=(const TypeName&)
+  TypeName(const TypeName&) = delete;                  \
+  void operator=(const TypeName&) = delete
 
 #undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
 #define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                           \
-  TypeName(const TypeName&);                            \
-  void operator=(const TypeName&)
+  TypeName() = delete;                                  \
+  TypeName(const TypeName&) = delete;                   \
+  void operator=(const TypeName&) = delete
 
 // ===================================================================
 // from google3/base/basictypes.h
@@ -89,31 +87,6 @@ namespace protobuf {
   ((sizeof(a) / sizeof(*(a))) / \
    static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
 
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-//   COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
-//                  content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-namespace internal {
-
-template <bool>
-struct CompileAssert {
-};
-
-}  // namespace internal
-
-#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
 }  // namespace protobuf
 }  // namespace google
 

+ 1 - 1
src/google/protobuf/stubs/status_macros.h

@@ -60,7 +60,7 @@ namespace util {
 template<typename T>
 Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
   if (result.ok()) {
-    lhs = result.ValueOrDie();
+    lhs = result.value();
   }
   return result.status();
 }

+ 2 - 2
src/google/protobuf/stubs/statusor.cc

@@ -35,14 +35,14 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace internal {
+namespace statusor_internal {
 
 void StatusOrHelper::Crash(const Status& status) {
   GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
                     << status.ToString();
 }
 
-}  // namespace internal
+}  // namespace statusor_internal
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google

+ 16 - 32
src/google/protobuf/stubs/statusor.h

@@ -42,7 +42,7 @@
 //
 //  StatusOr<float> result = DoBigCalculationThatCouldFail();
 //  if (result.ok()) {
-//    float answer = result.ValueOrDie();
+//    float answer = result.value();
 //    printf("Big calculation yielded: %f", answer);
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -52,17 +52,7 @@
 //
 //  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
 //  if (result.ok()) {
-//    std::unique_ptr<Foo> foo(result.ValueOrDie());
-//    foo->DoSomethingCool();
-//  } else {
-//    LOG(ERROR) << result.status();
-//  }
-//
-// Example client usage for a StatusOr<std::unique_ptr<T>>:
-//
-//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
-//  if (result.ok()) {
-//    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
+//    std::unique_ptr<Foo> foo(result.value());
 //    foo->DoSomethingCool();
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -93,17 +83,21 @@
 namespace google {
 namespace protobuf {
 namespace util {
+namespace statusor_internal {
 
 template<typename T>
 class StatusOr {
   template<typename U> friend class StatusOr;
 
  public:
+  using value_type = T;
+
+  // Construct a new StatusOr with Status::UNKNOWN status.
   // Construct a new StatusOr with UnknownError() status.
-  StatusOr();
+  explicit StatusOr();
 
   // Construct a new StatusOr with the given non-ok status. After calling
-  // this constructor, calls to ValueOrDie() will CHECK-fail.
+  // this constructor, calls to value() will CHECK-fail.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return
   // value, so it is convenient and sensible to be able to do 'return
@@ -116,7 +110,7 @@ class StatusOr {
 
   // Construct a new StatusOr with the given value. If T is a plain pointer,
   // value must not be nullptr. After calling this constructor, calls to
-  // ValueOrDie() will succeed, and calls to status() will return OK.
+  // value() will succeed, and calls to status() will return OK.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return type
   // so it is convenient and sensible to be able to do 'return T()'
@@ -149,9 +143,6 @@ class StatusOr {
   bool ok() const;
 
   // Returns a reference to our current value, or CHECK-fails if !this->ok().
-  // If you need to initialize a T object from the stored value,
-  // ConsumeValueOrDie() may be more efficient.
-  const T& ValueOrDie() const;
   const T& value () const;
 
  private:
@@ -162,8 +153,6 @@ class StatusOr {
 ////////////////////////////////////////////////////////////////////////////////
 // Implementation details for StatusOr<T>
 
-namespace internal {
-
 class PROTOBUF_EXPORT StatusOrHelper {
  public:
   // Move type-agnostic error handling to the .cc.
@@ -185,8 +174,6 @@ struct StatusOrHelper::Specialize<T*> {
   static inline bool IsValueNull(const T* t) { return t == nullptr; }
 };
 
-}  // namespace internal
-
 template<typename T>
 inline StatusOr<T>::StatusOr()
     : status_(util::UnknownError("")) {
@@ -203,7 +190,7 @@ inline StatusOr<T>::StatusOr(const Status& status) {
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const T& value) {
-  if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+  if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
     status_ = util::InternalError("nullptr is not a valid argument.");
   } else {
     status_ = util::OkStatus();
@@ -247,21 +234,18 @@ inline bool StatusOr<T>::ok() const {
   return status().ok();
 }
 
-template<typename T>
-inline const T& StatusOr<T>::ValueOrDie() const {
-  if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
-  }
-  return value_;
-}
-
 template<typename T>
 inline const T& StatusOr<T>::value() const {
   if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
+    StatusOrHelper::Crash(status_);
   }
   return value_;
 }
+
+}  // namespace statusor_internal
+
+using ::google::protobuf::util::statusor_internal::StatusOr;
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google

+ 14 - 16
src/google/protobuf/stubs/statusor_test.cc

@@ -84,7 +84,7 @@ TEST(StatusOr, TestValueCtor) {
   const int kI = 4;
   StatusOr<int> thing(kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusOk) {
@@ -92,7 +92,7 @@ TEST(StatusOr, TestCopyCtorStatusOk) {
   StatusOr<int> original(kI);
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOk) {
@@ -106,7 +106,7 @@ TEST(StatusOr, TestCopyCtorStatusOKConverting) {
   StatusOr<int>    original(kI);
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
@@ -121,7 +121,7 @@ TEST(StatusOr, TestAssignmentStatusOk) {
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOk) {
@@ -137,7 +137,7 @@ TEST(StatusOr, TestAssignmentStatusOKConverting) {
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_DOUBLE_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
@@ -158,13 +158,13 @@ TEST(StatusOr, TestStatus) {
 TEST(StatusOr, TestValue) {
   const int kI = 4;
   StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestValueConst) {
   const int kI = 4;
   const StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerDefaultCtor) {
@@ -183,7 +183,7 @@ TEST(StatusOr, TestPointerValueCtor) {
   const int kI = 4;
   StatusOr<const int*> thing(&kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusOk) {
@@ -191,7 +191,7 @@ TEST(StatusOr, TestPointerCopyCtorStatusOk) {
   StatusOr<const int*> original(&kI);
   StatusOr<const int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
@@ -205,8 +205,7 @@ TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
   StatusOr<Derived*> original(&derived);
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
-            copy.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(original.value()), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
@@ -221,7 +220,7 @@ TEST(StatusOr, TestPointerAssignmentStatusOk) {
   StatusOr<const int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
@@ -237,8 +236,7 @@ TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
   StatusOr<Base2*>   target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()),
-            target.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(source.value()), target.value());
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
@@ -259,13 +257,13 @@ TEST(StatusOr, TestPointerStatus) {
 TEST(StatusOr, TestPointerValue) {
   const int kI = 0;
   StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerValueConst) {
   const int kI = 0;
   const StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 }  // namespace

+ 42 - 59
src/google/protobuf/stubs/stringpiece.cc

@@ -39,31 +39,13 @@
 
 namespace google {
 namespace protobuf {
+namespace stringpiece_internal {
+
 std::ostream& operator<<(std::ostream& o, StringPiece piece) {
   o.write(piece.data(), piece.size());
   return o;
 }
 
-// Out-of-line error path.
-void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
-  GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
-}
-
-StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
-    : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-}
-
-StringPiece::StringPiece(StringPiece x,
-                         stringpiece_ssize_type pos,
-                         stringpiece_ssize_type len)
-    : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-  GOOGLE_DCHECK_GE(len, 0);
-}
-
 void StringPiece::CopyToString(std::string* target) const {
   target->assign(ptr_, length_);
 }
@@ -89,10 +71,9 @@ bool StringPiece::ConsumeFromEnd(StringPiece x) {
   return false;
 }
 
-stringpiece_ssize_type StringPiece::copy(char* buf,
-                                         size_type n,
-                                         size_type pos) const {
-  stringpiece_ssize_type ret = std::min(length_ - pos, n);
+StringPiece::size_type StringPiece::copy(
+    char* buf, size_type n, size_type pos) const {
+  size_type ret = std::min(length_ - pos, n);
   memcpy(buf, ptr_ + pos, ret);
   return ret;
 }
@@ -101,7 +82,8 @@ bool StringPiece::contains(StringPiece s) const {
   return find(s, 0) != npos;
 }
 
-stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::find(
+    StringPiece s, size_type pos) const {
   if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
     if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
     return npos;
@@ -111,7 +93,7 @@ stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
   return result == ptr_ + length_ ? npos : result - ptr_;
 }
 
-stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
+StringPiece::size_type StringPiece::find(char c, size_type pos) const {
   if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
     return npos;
   }
@@ -120,7 +102,7 @@ stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
   return result != nullptr ? result - ptr_ : npos;
 }
 
-stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(StringPiece s, size_type pos) const {
   if (length_ < s.length_) return npos;
   const size_t ulen = length_;
   if (s.length_ == 0) return std::min(ulen, pos);
@@ -131,10 +113,10 @@ stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
 }
 
 // Search range is [0..pos] inclusive.  If pos == npos, search everything.
-stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(char c, size_type pos) const {
   // Note: memrchr() is not available on Windows.
-  if (length_ <= 0) return npos;
-  for (stringpiece_ssize_type i =
+  if (empty()) return npos;
+  for (difference_type i =
       std::min(pos, static_cast<size_type>(length_ - 1));
        i >= 0; --i) {
     if (ptr_[i] == c) {
@@ -154,16 +136,16 @@ stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
 //   bool table[UCHAR_MAX + 1]
 static inline void BuildLookupTable(StringPiece characters_wanted,
                                     bool* table) {
-  const stringpiece_ssize_type length = characters_wanted.length();
+  const StringPiece::size_type length = characters_wanted.length();
   const char* const data = characters_wanted.data();
-  for (stringpiece_ssize_type i = 0; i < length; ++i) {
+  for (StringPiece::size_type i = 0; i < length; ++i) {
     table[static_cast<unsigned char>(data[i])] = true;
   }
 }
 
-stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
-                                                  size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) {
+StringPiece::size_type StringPiece::find_first_of(
+    StringPiece s, size_type pos) const {
+  if (empty() || s.empty()) {
     return npos;
   }
   // Avoid the cost of BuildLookupTable() for a single-character search.
@@ -171,7 +153,7 @@ stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -179,16 +161,16 @@ stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
-                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
-  if (s.length_ <= 0) return 0;
+StringPiece::size_type StringPiece::find_first_not_of(
+    StringPiece s, size_type pos) const {
+  if (empty()) return npos;
+  if (s.empty()) return 0;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -196,9 +178,9 @@ stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(char c,
-                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_first_not_of(
+    char c, size_type pos) const {
+  if (empty()) return npos;
 
   for (; pos < static_cast<size_type>(length_); ++pos) {
     if (ptr_[pos] != c) {
@@ -208,15 +190,15 @@ stringpiece_ssize_type StringPiece::find_first_not_of(char c,
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
-                                                 size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_of(
+    StringPiece s, size_type pos) const {
+  if (empty() || s.empty()) return npos;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i =
+  for (difference_type i =
        std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
@@ -225,12 +207,12 @@ stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
-                                                     size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_not_of(
+    StringPiece s, size_type pos) const {
+  if (empty()) return npos;
 
-  stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
-  if (s.length_ <= 0) return i;
+  size_type i = std::min(pos, length()-1);
+  if (s.empty()) return i;
 
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
@@ -245,11 +227,11 @@ stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(char c,
-                                                     size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_not_of(
+    char c, size_type pos) const {
+  if (empty()) return npos;
 
-  for (stringpiece_ssize_type i =
+  for (difference_type i =
        std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
     if (ptr_[i] != c) {
       return i;
@@ -259,12 +241,13 @@ stringpiece_ssize_type StringPiece::find_last_not_of(char c,
 }
 
 StringPiece StringPiece::substr(size_type pos, size_type n) const {
-  if (pos > length_) pos = length_;
-  if (n > length_ - pos) n = length_ - pos;
+  if (pos > length()) pos = length();
+  if (n > length_ - pos) n = length() - pos;
   return StringPiece(ptr_ + pos, n);
 }
 
 const StringPiece::size_type StringPiece::npos = size_type(-1);
 
+}  // namespace stringpiece_internal
 }  // namespace protobuf
 }  // namespace google

+ 50 - 122
src/google/protobuf/stubs/stringpiece.h

@@ -154,52 +154,26 @@
 
 namespace google {
 namespace protobuf {
-// StringPiece has *two* size types.
-// StringPiece::size_type
-//   is unsigned
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   no future changes intended
-// stringpiece_ssize_type
-//   is signed
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   future changes intended: http://go/64BitStringPiece
-//
-typedef std::string::difference_type stringpiece_ssize_type;
-
-// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
-// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
-#if !defined(NDEBUG)
-#define STRINGPIECE_CHECK_SIZE 1
-#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#define STRINGPIECE_CHECK_SIZE 1
-#else
-#define STRINGPIECE_CHECK_SIZE 0
-#endif
+namespace stringpiece_internal {
 
 class PROTOBUF_EXPORT StringPiece {
+ public:
+  using traits_type = std::char_traits<char>;
+  using value_type = char;
+  using pointer = char*;
+  using const_pointer = const char*;
+  using reference = char&;
+  using const_reference = const char&;
+  using const_iterator = const char*;
+  using iterator = const_iterator;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using reverse_iterator = const_reverse_iterator;
+  using size_type = size_t;
+  using difference_type = std::ptrdiff_t;
+
  private:
   const char* ptr_;
-  stringpiece_ssize_type length_;
-
-  // Prevent overflow in debug mode or fortified mode.
-  // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
-  static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
-#if STRINGPIECE_CHECK_SIZE > 0
-#ifdef max
-#undef max
-#endif
-    if (size > static_cast<size_t>(
-        std::numeric_limits<stringpiece_ssize_type>::max())) {
-      // Some people grep for this message in logs
-      // so take care if you ever change it.
-      LogFatalSizeTooBig(size, "size_t to int conversion");
-    }
-#endif
-    return static_cast<stringpiece_ssize_type>(size);
-  }
-
-  // Out-of-line error path.
-  static void LogFatalSizeTooBig(size_t size, const char* details);
+  size_type length_;
 
  public:
   // We provide non-explicit singleton constructors so users can pass
@@ -213,7 +187,7 @@ class PROTOBUF_EXPORT StringPiece {
   StringPiece(const char* str)  // NOLINT(runtime/explicit)
       : ptr_(str), length_(0) {
     if (str != nullptr) {
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
+      length_ = strlen(str);
     }
   }
 
@@ -221,78 +195,40 @@ class PROTOBUF_EXPORT StringPiece {
   StringPiece(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
       : ptr_(str.data()), length_(0) {
-    length_ = CheckedSsizeTFromSizeT(str.size());
-  }
-
-  StringPiece(const char* offset, stringpiece_ssize_type len)
-      : ptr_(offset), length_(len) {
-    assert(len >= 0);
+    length_ = str.size();
   }
 
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  StringPiece(StringPiece x, stringpiece_ssize_type pos);
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  // len must be non-negative and will be pinned to at most x.length() - pos.
-  StringPiece(StringPiece x,
-              stringpiece_ssize_type pos,
-              stringpiece_ssize_type len);
+  StringPiece(const char* offset, size_type len)
+      : ptr_(offset), length_(len) {}
 
   // data() may return a pointer to a buffer with embedded NULs, and the
   // returned buffer may or may not be null terminated.  Therefore it is
   // typically a mistake to pass data() to a routine that expects a NUL
   // terminated string.
-  const char* data() const { return ptr_; }
-  stringpiece_ssize_type size() const { return length_; }
-  stringpiece_ssize_type length() const { return length_; }
+  const_pointer data() const { return ptr_; }
+  size_type size() const { return length_; }
+  size_type length() const { return length_; }
   bool empty() const { return length_ == 0; }
 
-  void clear() {
-    ptr_ = nullptr;
-    length_ = 0;
-  }
-
-  void set(const char* data, stringpiece_ssize_type len) {
-    assert(len >= 0);
-    ptr_ = data;
-    length_ = len;
-  }
-
-  void set(const char* str) {
-    ptr_ = str;
-    if (str != nullptr)
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
-    else
-      length_ = 0;
-  }
-
-  void set(const void* data, stringpiece_ssize_type len) {
-    ptr_ = reinterpret_cast<const char*>(data);
-    length_ = len;
-  }
-
-  char operator[](stringpiece_ssize_type i) const {
-    assert(0 <= i);
+  char operator[](size_type i) const {
     assert(i < length_);
     return ptr_[i];
   }
 
-  void remove_prefix(stringpiece_ssize_type n) {
+  void remove_prefix(size_type n) {
     assert(length_ >= n);
     ptr_ += n;
     length_ -= n;
   }
 
-  void remove_suffix(stringpiece_ssize_type n) {
+  void remove_suffix(size_type n) {
     assert(length_ >= n);
     length_ -= n;
   }
 
   // returns {-1, 0, 1}
   int compare(StringPiece x) const {
-    const stringpiece_ssize_type min_size =
-        length_ < x.length_ ? length_ : x.length_;
+    size_type min_size = length_ < x.length_ ? length_ : x.length_;
     int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
     if (r < 0) return -1;
     if (r > 0) return 1;
@@ -336,53 +272,41 @@ class PROTOBUF_EXPORT StringPiece {
   bool ConsumeFromEnd(StringPiece x);
 
   // standard STL container boilerplate
-  typedef char value_type;
-  typedef const char* pointer;
-  typedef const char& reference;
-  typedef const char& const_reference;
-  typedef size_t size_type;
-  typedef ptrdiff_t difference_type;
   static const size_type npos;
-  typedef const char* const_iterator;
-  typedef const char* iterator;
-  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-  typedef std::reverse_iterator<iterator> reverse_iterator;
-  iterator begin() const { return ptr_; }
-  iterator end() const { return ptr_ + length_; }
+  const_iterator begin() const { return ptr_; }
+  const_iterator end() const { return ptr_ + length_; }
   const_reverse_iterator rbegin() const {
     return const_reverse_iterator(ptr_ + length_);
   }
   const_reverse_iterator rend() const {
     return const_reverse_iterator(ptr_);
   }
-  stringpiece_ssize_type max_size() const { return length_; }
-  stringpiece_ssize_type capacity() const { return length_; }
+  size_type max_size() const { return length_; }
+  size_type capacity() const { return length_; }
 
   // cpplint.py emits a false positive [build/include_what_you_use]
-  stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
+  size_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
 
   bool contains(StringPiece s) const;
 
-  stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find(char c, size_type pos = 0) const;
-  stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
-  stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
+  size_type find(StringPiece s, size_type pos = 0) const;
+  size_type find(char c, size_type pos = 0) const;
+  size_type rfind(StringPiece s, size_type pos = npos) const;
+  size_type rfind(char c, size_type pos = npos) const;
 
-  stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
+  size_type find_first_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_of(char c, size_type pos = 0) const {
     return find(c, pos);
   }
-  stringpiece_ssize_type find_first_not_of(StringPiece s,
-                                           size_type pos = 0) const;
-  stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
-  stringpiece_ssize_type find_last_of(StringPiece s,
-                                      size_type pos = npos) const;
-  stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
+  size_type find_first_not_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_not_of(char c, size_type pos = 0) const;
+  size_type find_last_of(StringPiece s, size_type pos = npos) const;
+  size_type find_last_of(char c, size_type pos = npos) const {
     return rfind(c, pos);
   }
-  stringpiece_ssize_type find_last_not_of(StringPiece s,
+  size_type find_last_not_of(StringPiece s,
                                           size_type pos = npos) const;
-  stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
+  size_type find_last_not_of(char c, size_type pos = npos) const;
 
   StringPiece substr(size_type pos, size_type n = npos) const;
 };
@@ -391,7 +315,7 @@ class PROTOBUF_EXPORT StringPiece {
 // one of the arguments is a literal, the compiler can elide a lot of the
 // following comparisons.
 inline bool operator==(StringPiece x, StringPiece y) {
-  stringpiece_ssize_type len = x.size();
+  StringPiece::size_type len = x.size();
   if (len != y.size()) {
     return false;
   }
@@ -405,7 +329,7 @@ inline bool operator!=(StringPiece x, StringPiece y) {
 }
 
 inline bool operator<(StringPiece x, StringPiece y) {
-  const stringpiece_ssize_type min_size =
+  const StringPiece::size_type min_size =
       x.size() < y.size() ? x.size() : y.size();
   const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
   return (r < 0) || (r == 0 && x.size() < y.size());
@@ -426,6 +350,10 @@ inline bool operator>=(StringPiece x, StringPiece y) {
 // allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
 
+}  // namespace stringpiece_internal
+
+using ::google::protobuf::stringpiece_internal::StringPiece;
+
 }  // namespace protobuf
 }  // namespace google
 

+ 23 - 124
src/google/protobuf/stubs/stringpiece_unittest.cc

@@ -305,16 +305,9 @@ TEST(StringPiece, STL2) {
   const StringPiece a("abcdefghijklmnopqrstuvwxyz");
   const StringPiece b("abc");
   const StringPiece c("xyz");
-  StringPiece d("foobar");
   const StringPiece e;
   const StringPiece f("123" "\0" "456", 7);
 
-  d.clear();
-  EXPECT_EQ(d.size(), 0);
-  EXPECT_TRUE(d.empty());
-  EXPECT_TRUE(d.data() == nullptr);
-  EXPECT_TRUE(d.begin() == d.end());
-
   EXPECT_EQ(StringPiece::npos, std::string::npos);
 
   EXPECT_EQ(a.find(b), 0);
@@ -324,26 +317,16 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos);
   EXPECT_EQ(b.find(c), StringPiece::npos);
   EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos);
-  EXPECT_EQ(a.find(d), 0);
   EXPECT_EQ(a.find(e), 0);
-  EXPECT_EQ(a.find(d, 12), 12);
   EXPECT_EQ(a.find(e, 17), 17);
   StringPiece g("xx not found bb");
   EXPECT_EQ(a.find(g), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find(b), StringPiece::npos);
   EXPECT_EQ(e.find(b), StringPiece::npos);
-  EXPECT_EQ(d.find(b, 4), StringPiece::npos);
   EXPECT_EQ(e.find(b, 7), StringPiece::npos);
 
   size_t empty_search_pos = std::string().find(std::string());
-  EXPECT_EQ(d.find(d), empty_search_pos);
-  EXPECT_EQ(d.find(e), empty_search_pos);
-  EXPECT_EQ(e.find(d), empty_search_pos);
   EXPECT_EQ(e.find(e), empty_search_pos);
-  EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4));
-  EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4));
-  EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4));
   EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
 
   EXPECT_EQ(a.find('a'), 0);
@@ -359,13 +342,9 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(g.find('o', 5), 8);
   EXPECT_EQ(a.find('b', 5), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find('\0'), StringPiece::npos);
   EXPECT_EQ(e.find('\0'), StringPiece::npos);
-  EXPECT_EQ(d.find('\0', 4), StringPiece::npos);
   EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
-  EXPECT_EQ(d.find('x'), StringPiece::npos);
   EXPECT_EQ(e.find('x'), StringPiece::npos);
-  EXPECT_EQ(d.find('x', 4), StringPiece::npos);
   EXPECT_EQ(e.find('x', 7), StringPiece::npos);
 
   EXPECT_EQ(a.rfind(b), 0);
@@ -376,23 +355,13 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(a.rfind(c, 0), StringPiece::npos);
   EXPECT_EQ(b.rfind(c), StringPiece::npos);
   EXPECT_EQ(b.rfind(c, 0), StringPiece::npos);
-  EXPECT_EQ(a.rfind(d), a.as_string().rfind(std::string()));
   EXPECT_EQ(a.rfind(e), a.as_string().rfind(std::string()));
-  EXPECT_EQ(a.rfind(d, 12), 12);
   EXPECT_EQ(a.rfind(e, 17), 17);
   EXPECT_EQ(a.rfind(g), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b), StringPiece::npos);
   EXPECT_EQ(e.rfind(b), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b, 4), StringPiece::npos);
   EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
-  EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
   EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(d), std::string().rfind(std::string()));
-  EXPECT_EQ(e.rfind(d), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(e), std::string().rfind(std::string()));
   EXPECT_EQ(e.rfind(e), std::string().rfind(std::string()));
 
   EXPECT_EQ(g.rfind('o'), 8);
@@ -405,9 +374,7 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(f.rfind('3'), 2);
   EXPECT_EQ(f.rfind('5'), 5);
   // empty string nonsense
-  EXPECT_EQ(d.rfind('o'), StringPiece::npos);
   EXPECT_EQ(e.rfind('o'), StringPiece::npos);
-  EXPECT_EQ(d.rfind('o', 4), StringPiece::npos);
   EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_of(b), 0);
@@ -425,13 +392,8 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(a.find_first_of(f), StringPiece::npos);
   EXPECT_EQ(f.find_first_of(a), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(a.find_first_of(d), StringPiece::npos);
   EXPECT_EQ(a.find_first_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(b), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_not_of(b), 3);
@@ -440,14 +402,9 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(f.find_first_not_of(a), 0);
   EXPECT_EQ(a.find_first_not_of(f), 0);
-  EXPECT_EQ(a.find_first_not_of(d), 0);
   EXPECT_EQ(a.find_first_not_of(e), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
 
   StringPiece h("====");
@@ -459,9 +416,7 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
   EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
 
   //  StringPiece g("xx not found bb");
@@ -483,21 +438,11 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(f.find_last_of(i, 6), 6);
   EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
@@ -509,21 +454,11 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(a.find_last_not_of(b, 3), 3);
   EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
   EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
-  EXPECT_EQ(f.find_last_not_of(d, 4), 4);
   EXPECT_EQ(f.find_last_not_of(e, 4), 4);
-  EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
@@ -533,9 +468,7 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos);
   EXPECT_EQ(b.find_last_not_of('b', 1), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
 
   EXPECT_EQ(a.substr(0, 3), b);
@@ -546,33 +479,15 @@ TEST(StringPiece, STL2) {
   EXPECT_EQ(a.substr(3, 2), "de");
   // empty string nonsense
   EXPECT_EQ(a.substr(99, 2), e);
-  EXPECT_EQ(d.substr(99), e);
-  EXPECT_EQ(d.substr(0, 99), e);
-  EXPECT_EQ(d.substr(99, 99), e);
+  EXPECT_EQ(e.substr(99), e);
+  EXPECT_EQ(e.substr(0, 99), e);
+  EXPECT_EQ(e.substr(99, 99), e);
   // use of npos
   EXPECT_EQ(a.substr(0, StringPiece::npos), a);
   EXPECT_EQ(a.substr(23, StringPiece::npos), c);
   EXPECT_EQ(a.substr(StringPiece::npos, 0), e);
   EXPECT_EQ(a.substr(StringPiece::npos, 1), e);
   EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e);
-
-  // Substring constructors.
-  EXPECT_EQ(StringPiece(a, 0, 3), b);
-  EXPECT_EQ(StringPiece(a, 23), c);
-  EXPECT_EQ(StringPiece(a, 23, 3), c);
-  EXPECT_EQ(StringPiece(a, 23, 99), c);
-  EXPECT_EQ(StringPiece(a, 0), a);
-  EXPECT_EQ(StringPiece(a, 3, 2), "de");
-  // empty string nonsense
-  EXPECT_EQ(StringPiece(d, 0, 99), e);
-  // Verify that they work taking an actual string, not just a StringPiece.
-  std::string a2 = a.as_string();
-  EXPECT_EQ(StringPiece(a2, 0, 3), b);
-  EXPECT_EQ(StringPiece(a2, 23), c);
-  EXPECT_EQ(StringPiece(a2, 23, 3), c);
-  EXPECT_EQ(StringPiece(a2, 23, 99), c);
-  EXPECT_EQ(StringPiece(a2, 0), a);
-  EXPECT_EQ(StringPiece(a2, 3, 2), "de");
 }
 
 TEST(StringPiece, Custom) {
@@ -647,23 +562,7 @@ TEST(StringPiece, Custom) {
   c.remove_suffix(c.size());
   EXPECT_EQ(c, e);
 
-  // set
-  c.set("foobar", 6);
-  EXPECT_EQ(c, a);
-  c.set("foobar", 0);
-  EXPECT_EQ(c, e);
-  c.set("foobar", 7);
-  EXPECT_NE(c, a);
-
-  c.set("foobar");
-  EXPECT_EQ(c, a);
-
-  c.set(static_cast<const void*>("foobar"), 6);
-  EXPECT_EQ(c, a);
-  c.set(static_cast<const void*>("foobar"), 0);
-  EXPECT_EQ(c, e);
-  c.set(static_cast<const void*>("foobar"), 7);
-  EXPECT_NE(c, a);
+  c = StringPiece("foobar", 7);
 
   // as_string
   std::string s3(a.as_string().c_str(), 7);
@@ -680,21 +579,25 @@ TEST(StringPiece, Custom) {
   }
 
   // Consume
-  a.set("foobar");
-  EXPECT_TRUE(a.Consume("foo"));
-  EXPECT_EQ(a, "bar");
-  EXPECT_FALSE(a.Consume("foo"));
-  EXPECT_FALSE(a.Consume("barbar"));
-  EXPECT_FALSE(a.Consume("ar"));
-  EXPECT_EQ(a, "bar");
-
-  a.set("foobar");
-  EXPECT_TRUE(a.ConsumeFromEnd("bar"));
-  EXPECT_EQ(a, "foo");
-  EXPECT_FALSE(a.ConsumeFromEnd("bar"));
-  EXPECT_FALSE(a.ConsumeFromEnd("foofoo"));
-  EXPECT_FALSE(a.ConsumeFromEnd("fo"));
-  EXPECT_EQ(a, "foo");
+  {
+    StringPiece str("foobar");
+    EXPECT_TRUE(str.Consume("foo"));
+    EXPECT_EQ(str, "bar");
+    EXPECT_FALSE(str.Consume("foo"));
+    EXPECT_FALSE(str.Consume("barbar"));
+    EXPECT_FALSE(str.Consume("ar"));
+    EXPECT_EQ(str, "bar");
+  }
+
+  {
+  StringPiece str("foobar");
+  EXPECT_TRUE(str.ConsumeFromEnd("bar"));
+  EXPECT_EQ(str, "foo");
+  EXPECT_FALSE(str.ConsumeFromEnd("bar"));
+  EXPECT_FALSE(str.ConsumeFromEnd("foofoo"));
+  EXPECT_FALSE(str.ConsumeFromEnd("fo"));
+  EXPECT_EQ(str, "foo");
+  }
 }
 
 TEST(StringPiece, Contains) {
@@ -713,10 +616,6 @@ TEST(StringPiece, NullInput) {
   EXPECT_EQ(s.data(), (const char*)nullptr);
   EXPECT_EQ(s.size(), 0);
 
-  s.set(nullptr);
-  EXPECT_EQ(s.data(), (const char*)nullptr);
-  EXPECT_EQ(s.size(), 0);
-
   // .ToString() on a StringPiece with nullptr should produce the empty string.
   EXPECT_EQ("", s.ToString());
   EXPECT_EQ("", s.as_string());

+ 1 - 1
src/google/protobuf/stubs/stringprintf.cc

@@ -162,7 +162,7 @@ std::string StringPrintfVector(const char* format,
   // that accepts an array of arguments.  The best I can do is stick
   // this COMPILE_ASSERT right next to the actual statement.
 
-  GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+  static_assert(kStringPrintfVectorMaxArgs == 32, "arg_count_mismatch");
   return StringPrintf(format,
                       cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
                       cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],

+ 6 - 5
src/google/protobuf/stubs/strutil.cc

@@ -545,7 +545,7 @@ static inline size_t CEscapedLength(StringPiece src) {
   };
 
   size_t escaped_len = 0;
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     escaped_len += c_escaped_len[c];
   }
@@ -569,7 +569,7 @@ void CEscapeAndAppend(StringPiece src, std::string *dest) {
   dest->resize(cur_dest_len + escaped_len);
   char* append_ptr = &(*dest)[cur_dest_len];
 
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     switch (c) {
       case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break;
@@ -1244,7 +1244,7 @@ char* DoubleToBuffer(double value, char* buffer) {
   // platforms these days.  Just in case some system exists where DBL_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big);
+  static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1362,7 +1362,7 @@ char* FloatToBuffer(float value, char* buffer) {
   // platforms these days.  Just in case some system exists where FLT_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big);
+  static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1619,7 +1619,8 @@ int GlobalReplaceSubstring(const std::string &substring,
   std::string tmp;
   int num_replacements = 0;
   int pos = 0;
-  for (int match_pos = s->find(substring.data(), pos, substring.length());
+  for (StringPiece::size_type match_pos =
+           s->find(substring.data(), pos, substring.length());
        match_pos != std::string::npos; pos = match_pos + substring.length(),
            match_pos = s->find(substring.data(), pos, substring.length())) {
     ++num_replacements;

+ 4 - 4
src/google/protobuf/stubs/strutil.h

@@ -377,14 +377,14 @@ inline uint32 strtou32(const char *nptr, char **endptr, int base) {
 // For now, long long is 64-bit on all the platforms we care about, so these
 // functions can simply pass the call to strto[u]ll.
 inline int64 strto64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
-                        sizeof_int64_is_not_sizeof_long_long);
+  static_assert(sizeof(int64) == sizeof(long long),
+                "sizeof_int64_is_not_sizeof_long_long");
   return strtoll(nptr, endptr, base);
 }
 
 inline uint64 strtou64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
-                        sizeof_uint64_is_not_sizeof_long_long);
+  static_assert(sizeof(uint64) == sizeof(unsigned long long),
+                "sizeof_uint64_is_not_sizeof_long_long");
   return strtoull(nptr, endptr, base);
 }
 

+ 1 - 1
src/google/protobuf/util/internal/object_writer.cc

@@ -74,7 +74,7 @@ void ObjectWriter::RenderDataPieceTo(const DataPiece& data,
       break;
     }
     case DataPiece::TYPE_BYTES: {
-      ow->RenderBytes(name, data.ToBytes().ValueOrDie());
+      ow->RenderBytes(name, data.ToBytes().value());
       break;
     }
     case DataPiece::TYPE_NULL: {

+ 1 - 1
src/google/protobuf/util/internal/proto_writer.cc

@@ -253,7 +253,7 @@ inline util::Status WriteBytes(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
   util::StatusOr<std::string> c = data.ToBytes();
   if (c.ok()) {
-    WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream);
+    WireFormatLite::WriteBytes(field_number, c.value(), stream);
   }
   return c.status();
 }

+ 1 - 1
src/google/protobuf/util/internal/protostream_objectwriter.cc

@@ -436,7 +436,7 @@ void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() {
     StrAppend(&value_storage_, value_.str());
     value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding());
   } else if (value_.type() == DataPiece::TYPE_BYTES) {
-    value_storage_ = value_.ToBytes().ValueOrDie();
+    value_storage_ = value_.ToBytes().value();
     value_ =
         DataPiece(value_storage_, true, value_.use_strict_base64_decoding());
   }