Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C++] Refactor StatusOr and StringPiece #8406

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/google/protobuf/stubs/bytestream.cc
Expand Up @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions src/google/protobuf/stubs/casts.h
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion src/google/protobuf/stubs/common.h
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/google/protobuf/stubs/logging.h
Expand Up @@ -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>

Expand Down Expand Up @@ -64,7 +65,6 @@ enum LogLevel {
#endif
};

class StringPiece;
class uint128;
namespace internal {

Expand Down
37 changes: 5 additions & 32 deletions src/google/protobuf/stubs/macros.h
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/google/protobuf/stubs/status_macros.h
Expand Up @@ -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();
}
Expand Down
4 changes: 2 additions & 2 deletions src/google/protobuf/stubs/statusor.cc
Expand Up @@ -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
48 changes: 16 additions & 32 deletions src/google/protobuf/stubs/statusor.h
Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand All @@ -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()'
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand All @@ -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("")) {
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand Down
30 changes: 14 additions & 16 deletions src/google/protobuf/stubs/statusor_test.cc
Expand Up @@ -84,15 +84,15 @@ 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) {
const int kI = 4;
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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -183,15 +183,15 @@ 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) {
const int kI = 0;
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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
Expand Down