Commit 55621d1a by Dmitri Gribenko Committed by Copybara-Service

Add nullability annotations

PiperOrigin-RevId: 589842893
Change-Id: I9657761d1f71c665582406f278c6605f6d382f6d
parent fad94622
...@@ -66,6 +66,7 @@ cc_library( ...@@ -66,6 +66,7 @@ cc_library(
deps = [ deps = [
":algorithm", ":algorithm",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/meta:type_traits", "//absl/meta:type_traits",
], ],
) )
......
...@@ -50,6 +50,7 @@ absl_cc_library( ...@@ -50,6 +50,7 @@ absl_cc_library(
absl::algorithm absl::algorithm
absl::core_headers absl::core_headers
absl::meta absl::meta
absl::nullability
PUBLIC PUBLIC
) )
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "absl/algorithm/algorithm.h" #include "absl/algorithm/algorithm.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
namespace absl { namespace absl {
......
...@@ -287,6 +287,7 @@ cc_library( ...@@ -287,6 +287,7 @@ cc_library(
":cycleclock_internal", ":cycleclock_internal",
":dynamic_annotations", ":dynamic_annotations",
":log_severity", ":log_severity",
":nullability",
":raw_logging_internal", ":raw_logging_internal",
":spinlock_wait", ":spinlock_wait",
"//absl/meta:type_traits", "//absl/meta:type_traits",
...@@ -549,6 +550,7 @@ cc_library( ...@@ -549,6 +550,7 @@ cc_library(
":base", ":base",
":config", ":config",
":core_headers", ":core_headers",
":nullability",
], ],
) )
......
...@@ -247,6 +247,7 @@ absl_cc_library( ...@@ -247,6 +247,7 @@ absl_cc_library(
absl::core_headers absl::core_headers
absl::dynamic_annotations absl::dynamic_annotations
absl::log_severity absl::log_severity
absl::nullability
absl::raw_logging_internal absl::raw_logging_internal
absl::spinlock_wait absl::spinlock_wait
absl::type_traits absl::type_traits
...@@ -475,6 +476,7 @@ absl_cc_library( ...@@ -475,6 +476,7 @@ absl_cc_library(
absl::base absl::base
absl::config absl::config
absl::core_headers absl::core_headers
absl::nullability
PUBLIC PUBLIC
) )
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/spinlock_wait.h" #include "absl/base/internal/spinlock_wait.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h" #include "absl/base/optimization.h"
#include "absl/base/port.h" #include "absl/base/port.h"
...@@ -46,7 +47,8 @@ ABSL_NAMESPACE_BEGIN ...@@ -46,7 +47,8 @@ ABSL_NAMESPACE_BEGIN
class once_flag; class once_flag;
namespace base_internal { namespace base_internal {
std::atomic<uint32_t>* ControlWord(absl::once_flag* flag); absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
absl::Nonnull<absl::once_flag*> flag);
} // namespace base_internal } // namespace base_internal
// call_once() // call_once()
...@@ -89,7 +91,8 @@ class once_flag { ...@@ -89,7 +91,8 @@ class once_flag {
once_flag& operator=(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete;
private: private:
friend std::atomic<uint32_t>* base_internal::ControlWord(once_flag* flag); friend absl::Nonnull<std::atomic<uint32_t>*> base_internal::ControlWord(
absl::Nonnull<once_flag*> flag);
std::atomic<uint32_t> control_; std::atomic<uint32_t> control_;
}; };
...@@ -103,7 +106,8 @@ namespace base_internal { ...@@ -103,7 +106,8 @@ namespace base_internal {
// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to // Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to
// initialize entities used by the scheduler implementation. // initialize entities used by the scheduler implementation.
template <typename Callable, typename... Args> template <typename Callable, typename... Args>
void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args); void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
Args&&... args);
// Disables scheduling while on stack when scheduling mode is non-cooperative. // Disables scheduling while on stack when scheduling mode is non-cooperative.
// No effect for cooperative scheduling modes. // No effect for cooperative scheduling modes.
...@@ -143,10 +147,10 @@ enum { ...@@ -143,10 +147,10 @@ enum {
}; };
template <typename Callable, typename... Args> template <typename Callable, typename... Args>
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NOINLINE void CallOnceImpl(
void CallOnceImpl(std::atomic<uint32_t>* control, absl::Nonnull<std::atomic<uint32_t>*> control,
base_internal::SchedulingMode scheduling_mode, Callable&& fn, base_internal::SchedulingMode scheduling_mode, Callable&& fn,
Args&&... args) { Args&&... args) {
#ifndef NDEBUG #ifndef NDEBUG
{ {
uint32_t old_control = control->load(std::memory_order_relaxed); uint32_t old_control = control->load(std::memory_order_relaxed);
...@@ -185,12 +189,14 @@ void CallOnceImpl(std::atomic<uint32_t>* control, ...@@ -185,12 +189,14 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
} // else *control is already kOnceDone } // else *control is already kOnceDone
} }
inline std::atomic<uint32_t>* ControlWord(once_flag* flag) { inline absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
absl::Nonnull<once_flag*> flag) {
return &flag->control_; return &flag->control_;
} }
template <typename Callable, typename... Args> template <typename Callable, typename... Args>
void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args) { void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
Args&&... args) {
std::atomic<uint32_t>* once = base_internal::ControlWord(flag); std::atomic<uint32_t>* once = base_internal::ControlWord(flag);
uint32_t s = once->load(std::memory_order_acquire); uint32_t s = once->load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) { if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "absl/base/casts.h" #include "absl/base/casts.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/unaligned_access.h" #include "absl/base/internal/unaligned_access.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h" #include "absl/base/port.h"
namespace absl { namespace absl {
...@@ -160,27 +161,27 @@ inline int64_t ToHost(int64_t x) { ...@@ -160,27 +161,27 @@ inline int64_t ToHost(int64_t x) {
} }
// Functions to do unaligned loads and stores in little-endian order. // Functions to do unaligned loads and stores in little-endian order.
inline uint16_t Load16(const void *p) { inline uint16_t Load16(absl::Nonnull<const void *> p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
} }
inline void Store16(void *p, uint16_t v) { inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
} }
inline uint32_t Load32(const void *p) { inline uint32_t Load32(absl::Nonnull<const void *> p) {
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
} }
inline void Store32(void *p, uint32_t v) { inline void Store32(absl::Nonnull<void *> p, uint32_t v) {
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
} }
inline uint64_t Load64(const void *p) { inline uint64_t Load64(absl::Nonnull<const void *> p) {
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
} }
inline void Store64(void *p, uint64_t v) { inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
} }
...@@ -250,27 +251,27 @@ inline int64_t ToHost(int64_t x) { ...@@ -250,27 +251,27 @@ inline int64_t ToHost(int64_t x) {
} }
// Functions to do unaligned loads and stores in big-endian order. // Functions to do unaligned loads and stores in big-endian order.
inline uint16_t Load16(const void *p) { inline uint16_t Load16(absl::Nonnull<const void *> p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
} }
inline void Store16(void *p, uint16_t v) { inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
} }
inline uint32_t Load32(const void *p) { inline uint32_t Load32(absl::Nonnull<const void *> p) {
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
} }
inline void Store32(void *p, uint32_t v) { inline void Store32(absl::Nonnull<void *>p, uint32_t v) {
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
} }
inline uint64_t Load64(const void *p) { inline uint64_t Load64(absl::Nonnull<const void *> p) {
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
} }
inline void Store64(void *p, uint64_t v) { inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
// unaligned APIs // unaligned APIs
...@@ -35,29 +36,35 @@ namespace absl { ...@@ -35,29 +36,35 @@ namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace base_internal { namespace base_internal {
inline uint16_t UnalignedLoad16(const void *p) { inline uint16_t UnalignedLoad16(absl::Nonnull<const void *> p) {
uint16_t t; uint16_t t;
memcpy(&t, p, sizeof t); memcpy(&t, p, sizeof t);
return t; return t;
} }
inline uint32_t UnalignedLoad32(const void *p) { inline uint32_t UnalignedLoad32(absl::Nonnull<const void *> p) {
uint32_t t; uint32_t t;
memcpy(&t, p, sizeof t); memcpy(&t, p, sizeof t);
return t; return t;
} }
inline uint64_t UnalignedLoad64(const void *p) { inline uint64_t UnalignedLoad64(absl::Nonnull<const void *> p) {
uint64_t t; uint64_t t;
memcpy(&t, p, sizeof t); memcpy(&t, p, sizeof t);
return t; return t;
} }
inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); } inline void UnalignedStore16(absl::Nonnull<void *> p, uint16_t v) {
memcpy(p, &v, sizeof v);
}
inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } inline void UnalignedStore32(absl::Nonnull<void *> p, uint32_t v) {
memcpy(p, &v, sizeof v);
}
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } inline void UnalignedStore64(absl::Nonnull<void *> p, uint64_t v) {
memcpy(p, &v, sizeof v);
}
} // namespace base_internal } // namespace base_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -54,6 +54,7 @@ cc_library( ...@@ -54,6 +54,7 @@ cc_library(
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:no_destructor", "//absl/base:no_destructor",
"//absl/base:nullability",
"//absl/base:raw_logging_internal", "//absl/base:raw_logging_internal",
"//absl/base:strerror", "//absl/base:strerror",
"//absl/container:inlined_vector", "//absl/container:inlined_vector",
...@@ -100,6 +101,7 @@ cc_library( ...@@ -100,6 +101,7 @@ cc_library(
"//absl/base", "//absl/base",
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/base:raw_logging_internal", "//absl/base:raw_logging_internal",
"//absl/meta:type_traits", "//absl/meta:type_traits",
"//absl/strings", "//absl/strings",
......
...@@ -37,6 +37,7 @@ absl_cc_library( ...@@ -37,6 +37,7 @@ absl_cc_library(
absl::inlined_vector absl::inlined_vector
absl::memory absl::memory
absl::no_destructor absl::no_destructor
absl::nullability
absl::optional absl::optional
absl::raw_logging_internal absl::raw_logging_internal
absl::span absl::span
...@@ -76,6 +77,7 @@ absl_cc_library( ...@@ -76,6 +77,7 @@ absl_cc_library(
absl::base absl::base
absl::config absl::config
absl::core_headers absl::core_headers
absl::nullability
absl::raw_logging_internal absl::raw_logging_internal
absl::status absl::status
absl::strings absl::strings
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/debugging/stacktrace.h" #include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h" #include "absl/debugging/symbolize.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
...@@ -187,7 +188,7 @@ bool StatusRep::operator==(const StatusRep& other) const { ...@@ -187,7 +188,7 @@ bool StatusRep::operator==(const StatusRep& other) const {
return true; return true;
} }
StatusRep* StatusRep::CloneAndUnref() const { absl::Nonnull<StatusRep*> StatusRep::CloneAndUnref() const {
// Optimization: no need to create a clone if we already have a refcount of 1. // Optimization: no need to create a clone if we already have a refcount of 1.
if (ref_.load(std::memory_order_acquire) == 1) { if (ref_.load(std::memory_order_acquire) == 1) {
// All StatusRep instances are heap allocated and mutable, therefore this // All StatusRep instances are heap allocated and mutable, therefore this
...@@ -233,8 +234,9 @@ absl::StatusCode MapToLocalCode(int value) { ...@@ -233,8 +234,9 @@ absl::StatusCode MapToLocalCode(int value) {
} }
} }
std::string* MakeCheckFailString(const absl::Status* status, absl::Nonnull<std::string*> MakeCheckFailString(
const char* prefix) { absl::Nonnull<const absl::Status*> status,
absl::Nonnull<const char*> prefix) {
return new std::string( return new std::string(
absl::StrCat(prefix, " (", absl::StrCat(prefix, " (",
status->ToString(StatusToStringMode::kWithEverything), ")")); status->ToString(StatusToStringMode::kWithEverything), ")"));
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/strings/cord.h" #include "absl/strings/cord.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -99,7 +100,7 @@ class StatusRep { ...@@ -99,7 +100,7 @@ class StatusRep {
// Returns an equivalent heap allocated StatusRep with refcount 1. // Returns an equivalent heap allocated StatusRep with refcount 1.
// //
// `this` is not safe to be used after calling as it may have been deleted. // `this` is not safe to be used after calling as it may have been deleted.
StatusRep* CloneAndUnref() const; absl::Nonnull<StatusRep*> CloneAndUnref() const;
private: private:
mutable std::atomic<int32_t> ref_; mutable std::atomic<int32_t> ref_;
...@@ -119,8 +120,9 @@ absl::StatusCode MapToLocalCode(int value); ...@@ -119,8 +120,9 @@ absl::StatusCode MapToLocalCode(int value);
// //
// This is an internal implementation detail for Abseil logging. // This is an internal implementation detail for Abseil logging.
ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
std::string* MakeCheckFailString(const absl::Status* status, absl::Nonnull<std::string*> MakeCheckFailString(
const char* prefix); absl::Nonnull<const absl::Status*> status,
absl::Nonnull<const char*> prefix);
} // namespace status_internal } // namespace status_internal
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <utility> #include <utility>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/utility/utility.h" #include "absl/utility/utility.h"
...@@ -123,7 +124,7 @@ using IsForwardingAssignmentValid = absl::disjunction< ...@@ -123,7 +124,7 @@ using IsForwardingAssignmentValid = absl::disjunction<
class Helper { class Helper {
public: public:
// Move type-agnostic error handling to the .cc. // Move type-agnostic error handling to the .cc.
static void HandleInvalidStatusCtorArg(Status*); static void HandleInvalidStatusCtorArg(absl::Nonnull<Status*>);
ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status); ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
}; };
...@@ -131,7 +132,8 @@ class Helper { ...@@ -131,7 +132,8 @@ class Helper {
// the constructor. // the constructor.
// This abstraction is here mostly for the gcc performance fix. // This abstraction is here mostly for the gcc performance fix.
template <typename T, typename... Args> template <typename T, typename... Args>
ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) { ABSL_ATTRIBUTE_NONNULL(1)
void PlacementNew(absl::Nonnull<void*> p, Args&&... args) {
new (p) T(std::forward<Args>(args)...); new (p) T(std::forward<Args>(args)...);
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "absl/base/internal/strerror.h" #include "absl/base/internal/strerror.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/no_destructor.h" #include "absl/base/no_destructor.h"
#include "absl/base/nullability.h"
#include "absl/debugging/stacktrace.h" #include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h" #include "absl/debugging/symbolize.h"
#include "absl/status/internal/status_internal.h" #include "absl/status/internal/status_internal.h"
...@@ -90,7 +91,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code) { ...@@ -90,7 +91,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code) {
return os << StatusCodeToString(code); return os << StatusCodeToString(code);
} }
const std::string* Status::EmptyString() { absl::Nonnull<const std::string*> Status::EmptyString() {
static const absl::NoDestructor<std::string> kEmpty; static const absl::NoDestructor<std::string> kEmpty;
return kEmpty.get(); return kEmpty.get();
} }
...@@ -99,7 +100,7 @@ const std::string* Status::EmptyString() { ...@@ -99,7 +100,7 @@ const std::string* Status::EmptyString() {
constexpr const char Status::kMovedFromString[]; constexpr const char Status::kMovedFromString[];
#endif #endif
const std::string* Status::MovedFromString() { absl::Nonnull<const std::string*> Status::MovedFromString() {
static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString); static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);
return kMovedFrom.get(); return kMovedFrom.get();
} }
...@@ -111,7 +112,8 @@ Status::Status(absl::StatusCode code, absl::string_view msg) ...@@ -111,7 +112,8 @@ Status::Status(absl::StatusCode code, absl::string_view msg)
} }
} }
status_internal::StatusRep* Status::PrepareToModify(uintptr_t rep) { absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify(
uintptr_t rep) {
if (IsInlined(rep)) { if (IsInlined(rep)) {
return new status_internal::StatusRep(InlinedRepToCode(rep), return new status_internal::StatusRep(InlinedRepToCode(rep),
absl::string_view(), nullptr); absl::string_view(), nullptr);
...@@ -412,7 +414,7 @@ Status ErrnoToStatus(int error_number, absl::string_view message) { ...@@ -412,7 +414,7 @@ Status ErrnoToStatus(int error_number, absl::string_view message) {
MessageForErrnoToStatus(error_number, message)); MessageForErrnoToStatus(error_number, message));
} }
const char* StatusMessageAsCStr(const Status& status) { absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) {
// As an internal implementation detail, we guarantee that if status.message() // As an internal implementation detail, we guarantee that if status.message()
// is non-empty, then the resulting string_view is null terminated. // is non-empty, then the resulting string_view is null terminated.
auto sv_message = status.message(); auto sv_message = status.message();
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h" #include "absl/base/optimization.h"
#include "absl/functional/function_ref.h" #include "absl/functional/function_ref.h"
#include "absl/status/internal/status_internal.h" #include "absl/status/internal/status_internal.h"
...@@ -622,14 +623,15 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final { ...@@ -622,14 +623,15 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final {
// REQUIRES: !ok() // REQUIRES: !ok()
// Ensures rep is not inlined or shared with any other Status. // Ensures rep is not inlined or shared with any other Status.
static status_internal::StatusRep* PrepareToModify(uintptr_t rep); static absl::Nonnull<status_internal::StatusRep*> PrepareToModify(
uintptr_t rep);
// MSVC 14.0 limitation requires the const. // MSVC 14.0 limitation requires the const.
static constexpr const char kMovedFromString[] = static constexpr const char kMovedFromString[] =
"Status accessed after move."; "Status accessed after move.";
static const std::string* EmptyString(); static absl::Nonnull<const std::string*> EmptyString();
static const std::string* MovedFromString(); static absl::Nonnull<const std::string*> MovedFromString();
// Returns whether rep contains an inlined representation. // Returns whether rep contains an inlined representation.
// See rep_ for details. // See rep_ for details.
...@@ -648,7 +650,8 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final { ...@@ -648,7 +650,8 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final {
// Converts between StatusRep* and the external uintptr_t representation used // Converts between StatusRep* and the external uintptr_t representation used
// by rep_. See rep_ for details. // by rep_. See rep_ for details.
static uintptr_t PointerToRep(status_internal::StatusRep* r); static uintptr_t PointerToRep(status_internal::StatusRep* r);
static const status_internal::StatusRep* RepToPointer(uintptr_t r); static absl::Nonnull<const status_internal::StatusRep*> RepToPointer(
uintptr_t r);
static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode); static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode);
...@@ -899,12 +902,14 @@ constexpr uintptr_t Status::MovedFromRep() { ...@@ -899,12 +902,14 @@ constexpr uintptr_t Status::MovedFromRep() {
return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;
} }
inline const status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { inline absl::Nonnull<const status_internal::StatusRep*> Status::RepToPointer(
uintptr_t rep) {
assert(!IsInlined(rep)); assert(!IsInlined(rep));
return reinterpret_cast<const status_internal::StatusRep*>(rep); return reinterpret_cast<const status_internal::StatusRep*>(rep);
} }
inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { inline uintptr_t Status::PointerToRep(
absl::Nonnull<status_internal::StatusRep*> rep) {
return reinterpret_cast<uintptr_t>(rep); return reinterpret_cast<uintptr_t>(rep);
} }
...@@ -929,7 +934,7 @@ inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } ...@@ -929,7 +934,7 @@ inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
// If the status's message is empty, the empty string is returned. // If the status's message is empty, the empty string is returned.
// //
// StatusMessageAsCStr exists for C support. Use `status.message()` in C++. // StatusMessageAsCStr exists for C support. Use `status.message()` in C++.
const char* StatusMessageAsCStr( absl::Nonnull<const char*> StatusMessageAsCStr(
const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND); const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND);
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <string> #include <string>
#include "absl/base/nullability.h"
#include "absl/strings/cord.h" #include "absl/strings/cord.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
...@@ -34,8 +35,8 @@ namespace status_internal { ...@@ -34,8 +35,8 @@ namespace status_internal {
// NOTE: This is an internal API and the design is subject to change in the // NOTE: This is an internal API and the design is subject to change in the
// future in a non-backward-compatible way. Since it's only meant for debugging // future in a non-backward-compatible way. Since it's only meant for debugging
// purpose, you should not rely on it in any critical logic. // purpose, you should not rely on it in any critical logic.
using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view, using StatusPayloadPrinter = absl::Nullable<absl::optional<std::string> (*)(
const absl::Cord&); absl::string_view, const absl::Cord&)>;
// Sets the global payload printer. Only one printer should be set per process. // Sets the global payload printer. Only one printer should be set per process.
// If multiple printers are set, it's undefined which one will be used. // If multiple printers are set, it's undefined which one will be used.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "absl/base/call_once.h" #include "absl/base/call_once.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/nullability.h"
#include "absl/status/internal/statusor_internal.h" #include "absl/status/internal/statusor_internal.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
...@@ -54,7 +55,7 @@ BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) { ...@@ -54,7 +55,7 @@ BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {
BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other) BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
: status_(std::move(other.status_)) {} : status_(std::move(other.status_)) {}
const char* BadStatusOrAccess::what() const noexcept { absl::Nonnull<const char*> BadStatusOrAccess::what() const noexcept {
InitWhat(); InitWhat();
return what_.c_str(); return what_.c_str();
} }
...@@ -69,7 +70,7 @@ void BadStatusOrAccess::InitWhat() const { ...@@ -69,7 +70,7 @@ void BadStatusOrAccess::InitWhat() const {
namespace internal_statusor { namespace internal_statusor {
void Helper::HandleInvalidStatusCtorArg(absl::Status* status) { void Helper::HandleInvalidStatusCtorArg(absl::Nonnull<absl::Status*> status) {
const char* kMessage = const char* kMessage =
"An OK status is not a valid constructor argument to StatusOr<T>"; "An OK status is not a valid constructor argument to StatusOr<T>";
#ifdef NDEBUG #ifdef NDEBUG
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <utility> #include <utility>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/call_once.h" #include "absl/base/call_once.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/status/internal/statusor_internal.h" #include "absl/status/internal/statusor_internal.h"
...@@ -88,7 +89,7 @@ class BadStatusOrAccess : public std::exception { ...@@ -88,7 +89,7 @@ class BadStatusOrAccess : public std::exception {
// //
// The pointer of this string is guaranteed to be valid until any non-const // The pointer of this string is guaranteed to be valid until any non-const
// function is invoked on the exception object. // function is invoked on the exception object.
const char* what() const noexcept override; absl::Nonnull<const char*> what() const noexcept override;
// BadStatusOrAccess::status() // BadStatusOrAccess::status()
// //
...@@ -750,13 +751,13 @@ T&& StatusOr<T>::operator*() && { ...@@ -750,13 +751,13 @@ T&& StatusOr<T>::operator*() && {
} }
template <typename T> template <typename T>
const T* StatusOr<T>::operator->() const { absl::Nonnull<const T*> StatusOr<T>::operator->() const {
this->EnsureOk(); this->EnsureOk();
return &this->data_; return &this->data_;
} }
template <typename T> template <typename T>
T* StatusOr<T>::operator->() { absl::Nonnull<T*> StatusOr<T>::operator->() {
this->EnsureOk(); this->EnsureOk();
return &this->data_; return &this->data_;
} }
......
...@@ -41,6 +41,7 @@ cc_library( ...@@ -41,6 +41,7 @@ cc_library(
"//absl/base", "//absl/base",
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/base:throw_delegate", "//absl/base:throw_delegate",
], ],
) )
...@@ -103,6 +104,7 @@ cc_library( ...@@ -103,6 +104,7 @@ cc_library(
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:endian", "//absl/base:endian",
"//absl/base:nullability",
"//absl/base:raw_logging_internal", "//absl/base:raw_logging_internal",
"//absl/base:throw_delegate", "//absl/base:throw_delegate",
"//absl/memory", "//absl/memory",
...@@ -588,6 +590,7 @@ cc_library( ...@@ -588,6 +590,7 @@ cc_library(
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:endian", "//absl/base:endian",
"//absl/base:nullability",
"//absl/base:raw_logging_internal", "//absl/base:raw_logging_internal",
"//absl/container:inlined_vector", "//absl/container:inlined_vector",
"//absl/crc:crc32c", "//absl/crc:crc32c",
...@@ -869,6 +872,7 @@ cc_library( ...@@ -869,6 +872,7 @@ cc_library(
":strings", ":strings",
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
], ],
) )
...@@ -1250,6 +1254,7 @@ cc_library( ...@@ -1250,6 +1254,7 @@ cc_library(
":string_view", ":string_view",
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/types:span", "//absl/types:span",
], ],
) )
......
...@@ -27,6 +27,7 @@ absl_cc_library( ...@@ -27,6 +27,7 @@ absl_cc_library(
absl::base absl::base
absl::config absl::config
absl::core_headers absl::core_headers
absl::nullability
absl::throw_delegate absl::throw_delegate
PUBLIC PUBLIC
) )
...@@ -84,6 +85,7 @@ absl_cc_library( ...@@ -84,6 +85,7 @@ absl_cc_library(
absl::endian absl::endian
absl::int128 absl::int128
absl::memory absl::memory
absl::nullability
absl::raw_logging_internal absl::raw_logging_internal
absl::throw_delegate absl::throw_delegate
absl::type_traits absl::type_traits
...@@ -472,6 +474,7 @@ absl_cc_library( ...@@ -472,6 +474,7 @@ absl_cc_library(
DEPS DEPS
absl::config absl::config
absl::core_headers absl::core_headers
absl::nullability
absl::span absl::span
absl::str_format_internal absl::str_format_internal
absl::string_view absl::string_view
...@@ -986,6 +989,7 @@ absl_cc_library( ...@@ -986,6 +989,7 @@ absl_cc_library(
absl::endian absl::endian
absl::function_ref absl::function_ref
absl::inlined_vector absl::inlined_vector
absl::nullability
absl::optional absl::optional
absl::raw_logging_internal absl::raw_logging_internal
absl::span absl::span
...@@ -1043,6 +1047,7 @@ absl_cc_library( ...@@ -1043,6 +1047,7 @@ absl_cc_library(
absl::cordz_statistics absl::cordz_statistics
absl::cordz_update_tracker absl::cordz_update_tracker
absl::core_headers absl::core_headers
absl::nullability
absl::strings absl::strings
TESTONLY TESTONLY
) )
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <string> #include <string>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -174,7 +175,8 @@ constexpr bool AsciiInAZRange(unsigned char c) { ...@@ -174,7 +175,8 @@ constexpr bool AsciiInAZRange(unsigned char c) {
} }
template <bool ToUpper> template <bool ToUpper>
constexpr void AsciiStrCaseFold(char* p, char* end) { constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p,
absl::Nonnull<char*> end) {
// The upper- and lowercase versions of ASCII characters differ by only 1 bit. // The upper- and lowercase versions of ASCII characters differ by only 1 bit.
// When we need to flip the case, we can xor with this bit to achieve the // When we need to flip the case, we can xor with this bit to achieve the
// desired result. Note that the choice of 'a' and 'A' here is arbitrary. We // desired result. Note that the choice of 'a' and 'A' here is arbitrary. We
...@@ -215,17 +217,17 @@ static_assert(ValidateAsciiCasefold() == 0, "error in case conversion"); ...@@ -215,17 +217,17 @@ static_assert(ValidateAsciiCasefold() == 0, "error in case conversion");
} // namespace ascii_internal } // namespace ascii_internal
void AsciiStrToLower(std::string* s) { void AsciiStrToLower(absl::Nonnull<std::string*> s) {
char* p = &(*s)[0]; // Guaranteed to be valid for empty strings char* p = &(*s)[0]; // Guaranteed to be valid for empty strings
return ascii_internal::AsciiStrCaseFold<false>(p, p + s->size()); return ascii_internal::AsciiStrCaseFold<false>(p, p + s->size());
} }
void AsciiStrToUpper(std::string* s) { void AsciiStrToUpper(absl::Nonnull<std::string*> s) {
char* p = &(*s)[0]; // Guaranteed to be valid for empty strings char* p = &(*s)[0]; // Guaranteed to be valid for empty strings
return ascii_internal::AsciiStrCaseFold<true>(p, p + s->size()); return ascii_internal::AsciiStrCaseFold<true>(p, p + s->size());
} }
void RemoveExtraAsciiWhitespace(std::string* str) { void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str) {
auto stripped = StripAsciiWhitespace(*str); auto stripped = StripAsciiWhitespace(*str);
if (stripped.empty()) { if (stripped.empty()) {
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
namespace absl { namespace absl {
...@@ -166,7 +167,7 @@ inline char ascii_tolower(unsigned char c) { ...@@ -166,7 +167,7 @@ inline char ascii_tolower(unsigned char c) {
} }
// Converts the characters in `s` to lowercase, changing the contents of `s`. // Converts the characters in `s` to lowercase, changing the contents of `s`.
void AsciiStrToLower(std::string* s); void AsciiStrToLower(absl::Nonnull<std::string*> s);
// Creates a lowercase string from a given absl::string_view. // Creates a lowercase string from a given absl::string_view.
ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) { ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) {
...@@ -184,7 +185,7 @@ inline char ascii_toupper(unsigned char c) { ...@@ -184,7 +185,7 @@ inline char ascii_toupper(unsigned char c) {
} }
// Converts the characters in `s` to uppercase, changing the contents of `s`. // Converts the characters in `s` to uppercase, changing the contents of `s`.
void AsciiStrToUpper(std::string* s); void AsciiStrToUpper(absl::Nonnull<std::string*> s);
// Creates an uppercase string from a given absl::string_view. // Creates an uppercase string from a given absl::string_view.
ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) { ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) {
...@@ -202,7 +203,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace( ...@@ -202,7 +203,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace(
} }
// Strips in place whitespace from the beginning of the given string. // Strips in place whitespace from the beginning of the given string.
inline void StripLeadingAsciiWhitespace(std::string* str) { inline void StripLeadingAsciiWhitespace(absl::Nonnull<std::string*> str) {
auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace); auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace);
str->erase(str->begin(), it); str->erase(str->begin(), it);
} }
...@@ -216,7 +217,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace( ...@@ -216,7 +217,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace(
} }
// Strips in place whitespace from the end of the given string // Strips in place whitespace from the end of the given string
inline void StripTrailingAsciiWhitespace(std::string* str) { inline void StripTrailingAsciiWhitespace(absl::Nonnull<std::string*> str) {
auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace); auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace);
str->erase(static_cast<size_t>(str->rend() - it)); str->erase(static_cast<size_t>(str->rend() - it));
} }
...@@ -229,13 +230,13 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace( ...@@ -229,13 +230,13 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace(
} }
// Strips in place whitespace from both ends of the given string // Strips in place whitespace from both ends of the given string
inline void StripAsciiWhitespace(std::string* str) { inline void StripAsciiWhitespace(absl::Nonnull<std::string*> str) {
StripTrailingAsciiWhitespace(str); StripTrailingAsciiWhitespace(str);
StripLeadingAsciiWhitespace(str); StripLeadingAsciiWhitespace(str);
} }
// Removes leading, trailing, and consecutive internal whitespace. // Removes leading, trailing, and consecutive internal whitespace.
void RemoveExtraAsciiWhitespace(std::string*); void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str);
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "absl/base/casts.h" #include "absl/base/casts.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/numeric/bits.h" #include "absl/numeric/bits.h"
#include "absl/numeric/int128.h" #include "absl/numeric/int128.h"
#include "absl/strings/internal/charconv_bigint.h" #include "absl/strings/internal/charconv_bigint.h"
...@@ -119,7 +120,7 @@ struct FloatTraits<double> { ...@@ -119,7 +120,7 @@ struct FloatTraits<double> {
// Parsing a smaller N will produce something finite. // Parsing a smaller N will produce something finite.
static constexpr int kEiselLemireMaxExclusiveExp10 = 309; static constexpr int kEiselLemireMaxExclusiveExp10 = 309;
static double MakeNan(const char* tagp) { static double MakeNan(absl::Nullable<const char*> tagp) {
#if ABSL_HAVE_BUILTIN(__builtin_nan) #if ABSL_HAVE_BUILTIN(__builtin_nan)
// Use __builtin_nan() if available since it has a fix for // Use __builtin_nan() if available since it has a fix for
// https://bugs.llvm.org/show_bug.cgi?id=37778 // https://bugs.llvm.org/show_bug.cgi?id=37778
...@@ -192,7 +193,7 @@ struct FloatTraits<float> { ...@@ -192,7 +193,7 @@ struct FloatTraits<float> {
static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18; static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18;
static constexpr int kEiselLemireMaxExclusiveExp10 = 39; static constexpr int kEiselLemireMaxExclusiveExp10 = 39;
static float MakeNan(const char* tagp) { static float MakeNan(absl::Nullable<const char*> tagp) {
#if ABSL_HAVE_BUILTIN(__builtin_nanf) #if ABSL_HAVE_BUILTIN(__builtin_nanf)
// Use __builtin_nanf() if available since it has a fix for // Use __builtin_nanf() if available since it has a fix for
// https://bugs.llvm.org/show_bug.cgi?id=37778 // https://bugs.llvm.org/show_bug.cgi?id=37778
...@@ -344,7 +345,7 @@ int NormalizedShiftSize(int mantissa_width, int binary_exponent) { ...@@ -344,7 +345,7 @@ int NormalizedShiftSize(int mantissa_width, int binary_exponent) {
// `value` must be wider than the requested bit width. // `value` must be wider than the requested bit width.
// //
// Returns the number of bits shifted. // Returns the number of bits shifted.
int TruncateToBitWidth(int bit_width, uint128* value) { int TruncateToBitWidth(int bit_width, absl::Nonnull<uint128*> value) {
const int current_bit_width = BitWidth(*value); const int current_bit_width = BitWidth(*value);
const int shift = current_bit_width - bit_width; const int shift = current_bit_width - bit_width;
*value >>= shift; *value >>= shift;
...@@ -356,7 +357,7 @@ int TruncateToBitWidth(int bit_width, uint128* value) { ...@@ -356,7 +357,7 @@ int TruncateToBitWidth(int bit_width, uint128* value) {
// the appropriate double, and returns true. // the appropriate double, and returns true.
template <typename FloatType> template <typename FloatType>
bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
FloatType* value) { absl::Nonnull<FloatType*> value) {
if (input.type == strings_internal::FloatType::kNan) { if (input.type == strings_internal::FloatType::kNan) {
// A bug in both clang < 7 and gcc would cause the compiler to optimize // A bug in both clang < 7 and gcc would cause the compiler to optimize
// away the buffer we are building below. Declaring the buffer volatile // away the buffer we are building below. Declaring the buffer volatile
...@@ -405,7 +406,8 @@ bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, ...@@ -405,7 +406,8 @@ bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
// number is stored in *value. // number is stored in *value.
template <typename FloatType> template <typename FloatType>
void EncodeResult(const CalculatedFloat& calculated, bool negative, void EncodeResult(const CalculatedFloat& calculated, bool negative,
absl::from_chars_result* result, FloatType* value) { absl::Nonnull<absl::from_chars_result*> result,
absl::Nonnull<FloatType*> value) {
if (calculated.exponent == kOverflow) { if (calculated.exponent == kOverflow) {
result->ec = std::errc::result_out_of_range; result->ec = std::errc::result_out_of_range;
*value = negative ? -std::numeric_limits<FloatType>::max() *value = negative ? -std::numeric_limits<FloatType>::max()
...@@ -451,7 +453,7 @@ void EncodeResult(const CalculatedFloat& calculated, bool negative, ...@@ -451,7 +453,7 @@ void EncodeResult(const CalculatedFloat& calculated, bool negative,
// Zero and negative values of `shift` are accepted, in which case the word is // Zero and negative values of `shift` are accepted, in which case the word is
// shifted left, as necessary. // shifted left, as necessary.
uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact, uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,
bool* output_exact) { absl::Nonnull<bool*> output_exact) {
if (shift <= 0) { if (shift <= 0) {
*output_exact = input_exact; *output_exact = input_exact;
return static_cast<uint64_t>(value << -shift); return static_cast<uint64_t>(value << -shift);
...@@ -685,7 +687,8 @@ CalculatedFloat CalculateFromParsedDecimal( ...@@ -685,7 +687,8 @@ CalculatedFloat CalculateFromParsedDecimal(
// this function returns false) is both fast and correct. // this function returns false) is both fast and correct.
template <typename FloatType> template <typename FloatType>
bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative, bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,
FloatType* value, std::errc* ec) { absl::Nonnull<FloatType*> value,
absl::Nonnull<std::errc*> ec) {
uint64_t man = input.mantissa; uint64_t man = input.mantissa;
int exp10 = input.exponent; int exp10 = input.exponent;
if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) { if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) {
...@@ -858,7 +861,8 @@ bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative, ...@@ -858,7 +861,8 @@ bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,
} }
template <typename FloatType> template <typename FloatType>
from_chars_result FromCharsImpl(const char* first, const char* last, from_chars_result FromCharsImpl(absl::Nonnull<const char*> first,
absl::Nonnull<const char*> last,
FloatType& value, chars_format fmt_flags) { FloatType& value, chars_format fmt_flags) {
from_chars_result result; from_chars_result result;
result.ptr = first; // overwritten on successful parse result.ptr = first; // overwritten on successful parse
...@@ -944,12 +948,14 @@ from_chars_result FromCharsImpl(const char* first, const char* last, ...@@ -944,12 +948,14 @@ from_chars_result FromCharsImpl(const char* first, const char* last,
} }
} // namespace } // namespace
from_chars_result from_chars(const char* first, const char* last, double& value, from_chars_result from_chars(absl::Nonnull<const char*> first,
absl::Nonnull<const char*> last, double& value,
chars_format fmt) { chars_format fmt) {
return FromCharsImpl(first, last, value, fmt); return FromCharsImpl(first, last, value, fmt);
} }
from_chars_result from_chars(const char* first, const char* last, float& value, from_chars_result from_chars(absl::Nonnull<const char*> first,
absl::Nonnull<const char*> last, float& value,
chars_format fmt) { chars_format fmt) {
return FromCharsImpl(first, last, value, fmt); return FromCharsImpl(first, last, value, fmt);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <system_error> // NOLINT(build/c++11) #include <system_error> // NOLINT(build/c++11)
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -44,7 +45,7 @@ enum class chars_format { ...@@ -44,7 +45,7 @@ enum class chars_format {
// characters that were successfully parsed. If none was found, `ptr` is set // characters that were successfully parsed. If none was found, `ptr` is set
// to the `first` argument to from_chars. // to the `first` argument to from_chars.
struct from_chars_result { struct from_chars_result {
const char* ptr; absl::Nonnull<const char*> ptr;
std::errc ec; std::errc ec;
}; };
...@@ -76,11 +77,13 @@ struct from_chars_result { ...@@ -76,11 +77,13 @@ struct from_chars_result {
// format that strtod() accepts, except that a "0x" prefix is NOT matched. // format that strtod() accepts, except that a "0x" prefix is NOT matched.
// (In particular, in `hex` mode, the input "0xff" results in the largest // (In particular, in `hex` mode, the input "0xff" results in the largest
// matching pattern "0".) // matching pattern "0".)
absl::from_chars_result from_chars(const char* first, const char* last, absl::from_chars_result from_chars(absl::Nonnull<const char*> first,
absl::Nonnull<const char*> last,
double& value, // NOLINT double& value, // NOLINT
chars_format fmt = chars_format::general); chars_format fmt = chars_format::general);
absl::from_chars_result from_chars(const char* first, const char* last, absl::from_chars_result from_chars(absl::Nonnull<const char*> first,
absl::Nonnull<const char*> last,
float& value, // NOLINT float& value, // NOLINT
chars_format fmt = chars_format::general); chars_format fmt = chars_format::general);
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/optimization.h" #include "absl/base/optimization.h"
#include "absl/base/nullability.h"
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/crc/crc32c.h" #include "absl/crc/crc32c.h"
#include "absl/crc/internal/crc_cord_state.h" #include "absl/crc/internal/crc_cord_state.h"
...@@ -74,18 +75,21 @@ using ::absl::cord_internal::kMinFlatLength; ...@@ -74,18 +75,21 @@ using ::absl::cord_internal::kMinFlatLength;
using ::absl::cord_internal::kInlinedVectorSize; using ::absl::cord_internal::kInlinedVectorSize;
using ::absl::cord_internal::kMaxBytesToCopy; using ::absl::cord_internal::kMaxBytesToCopy;
static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, static void DumpNode(absl::Nonnull<CordRep*> rep, bool include_data,
int indent = 0); absl::Nonnull<std::ostream*> os, int indent = 0);
static bool VerifyNode(CordRep* root, CordRep* start_node); static bool VerifyNode(absl::Nonnull<CordRep*> root,
absl::Nonnull<CordRep*> start_node);
static inline CordRep* VerifyTree(CordRep* node) { static inline absl::Nullable<CordRep*> VerifyTree(
absl::Nullable<CordRep*> node) {
assert(node == nullptr || VerifyNode(node, node)); assert(node == nullptr || VerifyNode(node, node));
static_cast<void>(&VerifyNode); static_cast<void>(&VerifyNode);
return node; return node;
} }
static CordRepFlat* CreateFlat(const char* data, size_t length, static absl::Nonnull<CordRepFlat*> CreateFlat(absl::Nonnull<const char*> data,
size_t alloc_hint) { size_t length,
size_t alloc_hint) {
CordRepFlat* flat = CordRepFlat::New(length + alloc_hint); CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
flat->length = length; flat->length = length;
memcpy(flat->Data(), data, length); memcpy(flat->Data(), data, length);
...@@ -94,7 +98,8 @@ static CordRepFlat* CreateFlat(const char* data, size_t length, ...@@ -94,7 +98,8 @@ static CordRepFlat* CreateFlat(const char* data, size_t length,
// Creates a new flat or Btree out of the specified array. // Creates a new flat or Btree out of the specified array.
// The returned node has a refcount of 1. // The returned node has a refcount of 1.
static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) { static absl::Nonnull<CordRep*> NewBtree(absl::Nonnull<const char*> data,
size_t length, size_t alloc_hint) {
if (length <= kMaxFlatLength) { if (length <= kMaxFlatLength) {
return CreateFlat(data, length, alloc_hint); return CreateFlat(data, length, alloc_hint);
} }
...@@ -107,14 +112,16 @@ static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) { ...@@ -107,14 +112,16 @@ static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) {
// Create a new tree out of the specified array. // Create a new tree out of the specified array.
// The returned node has a refcount of 1. // The returned node has a refcount of 1.
static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) { static absl::Nullable<CordRep*> NewTree(absl::Nullable<const char*> data,
size_t length, size_t alloc_hint) {
if (length == 0) return nullptr; if (length == 0) return nullptr;
return NewBtree(data, length, alloc_hint); return NewBtree(data, length, alloc_hint);
} }
namespace cord_internal { namespace cord_internal {
void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { void InitializeCordRepExternal(absl::string_view data,
absl::Nonnull<CordRepExternal*> rep) {
assert(!data.empty()); assert(!data.empty());
rep->length = data.size(); rep->length = data.size();
rep->tag = EXTERNAL; rep->tag = EXTERNAL;
...@@ -128,7 +135,7 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { ...@@ -128,7 +135,7 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
// and not wasteful, we move the string into an external cord rep, preserving // and not wasteful, we move the string into an external cord rep, preserving
// the already allocated string contents. // the already allocated string contents.
// Requires the provided string length to be larger than `kMaxInline`. // Requires the provided string length to be larger than `kMaxInline`.
static CordRep* CordRepFromString(std::string&& src) { static absl::Nonnull<CordRep*> CordRepFromString(std::string&& src) {
assert(src.length() > cord_internal::kMaxInline); assert(src.length() > cord_internal::kMaxInline);
if ( if (
// String is short: copy data to avoid external block overhead. // String is short: copy data to avoid external block overhead.
...@@ -160,12 +167,13 @@ static CordRep* CordRepFromString(std::string&& src) { ...@@ -160,12 +167,13 @@ static CordRep* CordRepFromString(std::string&& src) {
constexpr unsigned char Cord::InlineRep::kMaxInline; constexpr unsigned char Cord::InlineRep::kMaxInline;
#endif #endif
inline void Cord::InlineRep::set_data(const char* data, size_t n) { inline void Cord::InlineRep::set_data(absl::Nonnull<const char*> data,
size_t n) {
static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15"); static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
data_.set_inline_data(data, n); data_.set_inline_data(data, n);
} }
inline char* Cord::InlineRep::set_data(size_t n) { inline absl::Nonnull<char*> Cord::InlineRep::set_data(size_t n) {
assert(n <= kMaxInline); assert(n <= kMaxInline);
ResetToEmpty(); ResetToEmpty();
set_inline_size(n); set_inline_size(n);
...@@ -189,13 +197,13 @@ inline void Cord::InlineRep::remove_prefix(size_t n) { ...@@ -189,13 +197,13 @@ inline void Cord::InlineRep::remove_prefix(size_t n) {
// Returns `rep` converted into a CordRepBtree. // Returns `rep` converted into a CordRepBtree.
// Directly returns `rep` if `rep` is already a CordRepBtree. // Directly returns `rep` if `rep` is already a CordRepBtree.
static CordRepBtree* ForceBtree(CordRep* rep) { static absl::Nonnull<CordRepBtree*> ForceBtree(CordRep* rep) {
return rep->IsBtree() return rep->IsBtree()
? rep->btree() ? rep->btree()
: CordRepBtree::Create(cord_internal::RemoveCrcNode(rep)); : CordRepBtree::Create(cord_internal::RemoveCrcNode(rep));
} }
void Cord::InlineRep::AppendTreeToInlined(CordRep* tree, void Cord::InlineRep::AppendTreeToInlined(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) { MethodIdentifier method) {
assert(!is_tree()); assert(!is_tree());
if (!data_.is_empty()) { if (!data_.is_empty()) {
...@@ -205,14 +213,16 @@ void Cord::InlineRep::AppendTreeToInlined(CordRep* tree, ...@@ -205,14 +213,16 @@ void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
EmplaceTree(tree, method); EmplaceTree(tree, method);
} }
void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) { void Cord::InlineRep::AppendTreeToTree(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) {
assert(is_tree()); assert(is_tree());
const CordzUpdateScope scope(data_.cordz_info(), method); const CordzUpdateScope scope(data_.cordz_info(), method);
tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree); tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree);
SetTree(tree, scope); SetTree(tree, scope);
} }
void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) { void Cord::InlineRep::AppendTree(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) {
assert(tree != nullptr); assert(tree != nullptr);
assert(tree->length != 0); assert(tree->length != 0);
assert(!tree->IsCrc()); assert(!tree->IsCrc());
...@@ -223,7 +233,7 @@ void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) { ...@@ -223,7 +233,7 @@ void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) {
} }
} }
void Cord::InlineRep::PrependTreeToInlined(CordRep* tree, void Cord::InlineRep::PrependTreeToInlined(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) { MethodIdentifier method) {
assert(!is_tree()); assert(!is_tree());
if (!data_.is_empty()) { if (!data_.is_empty()) {
...@@ -233,7 +243,7 @@ void Cord::InlineRep::PrependTreeToInlined(CordRep* tree, ...@@ -233,7 +243,7 @@ void Cord::InlineRep::PrependTreeToInlined(CordRep* tree,
EmplaceTree(tree, method); EmplaceTree(tree, method);
} }
void Cord::InlineRep::PrependTreeToTree(CordRep* tree, void Cord::InlineRep::PrependTreeToTree(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) { MethodIdentifier method) {
assert(is_tree()); assert(is_tree());
const CordzUpdateScope scope(data_.cordz_info(), method); const CordzUpdateScope scope(data_.cordz_info(), method);
...@@ -241,7 +251,8 @@ void Cord::InlineRep::PrependTreeToTree(CordRep* tree, ...@@ -241,7 +251,8 @@ void Cord::InlineRep::PrependTreeToTree(CordRep* tree,
SetTree(tree, scope); SetTree(tree, scope);
} }
void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) { void Cord::InlineRep::PrependTree(absl::Nonnull<CordRep*> tree,
MethodIdentifier method) {
assert(tree != nullptr); assert(tree != nullptr);
assert(tree->length != 0); assert(tree->length != 0);
assert(!tree->IsCrc()); assert(!tree->IsCrc());
...@@ -256,8 +267,9 @@ void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) { ...@@ -256,8 +267,9 @@ void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
// suitable leaf is found, the function will update the length field for all // suitable leaf is found, the function will update the length field for all
// nodes to account for the size increase. The append region address will be // nodes to account for the size increase. The append region address will be
// written to region and the actual size increase will be written to size. // written to region and the actual size increase will be written to size.
static inline bool PrepareAppendRegion(CordRep* root, char** region, static inline bool PrepareAppendRegion(
size_t* size, size_t max_length) { absl::Nonnull<CordRep*> root, absl::Nonnull<absl::Nullable<char*>*> region,
absl::Nonnull<size_t*> size, size_t max_length) {
if (root->IsBtree() && root->refcount.IsOne()) { if (root->IsBtree() && root->refcount.IsOne()) {
Span<char> span = root->btree()->GetAppendBuffer(max_length); Span<char> span = root->btree()->GetAppendBuffer(max_length);
if (!span.empty()) { if (!span.empty()) {
...@@ -460,11 +472,11 @@ void Cord::InlineRep::AppendArray(absl::string_view src, ...@@ -460,11 +472,11 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
CommitTree(root, rep, scope, method); CommitTree(root, rep, scope, method);
} }
inline CordRep* Cord::TakeRep() const& { inline absl::Nonnull<CordRep*> Cord::TakeRep() const& {
return CordRep::Ref(contents_.tree()); return CordRep::Ref(contents_.tree());
} }
inline CordRep* Cord::TakeRep() && { inline absl::Nonnull<CordRep*> Cord::TakeRep() && {
CordRep* rep = contents_.tree(); CordRep* rep = contents_.tree();
contents_.clear(); contents_.clear();
return rep; return rep;
...@@ -522,7 +534,7 @@ inline void Cord::AppendImpl(C&& src) { ...@@ -522,7 +534,7 @@ inline void Cord::AppendImpl(C&& src) {
contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord); contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
} }
static CordRep::ExtractResult ExtractAppendBuffer(CordRep* rep, static CordRep::ExtractResult ExtractAppendBuffer(absl::Nonnull<CordRep*> rep,
size_t min_capacity) { size_t min_capacity) {
switch (rep->tag) { switch (rep->tag) {
case cord_internal::BTREE: case cord_internal::BTREE:
...@@ -769,8 +781,9 @@ int ClampResult(int memcmp_res) { ...@@ -769,8 +781,9 @@ int ClampResult(int memcmp_res) {
return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0); return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
} }
int CompareChunks(absl::string_view* lhs, absl::string_view* rhs, int CompareChunks(absl::Nonnull<absl::string_view*> lhs,
size_t* size_to_compare) { absl::Nonnull<absl::string_view*> rhs,
absl::Nonnull<size_t*> size_to_compare) {
size_t compared_size = std::min(lhs->size(), rhs->size()); size_t compared_size = std::min(lhs->size(), rhs->size());
assert(*size_to_compare >= compared_size); assert(*size_to_compare >= compared_size);
*size_to_compare -= compared_size; *size_to_compare -= compared_size;
...@@ -868,7 +881,8 @@ void Cord::SetExpectedChecksum(uint32_t crc) { ...@@ -868,7 +881,8 @@ void Cord::SetExpectedChecksum(uint32_t crc) {
SetCrcCordState(std::move(state)); SetCrcCordState(std::move(state));
} }
const crc_internal::CrcCordState* Cord::MaybeGetCrcCordState() const { absl::Nullable<const crc_internal::CrcCordState*> Cord::MaybeGetCrcCordState()
const {
if (!contents_.is_tree() || !contents_.tree()->IsCrc()) { if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {
return nullptr; return nullptr;
} }
...@@ -885,7 +899,8 @@ absl::optional<uint32_t> Cord::ExpectedChecksum() const { ...@@ -885,7 +899,8 @@ absl::optional<uint32_t> Cord::ExpectedChecksum() const {
inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
size_t size_to_compare) const { size_t size_to_compare) const {
auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it,
absl::Nonnull<absl::string_view*> chunk) {
if (!chunk->empty()) return true; if (!chunk->empty()) return true;
++*it; ++*it;
if (it->bytes_remaining_ == 0) return false; if (it->bytes_remaining_ == 0) return false;
...@@ -915,7 +930,8 @@ inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, ...@@ -915,7 +930,8 @@ inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size, inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
size_t size_to_compare) const { size_t size_to_compare) const {
auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it,
absl::Nonnull<absl::string_view*> chunk) {
if (!chunk->empty()) return true; if (!chunk->empty()) return true;
++*it; ++*it;
if (it->bytes_remaining_ == 0) return false; if (it->bytes_remaining_ == 0) return false;
...@@ -1037,7 +1053,7 @@ Cord::operator std::string() const { ...@@ -1037,7 +1053,7 @@ Cord::operator std::string() const {
return s; return s;
} }
void CopyCordToString(const Cord& src, std::string* dst) { void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst) {
if (!src.contents_.is_tree()) { if (!src.contents_.is_tree()) {
src.contents_.CopyTo(dst); src.contents_.CopyTo(dst);
} else { } else {
...@@ -1046,7 +1062,7 @@ void CopyCordToString(const Cord& src, std::string* dst) { ...@@ -1046,7 +1062,7 @@ void CopyCordToString(const Cord& src, std::string* dst) {
} }
} }
void Cord::CopyToArraySlowPath(char* dst) const { void Cord::CopyToArraySlowPath(absl::Nonnull<char*> dst) const {
assert(contents_.is_tree()); assert(contents_.is_tree());
absl::string_view fragment; absl::string_view fragment;
if (GetFlatAux(contents_.tree(), &fragment)) { if (GetFlatAux(contents_.tree(), &fragment)) {
...@@ -1372,7 +1388,8 @@ absl::string_view Cord::FlattenSlowPath() { ...@@ -1372,7 +1388,8 @@ absl::string_view Cord::FlattenSlowPath() {
return absl::string_view(new_buffer, total_size); return absl::string_view(new_buffer, total_size);
} }
/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) { /* static */ bool Cord::GetFlatAux(absl::Nonnull<CordRep*> rep,
absl::Nonnull<absl::string_view*> fragment) {
assert(rep != nullptr); assert(rep != nullptr);
if (rep->length == 0) { if (rep->length == 0) {
*fragment = absl::string_view(); *fragment = absl::string_view();
...@@ -1406,7 +1423,7 @@ absl::string_view Cord::FlattenSlowPath() { ...@@ -1406,7 +1423,7 @@ absl::string_view Cord::FlattenSlowPath() {
} }
/* static */ void Cord::ForEachChunkAux( /* static */ void Cord::ForEachChunkAux(
absl::cord_internal::CordRep* rep, absl::Nonnull<absl::cord_internal::CordRep*> rep,
absl::FunctionRef<void(absl::string_view)> callback) { absl::FunctionRef<void(absl::string_view)> callback) {
assert(rep != nullptr); assert(rep != nullptr);
if (rep->length == 0) return; if (rep->length == 0) return;
...@@ -1431,8 +1448,8 @@ absl::string_view Cord::FlattenSlowPath() { ...@@ -1431,8 +1448,8 @@ absl::string_view Cord::FlattenSlowPath() {
} }
} }
static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, static void DumpNode(absl::Nonnull<CordRep*> rep, bool include_data,
int indent) { absl::Nonnull<std::ostream*> os, int indent) {
const int kIndentStep = 1; const int kIndentStep = 1;
absl::InlinedVector<CordRep*, kInlinedVectorSize> stack; absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
absl::InlinedVector<int, kInlinedVectorSize> indents; absl::InlinedVector<int, kInlinedVectorSize> indents;
...@@ -1482,15 +1499,17 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, ...@@ -1482,15 +1499,17 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
ABSL_INTERNAL_CHECK(indents.empty(), ""); ABSL_INTERNAL_CHECK(indents.empty(), "");
} }
static std::string ReportError(CordRep* root, CordRep* node) { static std::string ReportError(absl::Nonnull<CordRep*> root,
absl::Nonnull<CordRep*> node) {
std::ostringstream buf; std::ostringstream buf;
buf << "Error at node " << node << " in:"; buf << "Error at node " << node << " in:";
DumpNode(root, true, &buf); DumpNode(root, true, &buf);
return buf.str(); return buf.str();
} }
static bool VerifyNode(CordRep* root, CordRep* start_node) { static bool VerifyNode(absl::Nonnull<CordRep*> root,
absl::InlinedVector<CordRep*, 2> worklist; absl::Nonnull<CordRep*> start_node) {
absl::InlinedVector<absl::Nonnull<CordRep*>, 2> worklist;
worklist.push_back(start_node); worklist.push_back(start_node);
do { do {
CordRep* node = worklist.back(); CordRep* node = worklist.back();
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#include "absl/base/internal/endian.h" #include "absl/base/internal/endian.h"
#include "absl/base/internal/per_thread_tls.h" #include "absl/base/internal/per_thread_tls.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h" #include "absl/base/port.h"
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/crc/internal/crc_cord_state.h" #include "absl/crc/internal/crc_cord_state.h"
...@@ -102,7 +103,7 @@ class Cord; ...@@ -102,7 +103,7 @@ class Cord;
class CordTestPeer; class CordTestPeer;
template <typename Releaser> template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view, Releaser&&); Cord MakeCordFromExternal(absl::string_view, Releaser&&);
void CopyCordToString(const Cord& src, std::string* dst); void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst);
// Cord memory accounting modes // Cord memory accounting modes
enum class CordMemoryAccounting { enum class CordMemoryAccounting {
...@@ -416,7 +417,8 @@ class Cord { ...@@ -416,7 +417,8 @@ class Cord {
// guarantee that pointers previously returned by `dst->data()` remain valid // guarantee that pointers previously returned by `dst->data()` remain valid
// even if `*dst` had enough capacity to hold `src`. If `*dst` is a new // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
// object, prefer to simply use the conversion operator to `std::string`. // object, prefer to simply use the conversion operator to `std::string`.
friend void CopyCordToString(const Cord& src, std::string* dst); friend void CopyCordToString(const Cord& src,
absl::Nonnull<std::string*> dst);
class CharIterator; class CharIterator;
...@@ -453,7 +455,7 @@ class Cord { ...@@ -453,7 +455,7 @@ class Cord {
using iterator_category = std::input_iterator_tag; using iterator_category = std::input_iterator_tag;
using value_type = absl::string_view; using value_type = absl::string_view;
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
using pointer = const value_type*; using pointer = absl::Nonnull<const value_type*>;
using reference = value_type; using reference = value_type;
ChunkIterator() = default; ChunkIterator() = default;
...@@ -473,14 +475,14 @@ class Cord { ...@@ -473,14 +475,14 @@ class Cord {
using CordRepBtree = absl::cord_internal::CordRepBtree; using CordRepBtree = absl::cord_internal::CordRepBtree;
using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader; using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
// Constructs a `begin()` iterator from `tree`. `tree` must not be null. // Constructs a `begin()` iterator from `tree`.
explicit ChunkIterator(cord_internal::CordRep* tree); explicit ChunkIterator(absl::Nonnull<cord_internal::CordRep*> tree);
// Constructs a `begin()` iterator from `cord`. // Constructs a `begin()` iterator from `cord`.
explicit ChunkIterator(const Cord* cord); explicit ChunkIterator(absl::Nonnull<const Cord*> cord);
// Initializes this instance from a tree. Invoked by constructors. // Initializes this instance from a tree. Invoked by constructors.
void InitTree(cord_internal::CordRep* tree); void InitTree(absl::Nonnull<cord_internal::CordRep*> tree);
// Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
// `current_chunk_.size()`. // `current_chunk_.size()`.
...@@ -498,7 +500,7 @@ class Cord { ...@@ -498,7 +500,7 @@ class Cord {
// The current leaf, or `nullptr` if the iterator points to short data. // The current leaf, or `nullptr` if the iterator points to short data.
// If the current chunk is a substring node, current_leaf_ points to the // If the current chunk is a substring node, current_leaf_ points to the
// underlying flat or external node. // underlying flat or external node.
absl::cord_internal::CordRep* current_leaf_ = nullptr; absl::Nullable<absl::cord_internal::CordRep*> current_leaf_ = nullptr;
// The number of bytes left in the `Cord` over which we are iterating. // The number of bytes left in the `Cord` over which we are iterating.
size_t bytes_remaining_ = 0; size_t bytes_remaining_ = 0;
...@@ -555,13 +557,13 @@ class Cord { ...@@ -555,13 +557,13 @@ class Cord {
using iterator = ChunkIterator; using iterator = ChunkIterator;
using const_iterator = ChunkIterator; using const_iterator = ChunkIterator;
explicit ChunkRange(const Cord* cord) : cord_(cord) {} explicit ChunkRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {}
ChunkIterator begin() const; ChunkIterator begin() const;
ChunkIterator end() const; ChunkIterator end() const;
private: private:
const Cord* cord_; absl::Nonnull<const Cord*> cord_;
}; };
// Cord::Chunks() // Cord::Chunks()
...@@ -614,7 +616,7 @@ class Cord { ...@@ -614,7 +616,7 @@ class Cord {
using iterator_category = std::input_iterator_tag; using iterator_category = std::input_iterator_tag;
using value_type = char; using value_type = char;
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
using pointer = const char*; using pointer = absl::Nonnull<const char*>;
using reference = const char&; using reference = const char&;
CharIterator() = default; CharIterator() = default;
...@@ -629,7 +631,8 @@ class Cord { ...@@ -629,7 +631,8 @@ class Cord {
friend Cord; friend Cord;
private: private:
explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {} explicit CharIterator(absl::Nonnull<const Cord*> cord)
: chunk_iterator_(cord) {}
ChunkIterator chunk_iterator_; ChunkIterator chunk_iterator_;
}; };
...@@ -640,14 +643,14 @@ class Cord { ...@@ -640,14 +643,14 @@ class Cord {
// advanced as a separate `Cord`. `n_bytes` must be less than or equal to the // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
// number of bytes within the Cord; otherwise, behavior is undefined. It is // number of bytes within the Cord; otherwise, behavior is undefined. It is
// valid to pass `char_end()` and `0`. // valid to pass `char_end()` and `0`.
static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes); static Cord AdvanceAndRead(absl::Nonnull<CharIterator*> it, size_t n_bytes);
// Cord::Advance() // Cord::Advance()
// //
// Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
// or equal to the number of bytes remaining within the Cord; otherwise, // or equal to the number of bytes remaining within the Cord; otherwise,
// behavior is undefined. It is valid to pass `char_end()` and `0`. // behavior is undefined. It is valid to pass `char_end()` and `0`.
static void Advance(CharIterator* it, size_t n_bytes); static void Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes);
// Cord::ChunkRemaining() // Cord::ChunkRemaining()
// //
...@@ -696,13 +699,13 @@ class Cord { ...@@ -696,13 +699,13 @@ class Cord {
using iterator = CharIterator; using iterator = CharIterator;
using const_iterator = CharIterator; using const_iterator = CharIterator;
explicit CharRange(const Cord* cord) : cord_(cord) {} explicit CharRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {}
CharIterator begin() const; CharIterator begin() const;
CharIterator end() const; CharIterator end() const;
private: private:
const Cord* cord_; absl::Nonnull<const Cord*> cord_;
}; };
// Cord::Chars() // Cord::Chars()
...@@ -761,7 +764,8 @@ class Cord { ...@@ -761,7 +764,8 @@ class Cord {
CharIterator Find(const absl::Cord& needle) const; CharIterator Find(const absl::Cord& needle) const;
// Supports absl::Cord as a sink object for absl::Format(). // Supports absl::Cord as a sink object for absl::Format().
friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) { friend void AbslFormatFlush(absl::Nonnull<absl::Cord*> cord,
absl::string_view part) {
cord->Append(part); cord->Append(part);
} }
...@@ -831,7 +835,8 @@ class Cord { ...@@ -831,7 +835,8 @@ class Cord {
friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, const Cord& rhs);
friend bool operator==(const Cord& lhs, absl::string_view rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs);
friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord); friend absl::Nullable<const CordzInfo*> GetCordzInfoForTesting(
const Cord& cord);
// Calls the provided function once for each cord chunk, in order. Unlike // Calls the provided function once for each cord chunk, in order. Unlike
// Chunks(), this API will not allocate memory. // Chunks(), this API will not allocate memory.
...@@ -858,19 +863,22 @@ class Cord { ...@@ -858,19 +863,22 @@ class Cord {
InlineRep& operator=(const InlineRep& src); InlineRep& operator=(const InlineRep& src);
InlineRep& operator=(InlineRep&& src) noexcept; InlineRep& operator=(InlineRep&& src) noexcept;
explicit constexpr InlineRep(absl::string_view sv, CordRep* rep); explicit constexpr InlineRep(absl::string_view sv,
absl::Nullable<CordRep*> rep);
void Swap(InlineRep* rhs); void Swap(absl::Nonnull<InlineRep*> rhs);
size_t size() const; size_t size() const;
const char* data() const; // Returns nullptr if holding pointer // Returns nullptr if holding pointer
void set_data(const char* data, size_t n); // Discards pointer, if any absl::Nullable<const char*> data() const;
char* set_data(size_t n); // Write data to the result // Discards pointer, if any
void set_data(absl::Nonnull<const char*> data, size_t n);
absl::Nonnull<char*> set_data(size_t n); // Write data to the result
// Returns nullptr if holding bytes // Returns nullptr if holding bytes
absl::cord_internal::CordRep* tree() const; absl::Nullable<absl::cord_internal::CordRep*> tree() const;
absl::cord_internal::CordRep* as_tree() const; absl::Nonnull<absl::cord_internal::CordRep*> as_tree() const;
const char* as_chars() const; absl::Nonnull<const char*> as_chars() const;
// Returns non-null iff was holding a pointer // Returns non-null iff was holding a pointer
absl::cord_internal::CordRep* clear(); absl::Nullable<absl::cord_internal::CordRep*> clear();
// Converts to pointer if necessary. // Converts to pointer if necessary.
void reduce_size(size_t n); // REQUIRES: holding data void reduce_size(size_t n); // REQUIRES: holding data
void remove_prefix(size_t n); // REQUIRES: holding data void remove_prefix(size_t n); // REQUIRES: holding data
...@@ -879,46 +887,52 @@ class Cord { ...@@ -879,46 +887,52 @@ class Cord {
// Creates a CordRepFlat instance from the current inlined data with `extra' // Creates a CordRepFlat instance from the current inlined data with `extra'
// bytes of desired additional capacity. // bytes of desired additional capacity.
CordRepFlat* MakeFlatWithExtraCapacity(size_t extra); absl::Nonnull<CordRepFlat*> MakeFlatWithExtraCapacity(size_t extra);
// Sets the tree value for this instance. `rep` must not be null. // Sets the tree value for this instance. `rep` must not be null.
// Requires the current instance to hold a tree, and a lock to be held on // Requires the current instance to hold a tree, and a lock to be held on
// any CordzInfo referenced by this instance. The latter is enforced through // any CordzInfo referenced by this instance. The latter is enforced through
// the CordzUpdateScope argument. If the current instance is sampled, then // the CordzUpdateScope argument. If the current instance is sampled, then
// the CordzInfo instance is updated to reference the new `rep` value. // the CordzInfo instance is updated to reference the new `rep` value.
void SetTree(CordRep* rep, const CordzUpdateScope& scope); void SetTree(absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope);
// Identical to SetTree(), except that `rep` is allowed to be null, in // Identical to SetTree(), except that `rep` is allowed to be null, in
// which case the current instance is reset to an empty value. // which case the current instance is reset to an empty value.
void SetTreeOrEmpty(CordRep* rep, const CordzUpdateScope& scope); void SetTreeOrEmpty(absl::Nullable<CordRep*> rep,
const CordzUpdateScope& scope);
// Sets the tree value for this instance, and randomly samples this cord. // Sets the tree value for this instance, and randomly samples this cord.
// This function disregards existing contents in `data_`, and should be // This function disregards existing contents in `data_`, and should be
// called when a Cord is 'promoted' from an 'uninitialized' or 'inlined' // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'
// value to a non-inlined (tree / ring) value. // value to a non-inlined (tree / ring) value.
void EmplaceTree(CordRep* rep, MethodIdentifier method); void EmplaceTree(absl::Nonnull<CordRep*> rep, MethodIdentifier method);
// Identical to EmplaceTree, except that it copies the parent stack from // Identical to EmplaceTree, except that it copies the parent stack from
// the provided `parent` data if the parent is sampled. // the provided `parent` data if the parent is sampled.
void EmplaceTree(CordRep* rep, const InlineData& parent, void EmplaceTree(absl::Nonnull<CordRep*> rep, const InlineData& parent,
MethodIdentifier method); MethodIdentifier method);
// Commits the change of a newly created, or updated `rep` root value into // Commits the change of a newly created, or updated `rep` root value into
// this cord. `old_rep` indicates the old (inlined or tree) value of the // this cord. `old_rep` indicates the old (inlined or tree) value of the
// cord, and determines if the commit invokes SetTree() or EmplaceTree(). // cord, and determines if the commit invokes SetTree() or EmplaceTree().
void CommitTree(const CordRep* old_rep, CordRep* rep, void CommitTree(absl::Nullable<const CordRep*> old_rep,
const CordzUpdateScope& scope, MethodIdentifier method); absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope,
MethodIdentifier method);
void AppendTreeToInlined(CordRep* tree, MethodIdentifier method);
void AppendTreeToTree(CordRep* tree, MethodIdentifier method); void AppendTreeToInlined(absl::Nonnull<CordRep*> tree,
void AppendTree(CordRep* tree, MethodIdentifier method); MethodIdentifier method);
void PrependTreeToInlined(CordRep* tree, MethodIdentifier method); void AppendTreeToTree(absl::Nonnull<CordRep*> tree,
void PrependTreeToTree(CordRep* tree, MethodIdentifier method); MethodIdentifier method);
void PrependTree(CordRep* tree, MethodIdentifier method); void AppendTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method);
void PrependTreeToInlined(absl::Nonnull<CordRep*> tree,
MethodIdentifier method);
void PrependTreeToTree(absl::Nonnull<CordRep*> tree,
MethodIdentifier method);
void PrependTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method);
bool IsSame(const InlineRep& other) const { return data_ == other.data_; } bool IsSame(const InlineRep& other) const { return data_ == other.data_; }
void CopyTo(std::string* dst) const { void CopyTo(absl::Nonnull<std::string*> dst) const {
// memcpy is much faster when operating on a known size. On most supported // memcpy is much faster when operating on a known size. On most supported
// platforms, the small string optimization is large enough that resizing // platforms, the small string optimization is large enough that resizing
// to 15 bytes does not cause a memory allocation. // to 15 bytes does not cause a memory allocation.
...@@ -930,7 +944,7 @@ class Cord { ...@@ -930,7 +944,7 @@ class Cord {
} }
// Copies the inline contents into `dst`. Assumes the cord is not empty. // Copies the inline contents into `dst`. Assumes the cord is not empty.
void CopyToArray(char* dst) const; void CopyToArray(absl::Nonnull<char*> dst) const;
bool is_tree() const { return data_.is_tree(); } bool is_tree() const { return data_.is_tree(); }
...@@ -943,12 +957,12 @@ class Cord { ...@@ -943,12 +957,12 @@ class Cord {
} }
// Returns the profiled CordzInfo, or nullptr if not sampled. // Returns the profiled CordzInfo, or nullptr if not sampled.
absl::cord_internal::CordzInfo* cordz_info() const { absl::Nullable<absl::cord_internal::CordzInfo*> cordz_info() const {
return data_.cordz_info(); return data_.cordz_info();
} }
// Sets the profiled CordzInfo. `cordz_info` must not be null. // Sets the profiled CordzInfo.
void set_cordz_info(cord_internal::CordzInfo* cordz_info) { void set_cordz_info(absl::Nonnull<cord_internal::CordzInfo*> cordz_info) {
assert(cordz_info != nullptr); assert(cordz_info != nullptr);
data_.set_cordz_info(cordz_info); data_.set_cordz_info(cordz_info);
} }
...@@ -980,19 +994,19 @@ class Cord { ...@@ -980,19 +994,19 @@ class Cord {
InlineRep contents_; InlineRep contents_;
// Helper for GetFlat() and TryFlat(). // Helper for GetFlat() and TryFlat().
static bool GetFlatAux(absl::cord_internal::CordRep* rep, static bool GetFlatAux(absl::Nonnull<absl::cord_internal::CordRep*> rep,
absl::string_view* fragment); absl::Nonnull<absl::string_view*> fragment);
// Helper for ForEachChunk(). // Helper for ForEachChunk().
static void ForEachChunkAux( static void ForEachChunkAux(
absl::cord_internal::CordRep* rep, absl::Nonnull<absl::cord_internal::CordRep*> rep,
absl::FunctionRef<void(absl::string_view)> callback); absl::FunctionRef<void(absl::string_view)> callback);
// The destructor for non-empty Cords. // The destructor for non-empty Cords.
void DestroyCordSlow(); void DestroyCordSlow();
// Out-of-line implementation of slower parts of logic. // Out-of-line implementation of slower parts of logic.
void CopyToArraySlowPath(char* dst) const; void CopyToArraySlowPath(absl::Nonnull<char*> dst) const;
int CompareSlowPath(absl::string_view rhs, size_t compared_size, int CompareSlowPath(absl::string_view rhs, size_t compared_size,
size_t size_to_compare) const; size_t size_to_compare) const;
int CompareSlowPath(const Cord& rhs, size_t compared_size, int CompareSlowPath(const Cord& rhs, size_t compared_size,
...@@ -1009,8 +1023,8 @@ class Cord { ...@@ -1009,8 +1023,8 @@ class Cord {
// Returns a new reference to contents_.tree(), or steals an existing // Returns a new reference to contents_.tree(), or steals an existing
// reference if called on an rvalue. // reference if called on an rvalue.
absl::cord_internal::CordRep* TakeRep() const&; absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() const&;
absl::cord_internal::CordRep* TakeRep() &&; absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() &&;
// Helper for Append(). // Helper for Append().
template <typename C> template <typename C>
...@@ -1047,7 +1061,8 @@ class Cord { ...@@ -1047,7 +1061,8 @@ class Cord {
friend class CrcCord; friend class CrcCord;
void SetCrcCordState(crc_internal::CrcCordState state); void SetCrcCordState(crc_internal::CrcCordState state);
const crc_internal::CrcCordState* MaybeGetCrcCordState() const; absl::Nullable<const crc_internal::CrcCordState*> MaybeGetCrcCordState()
const;
CharIterator FindImpl(CharIterator it, absl::string_view needle) const; CharIterator FindImpl(CharIterator it, absl::string_view needle) const;
}; };
...@@ -1068,13 +1083,15 @@ namespace cord_internal { ...@@ -1068,13 +1083,15 @@ namespace cord_internal {
// Does non-template-specific `CordRepExternal` initialization. // Does non-template-specific `CordRepExternal` initialization.
// Requires `data` to be non-empty. // Requires `data` to be non-empty.
void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep); void InitializeCordRepExternal(absl::string_view data,
absl::Nonnull<CordRepExternal*> rep);
// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
// to it. Requires `data` to be non-empty. // to it. Requires `data` to be non-empty.
template <typename Releaser> template <typename Releaser>
// NOLINTNEXTLINE - suppress clang-tidy raw pointer return. // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data,
Releaser&& releaser) {
assert(!data.empty()); assert(!data.empty());
using ReleaserType = absl::decay_t<Releaser>; using ReleaserType = absl::decay_t<Releaser>;
CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>( CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
...@@ -1086,7 +1103,7 @@ CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { ...@@ -1086,7 +1103,7 @@ CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
// Overload for function reference types that dispatches using a function // Overload for function reference types that dispatches using a function
// pointer because there are no `alignof()` or `sizeof()` a function reference. // pointer because there are no `alignof()` or `sizeof()` a function reference.
// NOLINTNEXTLINE - suppress clang-tidy raw pointer return. // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
inline CordRep* NewExternalRep(absl::string_view data, inline absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data,
void (&releaser)(absl::string_view)) { void (&releaser)(absl::string_view)) {
return NewExternalRep(data, &releaser); return NewExternalRep(data, &releaser);
} }
...@@ -1109,7 +1126,8 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) { ...@@ -1109,7 +1126,8 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
return cord; return cord;
} }
constexpr Cord::InlineRep::InlineRep(absl::string_view sv, CordRep* rep) constexpr Cord::InlineRep::InlineRep(absl::string_view sv,
absl::Nullable<CordRep*> rep)
: data_(sv, rep) {} : data_(sv, rep) {}
inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
...@@ -1148,28 +1166,30 @@ inline Cord::InlineRep& Cord::InlineRep::operator=( ...@@ -1148,28 +1166,30 @@ inline Cord::InlineRep& Cord::InlineRep::operator=(
return *this; return *this;
} }
inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) { inline void Cord::InlineRep::Swap(absl::Nonnull<Cord::InlineRep*> rhs) {
if (rhs == this) { if (rhs == this) {
return; return;
} }
std::swap(data_, rhs->data_); std::swap(data_, rhs->data_);
} }
inline const char* Cord::InlineRep::data() const { inline absl::Nullable<const char*> Cord::InlineRep::data() const {
return is_tree() ? nullptr : data_.as_chars(); return is_tree() ? nullptr : data_.as_chars();
} }
inline const char* Cord::InlineRep::as_chars() const { inline absl::Nonnull<const char*> Cord::InlineRep::as_chars() const {
assert(!data_.is_tree()); assert(!data_.is_tree());
return data_.as_chars(); return data_.as_chars();
} }
inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const { inline absl::Nonnull<absl::cord_internal::CordRep*> Cord::InlineRep::as_tree()
const {
assert(data_.is_tree()); assert(data_.is_tree());
return data_.as_tree(); return data_.as_tree();
} }
inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const { inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::tree()
const {
if (is_tree()) { if (is_tree()) {
return as_tree(); return as_tree();
} else { } else {
...@@ -1181,8 +1201,8 @@ inline size_t Cord::InlineRep::size() const { ...@@ -1181,8 +1201,8 @@ inline size_t Cord::InlineRep::size() const {
return is_tree() ? as_tree()->length : inline_size(); return is_tree() ? as_tree()->length : inline_size();
} }
inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity( inline absl::Nonnull<cord_internal::CordRepFlat*>
size_t extra) { Cord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) {
static_assert(cord_internal::kMinFlatLength >= sizeof(data_), ""); static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
size_t len = data_.inline_size(); size_t len = data_.inline_size();
auto* result = CordRepFlat::New(len + extra); auto* result = CordRepFlat::New(len + extra);
...@@ -1191,20 +1211,21 @@ inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity( ...@@ -1191,20 +1211,21 @@ inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
return result; return result;
} }
inline void Cord::InlineRep::EmplaceTree(CordRep* rep, inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep,
MethodIdentifier method) { MethodIdentifier method) {
assert(rep); assert(rep);
data_.make_tree(rep); data_.make_tree(rep);
CordzInfo::MaybeTrackCord(data_, method); CordzInfo::MaybeTrackCord(data_, method);
} }
inline void Cord::InlineRep::EmplaceTree(CordRep* rep, const InlineData& parent, inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep,
const InlineData& parent,
MethodIdentifier method) { MethodIdentifier method) {
data_.make_tree(rep); data_.make_tree(rep);
CordzInfo::MaybeTrackCord(data_, parent, method); CordzInfo::MaybeTrackCord(data_, parent, method);
} }
inline void Cord::InlineRep::SetTree(CordRep* rep, inline void Cord::InlineRep::SetTree(absl::Nonnull<CordRep*> rep,
const CordzUpdateScope& scope) { const CordzUpdateScope& scope) {
assert(rep); assert(rep);
assert(data_.is_tree()); assert(data_.is_tree());
...@@ -1212,7 +1233,7 @@ inline void Cord::InlineRep::SetTree(CordRep* rep, ...@@ -1212,7 +1233,7 @@ inline void Cord::InlineRep::SetTree(CordRep* rep,
scope.SetCordRep(rep); scope.SetCordRep(rep);
} }
inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep, inline void Cord::InlineRep::SetTreeOrEmpty(absl::Nullable<CordRep*> rep,
const CordzUpdateScope& scope) { const CordzUpdateScope& scope) {
assert(data_.is_tree()); assert(data_.is_tree());
if (rep) { if (rep) {
...@@ -1223,7 +1244,8 @@ inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep, ...@@ -1223,7 +1244,8 @@ inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep,
scope.SetCordRep(rep); scope.SetCordRep(rep);
} }
inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep, inline void Cord::InlineRep::CommitTree(absl::Nullable<const CordRep*> old_rep,
absl::Nonnull<CordRep*> rep,
const CordzUpdateScope& scope, const CordzUpdateScope& scope,
MethodIdentifier method) { MethodIdentifier method) {
if (old_rep) { if (old_rep) {
...@@ -1233,7 +1255,7 @@ inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep, ...@@ -1233,7 +1255,7 @@ inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep,
} }
} }
inline absl::cord_internal::CordRep* Cord::InlineRep::clear() { inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::clear() {
if (is_tree()) { if (is_tree()) {
CordzInfo::MaybeUntrackCord(cordz_info()); CordzInfo::MaybeUntrackCord(cordz_info());
} }
...@@ -1242,7 +1264,7 @@ inline absl::cord_internal::CordRep* Cord::InlineRep::clear() { ...@@ -1242,7 +1264,7 @@ inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
return result; return result;
} }
inline void Cord::InlineRep::CopyToArray(char* dst) const { inline void Cord::InlineRep::CopyToArray(absl::Nonnull<char*> dst) const {
assert(!is_tree()); assert(!is_tree());
size_t n = inline_size(); size_t n = inline_size();
assert(n != 0); assert(n != 0);
...@@ -1423,7 +1445,8 @@ inline bool Cord::StartsWith(absl::string_view rhs) const { ...@@ -1423,7 +1445,8 @@ inline bool Cord::StartsWith(absl::string_view rhs) const {
return EqualsImpl(rhs, rhs_size); return EqualsImpl(rhs, rhs_size);
} }
inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) { inline void Cord::ChunkIterator::InitTree(
absl::Nonnull<cord_internal::CordRep*> tree) {
tree = cord_internal::SkipCrcNode(tree); tree = cord_internal::SkipCrcNode(tree);
if (tree->tag == cord_internal::BTREE) { if (tree->tag == cord_internal::BTREE) {
current_chunk_ = btree_reader_.Init(tree->btree()); current_chunk_ = btree_reader_.Init(tree->btree());
...@@ -1433,12 +1456,13 @@ inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) { ...@@ -1433,12 +1456,13 @@ inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
} }
} }
inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree) { inline Cord::ChunkIterator::ChunkIterator(
absl::Nonnull<cord_internal::CordRep*> tree) {
bytes_remaining_ = tree->length; bytes_remaining_ = tree->length;
InitTree(tree); InitTree(tree);
} }
inline Cord::ChunkIterator::ChunkIterator(const Cord* cord) { inline Cord::ChunkIterator::ChunkIterator(absl::Nonnull<const Cord*> cord) {
if (CordRep* tree = cord->contents_.tree()) { if (CordRep* tree = cord->contents_.tree()) {
bytes_remaining_ = tree->length; bytes_remaining_ = tree->length;
if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) { if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) {
...@@ -1578,12 +1602,13 @@ inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const { ...@@ -1578,12 +1602,13 @@ inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
return chunk_iterator_->data(); return chunk_iterator_->data();
} }
inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) { inline Cord Cord::AdvanceAndRead(absl::Nonnull<CharIterator*> it,
size_t n_bytes) {
assert(it != nullptr); assert(it != nullptr);
return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes); return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
} }
inline void Cord::Advance(CharIterator* it, size_t n_bytes) { inline void Cord::Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes) {
assert(it != nullptr); assert(it != nullptr);
it->chunk_iterator_.AdvanceBytes(n_bytes); it->chunk_iterator_.AdvanceBytes(n_bytes);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <unordered_set> #include <unordered_set>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/cord_data_edge.h" #include "absl/strings/internal/cord_data_edge.h"
#include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_btree.h"
...@@ -38,13 +39,15 @@ enum class Mode { kFairShare, kTotal, kTotalMorePrecise }; ...@@ -38,13 +39,15 @@ enum class Mode { kFairShare, kTotal, kTotalMorePrecise };
template <Mode mode> template <Mode mode>
struct CordRepRef { struct CordRepRef {
// Instantiates a CordRepRef instance. // Instantiates a CordRepRef instance.
explicit CordRepRef(const CordRep* r) : rep(r) {} explicit CordRepRef(absl::Nonnull<const CordRep*> r) : rep(r) {}
// Creates a child reference holding the provided child. // Creates a child reference holding the provided child.
// Overloaded to add cumulative reference count for kFairShare. // Overloaded to add cumulative reference count for kFairShare.
CordRepRef Child(const CordRep* child) const { return CordRepRef(child); } CordRepRef Child(absl::Nonnull<const CordRep*> child) const {
return CordRepRef(child);
}
const CordRep* rep; absl::Nonnull<const CordRep*> rep;
}; };
// RawUsage holds the computed total number of bytes. // RawUsage holds the computed total number of bytes.
...@@ -63,7 +66,7 @@ template <> ...@@ -63,7 +66,7 @@ template <>
struct RawUsage<Mode::kTotalMorePrecise> { struct RawUsage<Mode::kTotalMorePrecise> {
size_t total = 0; size_t total = 0;
// TODO(b/289250880): Replace this with a flat_hash_set. // TODO(b/289250880): Replace this with a flat_hash_set.
std::unordered_set<const CordRep*> counted; std::unordered_set<absl::Nonnull<const CordRep*>> counted;
void Add(size_t size, CordRepRef<Mode::kTotalMorePrecise> repref) { void Add(size_t size, CordRepRef<Mode::kTotalMorePrecise> repref) {
if (counted.insert(repref.rep).second) { if (counted.insert(repref.rep).second) {
...@@ -87,15 +90,15 @@ double MaybeDiv(double d, refcount_t refcount) { ...@@ -87,15 +90,15 @@ double MaybeDiv(double d, refcount_t refcount) {
template <> template <>
struct CordRepRef<Mode::kFairShare> { struct CordRepRef<Mode::kFairShare> {
// Creates a CordRepRef with the provided rep and top (parent) fraction. // Creates a CordRepRef with the provided rep and top (parent) fraction.
explicit CordRepRef(const CordRep* r, double frac = 1.0) explicit CordRepRef(absl::Nonnull<const CordRep*> r, double frac = 1.0)
: rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {} : rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {}
// Returns a CordRepRef with a fraction of `this->fraction / child.refcount` // Returns a CordRepRef with a fraction of `this->fraction / child.refcount`
CordRepRef Child(const CordRep* child) const { CordRepRef Child(absl::Nonnull<const CordRep*> child) const {
return CordRepRef(child, fraction); return CordRepRef(child, fraction);
} }
const CordRep* rep; absl::Nonnull<const CordRep*> rep;
double fraction; double fraction;
}; };
...@@ -147,7 +150,7 @@ void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { ...@@ -147,7 +150,7 @@ void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {
} }
template <Mode mode> template <Mode mode>
size_t GetEstimatedUsage(const CordRep* rep) { size_t GetEstimatedUsage(absl::Nonnull<const CordRep*> rep) {
// Zero initialized memory usage totals. // Zero initialized memory usage totals.
RawUsage<mode> raw_usage; RawUsage<mode> raw_usage;
...@@ -176,15 +179,15 @@ size_t GetEstimatedUsage(const CordRep* rep) { ...@@ -176,15 +179,15 @@ size_t GetEstimatedUsage(const CordRep* rep) {
} // namespace } // namespace
size_t GetEstimatedMemoryUsage(const CordRep* rep) { size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep) {
return GetEstimatedUsage<Mode::kTotal>(rep); return GetEstimatedUsage<Mode::kTotal>(rep);
} }
size_t GetEstimatedFairShareMemoryUsage(const CordRep* rep) { size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep) {
return GetEstimatedUsage<Mode::kFairShare>(rep); return GetEstimatedUsage<Mode::kFairShare>(rep);
} }
size_t GetMorePreciseMemoryUsage(const CordRep* rep) { size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep) {
return GetEstimatedUsage<Mode::kTotalMorePrecise>(rep); return GetEstimatedUsage<Mode::kTotalMorePrecise>(rep);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <cstdint> #include <cstdint>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_internal.h"
namespace absl { namespace absl {
...@@ -28,7 +29,7 @@ namespace cord_internal { ...@@ -28,7 +29,7 @@ namespace cord_internal {
// Returns the *approximate* number of bytes held in full or in part by this // Returns the *approximate* number of bytes held in full or in part by this
// Cord (which may not remain the same between invocations). Cords that share // Cord (which may not remain the same between invocations). Cords that share
// memory could each be "charged" independently for the same shared memory. // memory could each be "charged" independently for the same shared memory.
size_t GetEstimatedMemoryUsage(const CordRep* rep); size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep);
// Returns the *approximate* number of bytes held in full or in part by this // Returns the *approximate* number of bytes held in full or in part by this
// Cord for the distinct memory held by this cord. This is similar to // Cord for the distinct memory held by this cord. This is similar to
...@@ -46,13 +47,13 @@ size_t GetEstimatedMemoryUsage(const CordRep* rep); ...@@ -46,13 +47,13 @@ size_t GetEstimatedMemoryUsage(const CordRep* rep);
// //
// This is more expensive than `GetEstimatedMemoryUsage()` as it requires // This is more expensive than `GetEstimatedMemoryUsage()` as it requires
// deduplicating all memory references. // deduplicating all memory references.
size_t GetMorePreciseMemoryUsage(const CordRep* rep); size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep);
// Returns the *approximate* number of bytes held in full or in part by this // Returns the *approximate* number of bytes held in full or in part by this
// CordRep weighted by the sharing ratio of that data. For example, if some data // CordRep weighted by the sharing ratio of that data. For example, if some data
// edge is shared by 4 different Cords, then each cord is attribute 1/4th of // edge is shared by 4 different Cords, then each cord is attribute 1/4th of
// the total memory usage as a 'fair share' of the total memory usage. // the total memory usage as a 'fair share' of the total memory usage.
size_t GetEstimatedFairShareMemoryUsage(const CordRep* rep); size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep);
} // namespace cord_internal } // namespace cord_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/strings/cord.h" #include "absl/strings/cord.h"
#include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cordz_info.h" #include "absl/strings/internal/cordz_info.h"
...@@ -33,15 +34,16 @@ namespace absl { ...@@ -33,15 +34,16 @@ namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
// Returns the CordzInfo for the cord, or nullptr if the cord is not sampled. // Returns the CordzInfo for the cord, or nullptr if the cord is not sampled.
inline const cord_internal::CordzInfo* GetCordzInfoForTesting( inline absl::Nullable<const cord_internal::CordzInfo*> GetCordzInfoForTesting(
const Cord& cord) { const Cord& cord) {
if (!cord.contents_.is_tree()) return nullptr; if (!cord.contents_.is_tree()) return nullptr;
return cord.contents_.cordz_info(); return cord.contents_.cordz_info();
} }
// Returns true if the provided cordz_info is in the list of sampled cords. // Returns true if the provided cordz_info is in the list of sampled cords.
inline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info, inline bool CordzInfoIsListed(
cord_internal::CordzSampleToken token = {}) { absl::Nonnull<const cord_internal::CordzInfo*> cordz_info,
cord_internal::CordzSampleToken token = {}) {
for (const cord_internal::CordzInfo& info : token) { for (const cord_internal::CordzInfo& info : token) {
if (cordz_info == &info) return true; if (cordz_info == &info) return true;
} }
...@@ -119,7 +121,7 @@ class CordzSamplingIntervalHelper { ...@@ -119,7 +121,7 @@ class CordzSamplingIntervalHelper {
// Wrapper struct managing a small CordRep `rep` // Wrapper struct managing a small CordRep `rep`
struct TestCordRep { struct TestCordRep {
cord_internal::CordRepFlat* rep; absl::Nonnull<cord_internal::CordRepFlat*> rep;
TestCordRep() { TestCordRep() {
rep = cord_internal::CordRepFlat::New(100); rep = cord_internal::CordRepFlat::New(100);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/endian.h" #include "absl/base/internal/endian.h"
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h" #include "absl/base/optimization.h"
#include "absl/numeric/bits.h" #include "absl/numeric/bits.h"
#include "absl/numeric/int128.h" #include "absl/numeric/int128.h"
...@@ -45,7 +46,7 @@ ...@@ -45,7 +46,7 @@
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
bool SimpleAtof(absl::string_view str, float* out) { bool SimpleAtof(absl::string_view str, absl::Nonnull<float*> out) {
*out = 0.0; *out = 0.0;
str = StripAsciiWhitespace(str); str = StripAsciiWhitespace(str);
// std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
...@@ -76,7 +77,7 @@ bool SimpleAtof(absl::string_view str, float* out) { ...@@ -76,7 +77,7 @@ bool SimpleAtof(absl::string_view str, float* out) {
return true; return true;
} }
bool SimpleAtod(absl::string_view str, double* out) { bool SimpleAtod(absl::string_view str, absl::Nonnull<double*> out) {
*out = 0.0; *out = 0.0;
str = StripAsciiWhitespace(str); str = StripAsciiWhitespace(str);
// std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
...@@ -107,7 +108,7 @@ bool SimpleAtod(absl::string_view str, double* out) { ...@@ -107,7 +108,7 @@ bool SimpleAtod(absl::string_view str, double* out) {
return true; return true;
} }
bool SimpleAtob(absl::string_view str, bool* out) { bool SimpleAtob(absl::string_view str, absl::Nonnull<bool*> out) {
ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr."); ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") || if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") || EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
...@@ -166,7 +167,7 @@ constexpr uint64_t kDivisionBy100Mul = 10486u; ...@@ -166,7 +167,7 @@ constexpr uint64_t kDivisionBy100Mul = 10486u;
constexpr uint64_t kDivisionBy100Div = 1 << 20; constexpr uint64_t kDivisionBy100Div = 1 << 20;
// Encode functions write the ASCII output of input `n` to `out_str`. // Encode functions write the ASCII output of input `n` to `out_str`.
inline char* EncodeHundred(uint32_t n, char* out_str) { inline char* EncodeHundred(uint32_t n, absl::Nonnull<char*> out_str) {
int num_digits = static_cast<int>(n - 10) >> 8; int num_digits = static_cast<int>(n - 10) >> 8;
uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div; uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div;
uint32_t mod10 = n - 10u * div10; uint32_t mod10 = n - 10u * div10;
...@@ -176,7 +177,7 @@ inline char* EncodeHundred(uint32_t n, char* out_str) { ...@@ -176,7 +177,7 @@ inline char* EncodeHundred(uint32_t n, char* out_str) {
return out_str + 2 + num_digits; return out_str + 2 + num_digits;
} }
inline char* EncodeTenThousand(uint32_t n, char* out_str) { inline char* EncodeTenThousand(uint32_t n, absl::Nonnull<char*> out_str) {
// We split lower 2 digits and upper 2 digits of n into 2 byte consecutive // We split lower 2 digits and upper 2 digits of n into 2 byte consecutive
// blocks. 123 -> [\0\1][\0\23]. We divide by 10 both blocks // blocks. 123 -> [\0\1][\0\23]. We divide by 10 both blocks
// (it's 1 division + zeroing upper bits), and compute modulo 10 as well "in // (it's 1 division + zeroing upper bits), and compute modulo 10 as well "in
...@@ -232,8 +233,8 @@ inline uint64_t PrepareEightDigits(uint32_t i) { ...@@ -232,8 +233,8 @@ inline uint64_t PrepareEightDigits(uint32_t i) {
return tens; return tens;
} }
inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU32(uint32_t n, inline ABSL_ATTRIBUTE_ALWAYS_INLINE absl::Nonnull<char*> EncodeFullU32(
char* out_str) { uint32_t n, absl::Nonnull<char*> out_str) {
if (n < 10) { if (n < 10) {
*out_str = static_cast<char>('0' + n); *out_str = static_cast<char>('0' + n);
return out_str + 1; return out_str + 1;
...@@ -282,7 +283,7 @@ inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU64(uint64_t i, ...@@ -282,7 +283,7 @@ inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* EncodeFullU64(uint64_t i,
} // namespace } // namespace
void numbers_internal::PutTwoDigits(uint32_t i, char* buf) { void numbers_internal::PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf) {
assert(i < 100); assert(i < 100);
uint32_t base = kTwoZeroBytes; uint32_t base = kTwoZeroBytes;
uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div; uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div;
...@@ -291,13 +292,15 @@ void numbers_internal::PutTwoDigits(uint32_t i, char* buf) { ...@@ -291,13 +292,15 @@ void numbers_internal::PutTwoDigits(uint32_t i, char* buf) {
little_endian::Store16(buf, static_cast<uint16_t>(base)); little_endian::Store16(buf, static_cast<uint16_t>(base));
} }
char* numbers_internal::FastIntToBuffer(uint32_t n, char* out_str) { absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
uint32_t n, absl::Nonnull<char*> out_str) {
out_str = EncodeFullU32(n, out_str); out_str = EncodeFullU32(n, out_str);
*out_str = '\0'; *out_str = '\0';
return out_str; return out_str;
} }
char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) { absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
int32_t i, absl::Nonnull<char*> buffer) {
uint32_t u = static_cast<uint32_t>(i); uint32_t u = static_cast<uint32_t>(i);
if (i < 0) { if (i < 0) {
*buffer++ = '-'; *buffer++ = '-';
...@@ -311,13 +314,15 @@ char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) { ...@@ -311,13 +314,15 @@ char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) {
return buffer; return buffer;
} }
char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) { absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
uint64_t i, absl::Nonnull<char*> buffer) {
buffer = EncodeFullU64(i, buffer); buffer = EncodeFullU64(i, buffer);
*buffer = '\0'; *buffer = '\0';
return buffer; return buffer;
} }
char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) { absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
int64_t i, absl::Nonnull<char*> buffer) {
uint64_t u = static_cast<uint64_t>(i); uint64_t u = static_cast<uint64_t>(i);
if (i < 0) { if (i < 0) {
*buffer++ = '-'; *buffer++ = '-';
...@@ -538,7 +543,8 @@ static ExpDigits SplitToSix(const double value) { ...@@ -538,7 +543,8 @@ static ExpDigits SplitToSix(const double value) {
// Helper function for fast formatting of floating-point. // Helper function for fast formatting of floating-point.
// The result is the same as "%g", a.k.a. "%.6g". // The result is the same as "%g", a.k.a. "%.6g".
size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) { size_t numbers_internal::SixDigitsToBuffer(double d,
absl::Nonnull<char*> const buffer) {
static_assert(std::numeric_limits<float>::is_iec559, static_assert(std::numeric_limits<float>::is_iec559,
"IEEE-754/IEC-559 support only"); "IEEE-754/IEC-559 support only");
...@@ -685,9 +691,10 @@ static const int8_t kAsciiToInt[256] = { ...@@ -685,9 +691,10 @@ static const int8_t kAsciiToInt[256] = {
36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}; 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36};
// Parse the sign and optional hex or oct prefix in text. // Parse the sign and optional hex or oct prefix in text.
inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/, inline bool safe_parse_sign_and_base(
int* base_ptr /*inout*/, absl::Nonnull<absl::string_view*> text /*inout*/,
bool* negative_ptr /*output*/) { absl::Nonnull<int*> base_ptr /*inout*/,
absl::Nonnull<bool*> negative_ptr /*output*/) {
if (text->data() == nullptr) { if (text->data() == nullptr) {
return false; return false;
} }
...@@ -972,7 +979,7 @@ ABSL_CONST_INIT const IntType LookupTables<IntType>::kVminOverBase[] = ...@@ -972,7 +979,7 @@ ABSL_CONST_INIT const IntType LookupTables<IntType>::kVminOverBase[] =
template <typename IntType> template <typename IntType>
inline bool safe_parse_positive_int(absl::string_view text, int base, inline bool safe_parse_positive_int(absl::string_view text, int base,
IntType* value_p) { absl::Nonnull<IntType*> value_p) {
IntType value = 0; IntType value = 0;
const IntType vmax = std::numeric_limits<IntType>::max(); const IntType vmax = std::numeric_limits<IntType>::max();
assert(vmax > 0); assert(vmax > 0);
...@@ -1009,7 +1016,7 @@ inline bool safe_parse_positive_int(absl::string_view text, int base, ...@@ -1009,7 +1016,7 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
template <typename IntType> template <typename IntType>
inline bool safe_parse_negative_int(absl::string_view text, int base, inline bool safe_parse_negative_int(absl::string_view text, int base,
IntType* value_p) { absl::Nonnull<IntType*> value_p) {
IntType value = 0; IntType value = 0;
const IntType vmin = std::numeric_limits<IntType>::min(); const IntType vmin = std::numeric_limits<IntType>::min();
assert(vmin < 0); assert(vmin < 0);
...@@ -1053,8 +1060,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base, ...@@ -1053,8 +1060,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base,
// Input format based on POSIX.1-2008 strtol // Input format based on POSIX.1-2008 strtol
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
template <typename IntType> template <typename IntType>
inline bool safe_int_internal(absl::string_view text, IntType* value_p, inline bool safe_int_internal(absl::string_view text,
int base) { absl::Nonnull<IntType*> value_p, int base) {
*value_p = 0; *value_p = 0;
bool negative; bool negative;
if (!safe_parse_sign_and_base(&text, &base, &negative)) { if (!safe_parse_sign_and_base(&text, &base, &negative)) {
...@@ -1068,8 +1075,8 @@ inline bool safe_int_internal(absl::string_view text, IntType* value_p, ...@@ -1068,8 +1075,8 @@ inline bool safe_int_internal(absl::string_view text, IntType* value_p,
} }
template <typename IntType> template <typename IntType>
inline bool safe_uint_internal(absl::string_view text, IntType* value_p, inline bool safe_uint_internal(absl::string_view text,
int base) { absl::Nonnull<IntType*> value_p, int base) {
*value_p = 0; *value_p = 0;
bool negative; bool negative;
if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) { if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) {
...@@ -1103,27 +1110,33 @@ ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] = ...@@ -1103,27 +1110,33 @@ ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
bool safe_strto32_base(absl::string_view text, int32_t* value, int base) { bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
int base) {
return safe_int_internal<int32_t>(text, value, base); return safe_int_internal<int32_t>(text, value, base);
} }
bool safe_strto64_base(absl::string_view text, int64_t* value, int base) { bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value,
int base) {
return safe_int_internal<int64_t>(text, value, base); return safe_int_internal<int64_t>(text, value, base);
} }
bool safe_strto128_base(absl::string_view text, int128* value, int base) { bool safe_strto128_base(absl::string_view text, absl::Nonnull<int128*> value,
int base) {
return safe_int_internal<absl::int128>(text, value, base); return safe_int_internal<absl::int128>(text, value, base);
} }
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) { bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
int base) {
return safe_uint_internal<uint32_t>(text, value, base); return safe_uint_internal<uint32_t>(text, value, base);
} }
bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) { bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value,
int base) {
return safe_uint_internal<uint64_t>(text, value, base); return safe_uint_internal<uint64_t>(text, value, base);
} }
bool safe_strtou128_base(absl::string_view text, uint128* value, int base) { bool safe_strtou128_base(absl::string_view text, absl::Nonnull<uint128*> value,
int base) {
return safe_uint_internal<absl::uint128>(text, value, base); return safe_uint_internal<absl::uint128>(text, value, base);
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/endian.h" #include "absl/base/internal/endian.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h" #include "absl/base/port.h"
#include "absl/numeric/bits.h" #include "absl/numeric/bits.h"
#include "absl/numeric/int128.h" #include "absl/numeric/int128.h"
...@@ -59,7 +60,8 @@ ABSL_NAMESPACE_BEGIN ...@@ -59,7 +60,8 @@ ABSL_NAMESPACE_BEGIN
// encountered, this function returns `false`, leaving `out` in an unspecified // encountered, this function returns `false`, leaving `out` in an unspecified
// state. // state.
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str,
absl::Nonnull<int_type*> out);
// SimpleAtof() // SimpleAtof()
// //
...@@ -70,7 +72,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); ...@@ -70,7 +72,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
// allowed formats for `str`, except SimpleAtof() is locale-independent and will // allowed formats for `str`, except SimpleAtof() is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function // always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state. // returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str,
absl::Nonnull<float*> out);
// SimpleAtod() // SimpleAtod()
// //
...@@ -81,7 +84,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); ...@@ -81,7 +84,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
// allowed formats for `str`, except SimpleAtod is locale-independent and will // allowed formats for `str`, except SimpleAtod is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function // always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state. // returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str,
absl::Nonnull<double*> out);
// SimpleAtob() // SimpleAtob()
// //
...@@ -91,7 +95,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); ...@@ -91,7 +95,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any // are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
// errors are encountered, this function returns `false`, leaving `out` in an // errors are encountered, this function returns `false`, leaving `out` in an
// unspecified state. // unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str,
absl::Nonnull<bool*> out);
// SimpleHexAtoi() // SimpleHexAtoi()
// //
...@@ -104,13 +109,14 @@ ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); ...@@ -104,13 +109,14 @@ ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
// by this function. If any errors are encountered, this function returns // by this function. If any errors are encountered, this function returns
// `false`, leaving `out` in an unspecified state. // `false`, leaving `out` in an unspecified state.
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out); ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str,
absl::Nonnull<int_type*> out);
// Overloads of SimpleHexAtoi() for 128 bit integers. // Overloads of SimpleHexAtoi() for 128 bit integers.
ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
absl::int128* out); absl::string_view str, absl::Nonnull<absl::int128*> out);
ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
absl::uint128* out); absl::string_view str, absl::Nonnull<absl::uint128*> out);
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
...@@ -132,18 +138,22 @@ ABSL_DLL extern const char ...@@ -132,18 +138,22 @@ ABSL_DLL extern const char
// PutTwoDigits(42, buf); // PutTwoDigits(42, buf);
// // buf[0] == '4' // // buf[0] == '4'
// // buf[1] == '2' // // buf[1] == '2'
void PutTwoDigits(uint32_t i, char* buf); void PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf);
// safe_strto?() functions for implementing SimpleAtoi() // safe_strto?() functions for implementing SimpleAtoi()
bool safe_strto32_base(absl::string_view text, int32_t* value, int base); bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
bool safe_strto64_base(absl::string_view text, int64_t* value, int base); int base);
bool safe_strto128_base(absl::string_view text, absl::int128* value, bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value,
int base); int base);
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base); bool safe_strto128_base(absl::string_view text,
bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base); absl::Nonnull<absl::int128*> value, int base);
bool safe_strtou128_base(absl::string_view text, absl::uint128* value, bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
int base); int base);
bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value,
int base);
bool safe_strtou128_base(absl::string_view text,
absl::Nonnull<absl::uint128*> value, int base);
static const int kFastToBufferSize = 32; static const int kFastToBufferSize = 32;
static const int kSixDigitsToBufferSize = 16; static const int kSixDigitsToBufferSize = 16;
...@@ -154,20 +164,20 @@ static const int kSixDigitsToBufferSize = 16; ...@@ -154,20 +164,20 @@ static const int kSixDigitsToBufferSize = 16;
// outside the range 0.0001-999999 are output using scientific notation // outside the range 0.0001-999999 are output using scientific notation
// (1.23456e+06). This routine is heavily optimized. // (1.23456e+06). This routine is heavily optimized.
// Required buffer size is `kSixDigitsToBufferSize`. // Required buffer size is `kSixDigitsToBufferSize`.
size_t SixDigitsToBuffer(double d, char* buffer); size_t SixDigitsToBuffer(double d, absl::Nonnull<char*> buffer);
// These functions are intended for speed. All functions take an output buffer // These functions are intended for speed. All functions take an output buffer
// as an argument and return a pointer to the last byte they wrote, which is the // as an argument and return a pointer to the last byte they wrote, which is the
// terminating '\0'. At most `kFastToBufferSize` bytes are written. // terminating '\0'. At most `kFastToBufferSize` bytes are written.
char* FastIntToBuffer(int32_t, char*); absl::Nonnull<char*> FastIntToBuffer(int32_t, absl::Nonnull<char*>);
char* FastIntToBuffer(uint32_t, char*); absl::Nonnull<char*> FastIntToBuffer(uint32_t, absl::Nonnull<char*>);
char* FastIntToBuffer(int64_t, char*); absl::Nonnull<char*> FastIntToBuffer(int64_t, absl::Nonnull<char*>);
char* FastIntToBuffer(uint64_t, char*); absl::Nonnull<char*> FastIntToBuffer(uint64_t, absl::Nonnull<char*>);
// For enums and integer types that are not an exact match for the types above, // For enums and integer types that are not an exact match for the types above,
// use templates to call the appropriate one of the four overloads above. // use templates to call the appropriate one of the four overloads above.
template <typename int_type> template <typename int_type>
char* FastIntToBuffer(int_type i, char* buffer) { absl::Nonnull<char*> FastIntToBuffer(int_type i, absl::Nonnull<char*> buffer) {
static_assert(sizeof(i) <= 64 / 8, static_assert(sizeof(i) <= 64 / 8,
"FastIntToBuffer works only with 64-bit-or-less integers."); "FastIntToBuffer works only with 64-bit-or-less integers.");
// TODO(jorg): This signed-ness check is used because it works correctly // TODO(jorg): This signed-ness check is used because it works correctly
...@@ -194,7 +204,8 @@ char* FastIntToBuffer(int_type i, char* buffer) { ...@@ -194,7 +204,8 @@ char* FastIntToBuffer(int_type i, char* buffer) {
// Implementation of SimpleAtoi, generalized to support arbitrary base (used // Implementation of SimpleAtoi, generalized to support arbitrary base (used
// with base different from 10 elsewhere in Abseil implementation). // with base different from 10 elsewhere in Abseil implementation).
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s,
absl::Nonnull<int_type*> out,
int base) { int base) {
static_assert(sizeof(*out) == 4 || sizeof(*out) == 8, static_assert(sizeof(*out) == 4 || sizeof(*out) == 8,
"SimpleAtoi works only with 32-bit or 64-bit integers."); "SimpleAtoi works only with 32-bit or 64-bit integers.");
...@@ -237,7 +248,7 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, ...@@ -237,7 +248,7 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out,
// without the terminating null character. Thus `out` must be of length >= 16. // without the terminating null character. Thus `out` must be of length >= 16.
// Returns the number of non-pad digits of the output (it can never be zero // Returns the number of non-pad digits of the output (it can never be zero
// since 0 has one digit). // since 0 has one digit).
inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) { inline size_t FastHexToBufferZeroPad16(uint64_t val, absl::Nonnull<char*> out) {
#ifdef ABSL_INTERNAL_HAVE_SSSE3 #ifdef ABSL_INTERNAL_HAVE_SSSE3
uint64_t be = absl::big_endian::FromHost64(val); uint64_t be = absl::big_endian::FromHost64(val);
const auto kNibbleMask = _mm_set1_epi8(0xf); const auto kNibbleMask = _mm_set1_epi8(0xf);
...@@ -263,32 +274,34 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) { ...@@ -263,32 +274,34 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
} // namespace numbers_internal } // namespace numbers_internal
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) { ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str,
absl::Nonnull<int_type*> out) {
return numbers_internal::safe_strtoi_base(str, out, 10); return numbers_internal::safe_strtoi_base(str, out, 10);
} }
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
absl::int128* out) { absl::Nonnull<absl::int128*> out) {
return numbers_internal::safe_strto128_base(str, out, 10); return numbers_internal::safe_strto128_base(str, out, 10);
} }
ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
absl::uint128* out) { absl::Nonnull<absl::uint128*> out) {
return numbers_internal::safe_strtou128_base(str, out, 10); return numbers_internal::safe_strtou128_base(str, out, 10);
} }
template <typename int_type> template <typename int_type>
ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out) { ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str,
absl::Nonnull<int_type*> out) {
return numbers_internal::safe_strtoi_base(str, out, 16); return numbers_internal::safe_strtoi_base(str, out, 16);
} }
ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
absl::int128* out) { absl::string_view str, absl::Nonnull<absl::int128*> out) {
return numbers_internal::safe_strto128_base(str, out, 16); return numbers_internal::safe_strto128_base(str, out, 16);
} }
ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
absl::uint128* out) { absl::string_view str, absl::Nonnull<absl::uint128*> out) {
return numbers_internal::safe_strtou128_base(str, out, 16); return numbers_internal::safe_strtou128_base(str, out, 16);
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <string> #include <string>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -40,7 +41,8 @@ ABSL_NAMESPACE_BEGIN ...@@ -40,7 +41,8 @@ ABSL_NAMESPACE_BEGIN
namespace { namespace {
// Append is merely a version of memcpy that returns the address of the byte // Append is merely a version of memcpy that returns the address of the byte
// after the area just overwritten. // after the area just overwritten.
inline char* Append(char* out, const AlphaNum& x) { inline absl::Nonnull<char*> Append(absl::Nonnull<char*> out,
const AlphaNum& x) {
// memcpy is allowed to overwrite arbitrary memory, so doing this after the // memcpy is allowed to overwrite arbitrary memory, so doing this after the
// call would force an extra fetch of x.size(). // call would force an extra fetch of x.size().
char* after = out + x.size(); char* after = out + x.size();
...@@ -128,7 +130,7 @@ std::string CatPieces(std::initializer_list<absl::string_view> pieces) { ...@@ -128,7 +130,7 @@ std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
assert(((src).size() == 0) || \ assert(((src).size() == 0) || \
(uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size()))) (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
void AppendPieces(std::string* dest, void AppendPieces(absl::Nonnull<std::string*> dest,
std::initializer_list<absl::string_view> pieces) { std::initializer_list<absl::string_view> pieces) {
size_t old_size = dest->size(); size_t old_size = dest->size();
size_t to_append = 0; size_t to_append = 0;
...@@ -152,7 +154,7 @@ void AppendPieces(std::string* dest, ...@@ -152,7 +154,7 @@ void AppendPieces(std::string* dest,
} // namespace strings_internal } // namespace strings_internal
void StrAppend(std::string* dest, const AlphaNum& a) { void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a) {
ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, a);
std::string::size_type old_size = dest->size(); std::string::size_type old_size = dest->size();
STLStringAppendUninitializedAmortized(dest, a.size()); STLStringAppendUninitializedAmortized(dest, a.size());
...@@ -162,7 +164,8 @@ void StrAppend(std::string* dest, const AlphaNum& a) { ...@@ -162,7 +164,8 @@ void StrAppend(std::string* dest, const AlphaNum& a) {
assert(out == begin + dest->size()); assert(out == begin + dest->size());
} }
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) { void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
const AlphaNum& b) {
ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, a);
ASSERT_NO_OVERLAP(*dest, b); ASSERT_NO_OVERLAP(*dest, b);
std::string::size_type old_size = dest->size(); std::string::size_type old_size = dest->size();
...@@ -174,8 +177,8 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) { ...@@ -174,8 +177,8 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) {
assert(out == begin + dest->size()); assert(out == begin + dest->size());
} }
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
const AlphaNum& c) { const AlphaNum& b, const AlphaNum& c) {
ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, a);
ASSERT_NO_OVERLAP(*dest, b); ASSERT_NO_OVERLAP(*dest, b);
ASSERT_NO_OVERLAP(*dest, c); ASSERT_NO_OVERLAP(*dest, c);
...@@ -189,8 +192,8 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, ...@@ -189,8 +192,8 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
assert(out == begin + dest->size()); assert(out == begin + dest->size());
} }
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
const AlphaNum& c, const AlphaNum& d) { const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) {
ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, a);
ASSERT_NO_OVERLAP(*dest, b); ASSERT_NO_OVERLAP(*dest, b);
ASSERT_NO_OVERLAP(*dest, c); ASSERT_NO_OVERLAP(*dest, c);
......
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
#include <vector> #include <vector>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h" #include "absl/base/port.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/strings/has_absl_stringify.h" #include "absl/strings/has_absl_stringify.h"
...@@ -206,7 +207,7 @@ struct Hex { ...@@ -206,7 +207,7 @@ struct Hex {
!std::is_pointer<Int>::value>::type* = nullptr) !std::is_pointer<Int>::value>::type* = nullptr)
: Hex(spec, static_cast<uint64_t>(v)) {} : Hex(spec, static_cast<uint64_t>(v)) {}
template <typename Pointee> template <typename Pointee>
explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad) explicit Hex(absl::Nullable<Pointee*> v, PadSpec spec = absl::kNoPad)
: Hex(spec, reinterpret_cast<uintptr_t>(v)) {} : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
template <typename S> template <typename S>
...@@ -349,7 +350,7 @@ class AlphaNum { ...@@ -349,7 +350,7 @@ class AlphaNum {
ABSL_ATTRIBUTE_LIFETIME_BOUND) ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(&buf.data[0], buf.size) {} : piece_(&buf.data[0], buf.size) {}
AlphaNum(const char* c_str // NOLINT(runtime/explicit) AlphaNum(absl::Nullable<const char*> c_str // NOLINT(runtime/explicit)
ABSL_ATTRIBUTE_LIFETIME_BOUND) ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(NullSafeStringView(c_str)) {} : piece_(NullSafeStringView(c_str)) {}
AlphaNum(absl::string_view pc // NOLINT(runtime/explicit) AlphaNum(absl::string_view pc // NOLINT(runtime/explicit)
...@@ -376,7 +377,7 @@ class AlphaNum { ...@@ -376,7 +377,7 @@ class AlphaNum {
AlphaNum& operator=(const AlphaNum&) = delete; AlphaNum& operator=(const AlphaNum&) = delete;
absl::string_view::size_type size() const { return piece_.size(); } absl::string_view::size_type size() const { return piece_.size(); }
const char* data() const { return piece_.data(); } absl::Nullable<const char*> data() const { return piece_.data(); }
absl::string_view Piece() const { return piece_; } absl::string_view Piece() const { return piece_; }
// Match unscoped enums. Use integral promotion so that a `char`-backed // Match unscoped enums. Use integral promotion so that a `char`-backed
...@@ -446,7 +447,7 @@ namespace strings_internal { ...@@ -446,7 +447,7 @@ namespace strings_internal {
// Do not call directly - this is not part of the public API. // Do not call directly - this is not part of the public API.
std::string CatPieces(std::initializer_list<absl::string_view> pieces); std::string CatPieces(std::initializer_list<absl::string_view> pieces);
void AppendPieces(std::string* dest, void AppendPieces(absl::Nonnull<std::string*> dest,
std::initializer_list<absl::string_view> pieces); std::initializer_list<absl::string_view> pieces);
template <typename Integer> template <typename Integer>
...@@ -576,19 +577,20 @@ ABSL_MUST_USE_RESULT inline std::string StrCat( ...@@ -576,19 +577,20 @@ ABSL_MUST_USE_RESULT inline std::string StrCat(
// absl::string_view p = s; // absl::string_view p = s;
// StrAppend(&s, p); // StrAppend(&s, p);
inline void StrAppend(std::string*) {} inline void StrAppend(absl::Nonnull<std::string*>) {}
void StrAppend(std::string* dest, const AlphaNum& a); void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a);
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b); void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& b);
const AlphaNum& c); void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& b, const AlphaNum& c);
const AlphaNum& c, const AlphaNum& d); void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
const AlphaNum& b, const AlphaNum& c, const AlphaNum& d);
// Support 5 or more arguments // Support 5 or more arguments
template <typename... AV> template <typename... AV>
inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, inline void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
const AlphaNum& c, const AlphaNum& d, const AlphaNum& e, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
const AV&... args) { const AlphaNum& e, const AV&... args) {
strings_internal::AppendPieces( strings_internal::AppendPieces(
dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(), dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
static_cast<const AlphaNum&>(args).Piece()...}); static_cast<const AlphaNum&>(args).Piece()...});
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/str_format/arg.h" // IWYU pragma: export #include "absl/strings/internal/str_format/arg.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/bind.h" // IWYU pragma: export #include "absl/strings/internal/str_format/bind.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/checker.h" // IWYU pragma: export #include "absl/strings/internal/str_format/checker.h" // IWYU pragma: export
...@@ -110,7 +111,8 @@ class UntypedFormatSpec { ...@@ -110,7 +111,8 @@ class UntypedFormatSpec {
explicit UntypedFormatSpec(string_view s) : spec_(s) {} explicit UntypedFormatSpec(string_view s) : spec_(s) {}
protected: protected:
explicit UntypedFormatSpec(const str_format_internal::ParsedFormatBase* pc) explicit UntypedFormatSpec(
absl::Nonnull<const str_format_internal::ParsedFormatBase*> pc)
: spec_(pc) {} : spec_(pc) {}
private: private:
...@@ -150,7 +152,7 @@ str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) { ...@@ -150,7 +152,7 @@ str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
// EXPECT_EQ(8, n); // EXPECT_EQ(8, n);
class FormatCountCapture { class FormatCountCapture {
public: public:
explicit FormatCountCapture(int* p) : p_(p) {} explicit FormatCountCapture(absl::Nonnull<int*> p) : p_(p) {}
private: private:
// FormatCountCaptureHelper is used to define FormatConvertImpl() for this // FormatCountCaptureHelper is used to define FormatConvertImpl() for this
...@@ -159,8 +161,8 @@ class FormatCountCapture { ...@@ -159,8 +161,8 @@ class FormatCountCapture {
// Unused() is here because of the false positive from -Wunused-private-field // Unused() is here because of the false positive from -Wunused-private-field
// p_ is used in the templated function of the friend FormatCountCaptureHelper // p_ is used in the templated function of the friend FormatCountCaptureHelper
// class. // class.
int* Unused() { return p_; } absl::Nonnull<int*> Unused() { return p_; }
int* p_; absl::Nonnull<int*> p_;
}; };
// FormatSpec // FormatSpec
...@@ -375,7 +377,7 @@ ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format, ...@@ -375,7 +377,7 @@ ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
// std::string orig("For example PI is approximately "); // std::string orig("For example PI is approximately ");
// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14); // std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
template <typename... Args> template <typename... Args>
std::string& StrAppendFormat(std::string* dst, std::string& StrAppendFormat(absl::Nonnull<std::string*> dst,
const FormatSpec<Args...>& format, const FormatSpec<Args...>& format,
const Args&... args) { const Args&... args) {
return str_format_internal::AppendPack( return str_format_internal::AppendPack(
...@@ -435,7 +437,7 @@ int PrintF(const FormatSpec<Args...>& format, const Args&... args) { ...@@ -435,7 +437,7 @@ int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
// Outputs: "The capital of Mongolia is Ulaanbaatar" // Outputs: "The capital of Mongolia is Ulaanbaatar"
// //
template <typename... Args> template <typename... Args>
int FPrintF(std::FILE* output, const FormatSpec<Args...>& format, int FPrintF(absl::Nonnull<std::FILE*> output, const FormatSpec<Args...>& format,
const Args&... args) { const Args&... args) {
return str_format_internal::FprintF( return str_format_internal::FprintF(
output, str_format_internal::UntypedFormatSpecImpl::Extract(format), output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
...@@ -464,8 +466,8 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format, ...@@ -464,8 +466,8 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
// Post-condition: output == "The capital of Mongolia is Ulaanbaatar" // Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
// //
template <typename... Args> template <typename... Args>
int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format, int SNPrintF(absl::Nonnull<char*> output, std::size_t size,
const Args&... args) { const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::SnprintF( return str_format_internal::SnprintF(
output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format), output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...}); {str_format_internal::FormatArgImpl(args)...});
...@@ -498,7 +500,7 @@ class FormatRawSink { ...@@ -498,7 +500,7 @@ class FormatRawSink {
template <typename T, template <typename T,
typename = typename std::enable_if<std::is_constructible< typename = typename std::enable_if<std::is_constructible<
str_format_internal::FormatRawSinkImpl, T*>::value>::type> str_format_internal::FormatRawSinkImpl, T*>::value>::type>
FormatRawSink(T* raw) // NOLINT FormatRawSink(absl::Nonnull<T*> raw) // NOLINT
: sink_(raw) {} : sink_(raw) {}
private: private:
...@@ -855,14 +857,16 @@ class FormatSink { ...@@ -855,14 +857,16 @@ class FormatSink {
} }
// Support `absl::Format(&sink, format, args...)`. // Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(FormatSink* sink, absl::string_view v) { friend void AbslFormatFlush(absl::Nonnull<FormatSink*> sink,
absl::string_view v) {
sink->Append(v); sink->Append(v);
} }
private: private:
friend str_format_internal::FormatSinkImpl; friend str_format_internal::FormatSinkImpl;
explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {} explicit FormatSink(absl::Nonnull<str_format_internal::FormatSinkImpl*> s)
str_format_internal::FormatSinkImpl* sink_; : sink_(s) {}
absl::Nonnull<str_format_internal::FormatSinkImpl*> sink_;
}; };
// FormatConvertResult // FormatConvertResult
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <vector> #include <vector>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -36,8 +37,8 @@ using FixedMapping = ...@@ -36,8 +37,8 @@ using FixedMapping =
// occurred. // occurred.
int ApplySubstitutions( int ApplySubstitutions(
absl::string_view s, absl::string_view s,
std::vector<strings_internal::ViableSubstitution>* subs_ptr, absl::Nonnull<std::vector<strings_internal::ViableSubstitution>*> subs_ptr,
std::string* result_ptr) { absl::Nonnull<std::string*> result_ptr) {
auto& subs = *subs_ptr; auto& subs = *subs_ptr;
int substitutions = 0; int substitutions = 0;
size_t pos = 0; size_t pos = 0;
...@@ -82,7 +83,7 @@ std::string StrReplaceAll(absl::string_view s, ...@@ -82,7 +83,7 @@ std::string StrReplaceAll(absl::string_view s,
} }
int StrReplaceAll(strings_internal::FixedMapping replacements, int StrReplaceAll(strings_internal::FixedMapping replacements,
std::string* target) { absl::Nonnull<std::string*> target) {
return StrReplaceAll<strings_internal::FixedMapping>(replacements, target); return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
} }
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <vector> #include <vector>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
namespace absl { namespace absl {
...@@ -113,7 +114,7 @@ std::string StrReplaceAll(absl::string_view s, ...@@ -113,7 +114,7 @@ std::string StrReplaceAll(absl::string_view s,
int StrReplaceAll( int StrReplaceAll(
std::initializer_list<std::pair<absl::string_view, absl::string_view>> std::initializer_list<std::pair<absl::string_view, absl::string_view>>
replacements, replacements,
std::string* target); absl::Nonnull<std::string*> target);
// Overload of `StrReplaceAll()` to replace patterns within a given output // Overload of `StrReplaceAll()` to replace patterns within a given output
// string *in place* with replacements provided within a container of key/value // string *in place* with replacements provided within a container of key/value
...@@ -128,7 +129,8 @@ int StrReplaceAll( ...@@ -128,7 +129,8 @@ int StrReplaceAll(
// EXPECT_EQ(count, 2); // EXPECT_EQ(count, 2);
// EXPECT_EQ("if (ptr &lt; &amp;foo)", s); // EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
template <typename StrToStrMapping> template <typename StrToStrMapping>
int StrReplaceAll(const StrToStrMapping& replacements, std::string* target); int StrReplaceAll(const StrToStrMapping& replacements,
absl::Nonnull<std::string*> target);
// Implementation details only, past this point. // Implementation details only, past this point.
namespace strings_internal { namespace strings_internal {
...@@ -185,8 +187,8 @@ std::vector<ViableSubstitution> FindSubstitutions( ...@@ -185,8 +187,8 @@ std::vector<ViableSubstitution> FindSubstitutions(
} }
int ApplySubstitutions(absl::string_view s, int ApplySubstitutions(absl::string_view s,
std::vector<ViableSubstitution>* subs_ptr, absl::Nonnull<std::vector<ViableSubstitution>*> subs_ptr,
std::string* result_ptr); absl::Nonnull<std::string*> result_ptr);
} // namespace strings_internal } // namespace strings_internal
...@@ -201,7 +203,8 @@ std::string StrReplaceAll(absl::string_view s, ...@@ -201,7 +203,8 @@ std::string StrReplaceAll(absl::string_view s,
} }
template <typename StrToStrMapping> template <typename StrToStrMapping>
int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) { int StrReplaceAll(const StrToStrMapping& replacements,
absl::Nonnull<std::string*> target) {
auto subs = strings_internal::FindSubstitutions(*target, replacements); auto subs = strings_internal::FindSubstitutions(*target, replacements);
if (subs.empty()) return 0; if (subs.empty()) return 0;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <cstring> #include <cstring>
#include <ostream> #include <ostream>
#include "absl/base/nullability.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -28,8 +30,10 @@ namespace { ...@@ -28,8 +30,10 @@ namespace {
// This is significantly faster for case-sensitive matches with very // This is significantly faster for case-sensitive matches with very
// few possible matches. // few possible matches.
const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, absl::Nullable<const char*> memmatch(absl::Nullable<const char*> phaystack,
size_t neelen) { size_t haylen,
absl::Nullable<const char*> pneedle,
size_t neelen) {
if (0 == neelen) { if (0 == neelen) {
return phaystack; // even if haylen is 0 return phaystack; // even if haylen is 0
} }
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <string> #include <string>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h" #include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
...@@ -162,11 +163,11 @@ class string_view { ...@@ -162,11 +163,11 @@ class string_view {
public: public:
using traits_type = std::char_traits<char>; using traits_type = std::char_traits<char>;
using value_type = char; using value_type = char;
using pointer = char*; using pointer = absl::Nullable<char*>;
using const_pointer = const char*; using const_pointer = absl::Nullable<const char*>;
using reference = char&; using reference = char&;
using const_reference = const char&; using const_reference = const char&;
using const_iterator = const char*; using const_iterator = absl::Nullable<const char*>;
using iterator = const_iterator; using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator; using reverse_iterator = const_reverse_iterator;
...@@ -194,11 +195,12 @@ class string_view { ...@@ -194,11 +195,12 @@ class string_view {
// accepting possibly null strings, use `absl::NullSafeStringView(str)` // accepting possibly null strings, use `absl::NullSafeStringView(str)`
// instead (see below). // instead (see below).
// The length check is skipped since it is unnecessary and causes code bloat. // The length check is skipped since it is unnecessary and causes code bloat.
constexpr string_view(const char* str) // NOLINT(runtime/explicit) constexpr string_view( // NOLINT(runtime/explicit)
absl::Nonnull<const char*> str)
: ptr_(str), length_(str ? StrlenInternal(str) : 0) {} : ptr_(str), length_(str ? StrlenInternal(str) : 0) {}
// Implicit constructor of a `string_view` from a `const char*` and length. // Implicit constructor of a `string_view` from a `const char*` and length.
constexpr string_view(const char* data, size_type len) constexpr string_view(absl::Nullable<const char*> data, size_type len)
: ptr_(data), length_(CheckLengthInternal(len)) {} : ptr_(data), length_(CheckLengthInternal(len)) {}
// NOTE: Harmlessly omitted to work around gdb bug. // NOTE: Harmlessly omitted to work around gdb bug.
...@@ -427,18 +429,21 @@ class string_view { ...@@ -427,18 +429,21 @@ class string_view {
// Overload of `string_view::compare()` for comparing a `string_view` and a // Overload of `string_view::compare()` for comparing a `string_view` and a
// a different C-style string `s`. // a different C-style string `s`.
constexpr int compare(const char* s) const { return compare(string_view(s)); } constexpr int compare(absl::Nonnull<const char*> s) const {
return compare(string_view(s));
}
// Overload of `string_view::compare()` for comparing a substring of the // Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a different string C-style string `s`. // `string_view` and a different string C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s) const { constexpr int compare(size_type pos1, size_type count1,
absl::Nonnull<const char*> s) const {
return substr(pos1, count1).compare(string_view(s)); return substr(pos1, count1).compare(string_view(s));
} }
// Overload of `string_view::compare()` for comparing a substring of the // Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of a different C-style string `s`. // `string_view` and a substring of a different C-style string `s`.
constexpr int compare(size_type pos1, size_type count1, const char* s, constexpr int compare(size_type pos1, size_type count1,
size_type count2) const { absl::Nonnull<const char*> s, size_type count2) const {
return substr(pos1, count1).compare(string_view(s, count2)); return substr(pos1, count1).compare(string_view(s, count2));
} }
...@@ -457,13 +462,14 @@ class string_view { ...@@ -457,13 +462,14 @@ class string_view {
// Overload of `string_view::find()` for finding a substring of a different // Overload of `string_view::find()` for finding a substring of a different
// C-style string `s` within the `string_view`. // C-style string `s` within the `string_view`.
size_type find(const char* s, size_type pos, size_type count) const { size_type find(absl::Nonnull<const char*> s, size_type pos,
size_type count) const {
return find(string_view(s, count), pos); return find(string_view(s, count), pos);
} }
// Overload of `string_view::find()` for finding a different C-style string // Overload of `string_view::find()` for finding a different C-style string
// `s` within the `string_view`. // `s` within the `string_view`.
size_type find(const char* s, size_type pos = 0) const { size_type find(absl::Nonnull<const char *> s, size_type pos = 0) const {
return find(string_view(s), pos); return find(string_view(s), pos);
} }
...@@ -480,13 +486,14 @@ class string_view { ...@@ -480,13 +486,14 @@ class string_view {
// Overload of `string_view::rfind()` for finding a substring of a different // Overload of `string_view::rfind()` for finding a substring of a different
// C-style string `s` within the `string_view`. // C-style string `s` within the `string_view`.
size_type rfind(const char* s, size_type pos, size_type count) const { size_type rfind(absl::Nonnull<const char*> s, size_type pos,
size_type count) const {
return rfind(string_view(s, count), pos); return rfind(string_view(s, count), pos);
} }
// Overload of `string_view::rfind()` for finding a different C-style string // Overload of `string_view::rfind()` for finding a different C-style string
// `s` within the `string_view`. // `s` within the `string_view`.
size_type rfind(const char* s, size_type pos = npos) const { size_type rfind(absl::Nonnull<const char*> s, size_type pos = npos) const {
return rfind(string_view(s), pos); return rfind(string_view(s), pos);
} }
...@@ -505,14 +512,15 @@ class string_view { ...@@ -505,14 +512,15 @@ class string_view {
// Overload of `string_view::find_first_of()` for finding a substring of a // Overload of `string_view::find_first_of()` for finding a substring of a
// different C-style string `s` within the `string_view`. // different C-style string `s` within the `string_view`.
size_type find_first_of(const char* s, size_type pos, size_type find_first_of(absl::Nonnull<const char*> s, size_type pos,
size_type count) const { size_type count) const {
return find_first_of(string_view(s, count), pos); return find_first_of(string_view(s, count), pos);
} }
// Overload of `string_view::find_first_of()` for finding a different C-style // Overload of `string_view::find_first_of()` for finding a different C-style
// string `s` within the `string_view`. // string `s` within the `string_view`.
size_type find_first_of(const char* s, size_type pos = 0) const { size_type find_first_of(absl::Nonnull<const char*> s,
size_type pos = 0) const {
return find_first_of(string_view(s), pos); return find_first_of(string_view(s), pos);
} }
...@@ -531,13 +539,15 @@ class string_view { ...@@ -531,13 +539,15 @@ class string_view {
// Overload of `string_view::find_last_of()` for finding a substring of a // Overload of `string_view::find_last_of()` for finding a substring of a
// different C-style string `s` within the `string_view`. // different C-style string `s` within the `string_view`.
size_type find_last_of(const char* s, size_type pos, size_type count) const { size_type find_last_of(absl::Nonnull<const char*> s, size_type pos,
size_type count) const {
return find_last_of(string_view(s, count), pos); return find_last_of(string_view(s, count), pos);
} }
// Overload of `string_view::find_last_of()` for finding a different C-style // Overload of `string_view::find_last_of()` for finding a different C-style
// string `s` within the `string_view`. // string `s` within the `string_view`.
size_type find_last_of(const char* s, size_type pos = npos) const { size_type find_last_of(absl::Nonnull<const char*> s,
size_type pos = npos) const {
return find_last_of(string_view(s), pos); return find_last_of(string_view(s), pos);
} }
...@@ -554,14 +564,15 @@ class string_view { ...@@ -554,14 +564,15 @@ class string_view {
// Overload of `string_view::find_first_not_of()` for finding a substring of a // Overload of `string_view::find_first_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`. // different C-style string `s` within the `string_view`.
size_type find_first_not_of(const char* s, size_type pos, size_type find_first_not_of(absl::Nonnull<const char*> s, size_type pos,
size_type count) const { size_type count) const {
return find_first_not_of(string_view(s, count), pos); return find_first_not_of(string_view(s, count), pos);
} }
// Overload of `string_view::find_first_not_of()` for finding a different // Overload of `string_view::find_first_not_of()` for finding a different
// C-style string `s` within the `string_view`. // C-style string `s` within the `string_view`.
size_type find_first_not_of(const char* s, size_type pos = 0) const { size_type find_first_not_of(absl::Nonnull<const char*> s,
size_type pos = 0) const {
return find_first_not_of(string_view(s), pos); return find_first_not_of(string_view(s), pos);
} }
...@@ -579,14 +590,15 @@ class string_view { ...@@ -579,14 +590,15 @@ class string_view {
// Overload of `string_view::find_last_not_of()` for finding a substring of a // Overload of `string_view::find_last_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`. // different C-style string `s` within the `string_view`.
size_type find_last_not_of(const char* s, size_type pos, size_type find_last_not_of(absl::Nonnull<const char*> s, size_type pos,
size_type count) const { size_type count) const {
return find_last_not_of(string_view(s, count), pos); return find_last_not_of(string_view(s, count), pos);
} }
// Overload of `string_view::find_last_not_of()` for finding a different // Overload of `string_view::find_last_not_of()` for finding a different
// C-style string `s` within the `string_view`. // C-style string `s` within the `string_view`.
size_type find_last_not_of(const char* s, size_type pos = npos) const { size_type find_last_not_of(absl::Nonnull<const char*> s,
size_type pos = npos) const {
return find_last_not_of(string_view(s), pos); return find_last_not_of(string_view(s), pos);
} }
...@@ -646,7 +658,8 @@ class string_view { ...@@ -646,7 +658,8 @@ class string_view {
// The constructor from std::string delegates to this constructor. // The constructor from std::string delegates to this constructor.
// See the comment on that constructor for the rationale. // See the comment on that constructor for the rationale.
struct SkipCheckLengthTag {}; struct SkipCheckLengthTag {};
string_view(const char* data, size_type len, SkipCheckLengthTag) noexcept string_view(absl::Nullable<const char*> data, size_type len,
SkipCheckLengthTag) noexcept
: ptr_(data), length_(len) {} : ptr_(data), length_(len) {}
static constexpr size_type kMaxSize = static constexpr size_type kMaxSize =
...@@ -656,7 +669,7 @@ class string_view { ...@@ -656,7 +669,7 @@ class string_view {
return ABSL_HARDENING_ASSERT(len <= kMaxSize), len; return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
} }
static constexpr size_type StrlenInternal(const char* str) { static constexpr size_type StrlenInternal(absl::Nonnull<const char*> str) {
#if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__) #if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__)
// MSVC 2017+ can evaluate this at compile-time. // MSVC 2017+ can evaluate this at compile-time.
const char* begin = str; const char* begin = str;
...@@ -685,7 +698,7 @@ class string_view { ...@@ -685,7 +698,7 @@ class string_view {
: (compare_result < 0 ? -1 : 1); : (compare_result < 0 ? -1 : 1);
} }
const char* ptr_; absl::Nullable<const char*> ptr_;
size_type length_; size_type length_;
}; };
...@@ -746,7 +759,7 @@ inline string_view ClippedSubstr(string_view s, size_t pos, ...@@ -746,7 +759,7 @@ inline string_view ClippedSubstr(string_view s, size_t pos,
// Creates an `absl::string_view` from a pointer `p` even if it's null-valued. // Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
// This function should be used where an `absl::string_view` can be created from // This function should be used where an `absl::string_view` can be created from
// a possibly-null pointer. // a possibly-null pointer.
constexpr string_view NullSafeStringView(const char* p) { constexpr string_view NullSafeStringView(absl::Nullable<const char*> p) {
return p ? string_view(p) : string_view(); return p ? string_view(p) : string_view();
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <string> #include <string>
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/strings/ascii.h" #include "absl/strings/ascii.h"
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -43,7 +44,8 @@ ABSL_NAMESPACE_BEGIN ...@@ -43,7 +44,8 @@ ABSL_NAMESPACE_BEGIN
// absl::string_view input("abc"); // absl::string_view input("abc");
// EXPECT_TRUE(absl::ConsumePrefix(&input, "a")); // EXPECT_TRUE(absl::ConsumePrefix(&input, "a"));
// EXPECT_EQ(input, "bc"); // EXPECT_EQ(input, "bc");
inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) { inline bool ConsumePrefix(absl::Nonnull<absl::string_view*> str,
absl::string_view expected) {
if (!absl::StartsWith(*str, expected)) return false; if (!absl::StartsWith(*str, expected)) return false;
str->remove_prefix(expected.size()); str->remove_prefix(expected.size());
return true; return true;
...@@ -59,7 +61,8 @@ inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) { ...@@ -59,7 +61,8 @@ inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) {
// absl::string_view input("abcdef"); // absl::string_view input("abcdef");
// EXPECT_TRUE(absl::ConsumeSuffix(&input, "def")); // EXPECT_TRUE(absl::ConsumeSuffix(&input, "def"));
// EXPECT_EQ(input, "abc"); // EXPECT_EQ(input, "abc");
inline bool ConsumeSuffix(absl::string_view* str, absl::string_view expected) { inline bool ConsumeSuffix(absl::Nonnull<absl::string_view*> str,
absl::string_view expected) {
if (!absl::EndsWith(*str, expected)) return false; if (!absl::EndsWith(*str, expected)) return false;
str->remove_suffix(expected.size()); str->remove_suffix(expected.size());
return true; return true;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/nullability.h"
#include "absl/strings/ascii.h" #include "absl/strings/ascii.h"
#include "absl/strings/escaping.h" #include "absl/strings/escaping.h"
#include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/resize_uninitialized.h"
...@@ -33,9 +34,9 @@ namespace absl { ...@@ -33,9 +34,9 @@ namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace substitute_internal { namespace substitute_internal {
void SubstituteAndAppendArray(std::string* output, absl::string_view format, void SubstituteAndAppendArray(
const absl::string_view* args_array, absl::Nonnull<std::string*> output, absl::string_view format,
size_t num_args) { absl::Nullable<const absl::string_view*> args_array, size_t num_args) {
// Determine total size needed. // Determine total size needed.
size_t size = 0; size_t size = 0;
for (size_t i = 0; i < format.size(); i++) { for (size_t i = 0; i < format.size(); i++) {
...@@ -104,7 +105,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format, ...@@ -104,7 +105,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
assert(target == output->data() + output->size()); assert(target == output->data() + output->size());
} }
Arg::Arg(const void* value) { Arg::Arg(absl::Nullable<const void*> value) {
static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2, static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
"fix sizeof(scratch_)"); "fix sizeof(scratch_)");
if (value == nullptr) { if (value == nullptr) {
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
#include <vector> #include <vector>
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h" #include "absl/base/port.h"
#include "absl/strings/ascii.h" #include "absl/strings/ascii.h"
#include "absl/strings/escaping.h" #include "absl/strings/escaping.h"
...@@ -105,7 +106,7 @@ class Arg { ...@@ -105,7 +106,7 @@ class Arg {
// Overloads for string-y things // Overloads for string-y things
// //
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`. // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(const char* value) // NOLINT(google-explicit-constructor) Arg(absl::Nullable<const char*> value) // NOLINT(google-explicit-constructor)
: piece_(absl::NullSafeStringView(value)) {} : piece_(absl::NullSafeStringView(value)) {}
template <typename Allocator> template <typename Allocator>
Arg( // NOLINT Arg( // NOLINT
...@@ -197,7 +198,8 @@ class Arg { ...@@ -197,7 +198,8 @@ class Arg {
// `void*` values, with the exception of `char*`, are printed as // `void*` values, with the exception of `char*`, are printed as
// "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed. // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
Arg(const void* value); // NOLINT(google-explicit-constructor) Arg( // NOLINT(google-explicit-constructor)
absl::Nullable<const void*> value);
// Normal enums are already handled by the integer formatters. // Normal enums are already handled by the integer formatters.
// This overload matches only scoped enums. // This overload matches only scoped enums.
...@@ -220,12 +222,12 @@ class Arg { ...@@ -220,12 +222,12 @@ class Arg {
// Internal helper function. Don't call this from outside this implementation. // Internal helper function. Don't call this from outside this implementation.
// This interface may change without notice. // This interface may change without notice.
void SubstituteAndAppendArray(std::string* output, absl::string_view format, void SubstituteAndAppendArray(
const absl::string_view* args_array, absl::Nonnull<std::string*> output, absl::string_view format,
size_t num_args); absl::Nullable<const absl::string_view*> args_array, size_t num_args);
#if defined(ABSL_BAD_CALL_IF) #if defined(ABSL_BAD_CALL_IF)
constexpr int CalculateOneBit(const char* format) { constexpr int CalculateOneBit(absl::Nonnull<const char*> format) {
// Returns: // Returns:
// * 2^N for '$N' when N is in [0-9] // * 2^N for '$N' when N is in [0-9]
// * 0 for correct '$' escaping: '$$'. // * 0 for correct '$' escaping: '$$'.
...@@ -234,11 +236,11 @@ constexpr int CalculateOneBit(const char* format) { ...@@ -234,11 +236,11 @@ constexpr int CalculateOneBit(const char* format) {
: (1 << (*format - '0')); : (1 << (*format - '0'));
} }
constexpr const char* SkipNumber(const char* format) { constexpr const char* SkipNumber(absl::Nonnull<const char*> format) {
return !*format ? format : (format + 1); return !*format ? format : (format + 1);
} }
constexpr int PlaceholderBitmask(const char* format) { constexpr int PlaceholderBitmask(absl::Nonnull<const char*> format) {
return !*format return !*format
? 0 ? 0
: *format != '$' ? PlaceholderBitmask(format + 1) : *format != '$' ? PlaceholderBitmask(format + 1)
...@@ -271,18 +273,21 @@ constexpr int PlaceholderBitmask(const char* format) { ...@@ -271,18 +273,21 @@ constexpr int PlaceholderBitmask(const char* format) {
// absl::SubstituteAndAppend(boilerplate, format, args...); // absl::SubstituteAndAppend(boilerplate, format, args...);
// } // }
// //
inline void SubstituteAndAppend(std::string* output, absl::string_view format) { inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format) {
substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0); substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format,
const substitute_internal::Arg& a0) { const substitute_internal::Arg& a0) {
const absl::string_view args[] = {a0.piece()}; const absl::string_view args[] = {a0.piece()};
substitute_internal::SubstituteAndAppendArray(output, format, args, substitute_internal::SubstituteAndAppendArray(output, format, args,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1) { const substitute_internal::Arg& a1) {
const absl::string_view args[] = {a0.piece(), a1.piece()}; const absl::string_view args[] = {a0.piece(), a1.piece()};
...@@ -290,7 +295,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ...@@ -290,7 +295,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2) { const substitute_internal::Arg& a2) {
...@@ -299,7 +305,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ...@@ -299,7 +305,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
...@@ -310,7 +317,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ...@@ -310,7 +317,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
...@@ -322,27 +330,23 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ...@@ -322,27 +330,23 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(
const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::string_view format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) {
const substitute_internal::Arg& a4,
const substitute_internal::Arg& a5) {
const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
a3.piece(), a4.piece(), a5.piece()}; a3.piece(), a4.piece(), a5.piece()};
substitute_internal::SubstituteAndAppendArray(output, format, args, substitute_internal::SubstituteAndAppendArray(output, format, args,
ABSL_ARRAYSIZE(args)); ABSL_ARRAYSIZE(args));
} }
inline void SubstituteAndAppend(std::string* output, absl::string_view format, inline void SubstituteAndAppend(
const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::string_view format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a6) {
const substitute_internal::Arg& a5,
const substitute_internal::Arg& a6) {
const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(),
a3.piece(), a4.piece(), a5.piece(), a3.piece(), a4.piece(), a5.piece(),
a6.piece()}; a6.piece()};
...@@ -351,7 +355,7 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ...@@ -351,7 +355,7 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format,
} }
inline void SubstituteAndAppend( inline void SubstituteAndAppend(
std::string* output, absl::string_view format, absl::Nonnull<std::string*> output, absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
...@@ -364,7 +368,7 @@ inline void SubstituteAndAppend( ...@@ -364,7 +368,7 @@ inline void SubstituteAndAppend(
} }
inline void SubstituteAndAppend( inline void SubstituteAndAppend(
std::string* output, absl::string_view format, absl::Nonnull<std::string*> output, absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
...@@ -378,7 +382,7 @@ inline void SubstituteAndAppend( ...@@ -378,7 +382,7 @@ inline void SubstituteAndAppend(
} }
inline void SubstituteAndAppend( inline void SubstituteAndAppend(
std::string* output, absl::string_view format, absl::Nonnull<std::string*> output, absl::string_view format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
...@@ -394,14 +398,16 @@ inline void SubstituteAndAppend( ...@@ -394,14 +398,16 @@ inline void SubstituteAndAppend(
#if defined(ABSL_BAD_CALL_IF) #if defined(ABSL_BAD_CALL_IF)
// This body of functions catches cases where the number of placeholders // This body of functions catches cases where the number of placeholders
// doesn't match the number of data arguments. // doesn't match the number of data arguments.
void SubstituteAndAppend(std::string* output, const char* format) void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 0, substitute_internal::PlaceholderBitmask(format) != 0,
"There were no substitution arguments " "There were no substitution arguments "
"but this format string either has a $[0-9] in it or contains " "but this format string either has a $[0-9] in it or contains "
"an unescaped $ character (use $$ instead)"); "an unescaped $ character (use $$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0) const substitute_internal::Arg& a0)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1, ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
"There was 1 substitution argument given, but " "There was 1 substitution argument given, but "
...@@ -409,7 +415,8 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -409,7 +415,8 @@ void SubstituteAndAppend(std::string* output, const char* format,
"one of $1-$9, or contains an unescaped $ character (use " "one of $1-$9, or contains an unescaped $ character (use "
"$$ instead)"); "$$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1) const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
...@@ -418,7 +425,8 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -418,7 +425,8 @@ void SubstituteAndAppend(std::string* output, const char* format,
"missing its $0/$1, contains one of $2-$9, or contains an " "missing its $0/$1, contains one of $2-$9, or contains an "
"unescaped $ character (use $$ instead)"); "unescaped $ character (use $$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2) const substitute_internal::Arg& a2)
...@@ -428,7 +436,8 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -428,7 +436,8 @@ void SubstituteAndAppend(std::string* output, const char* format,
"this format string is missing its $0/$1/$2, contains one of " "this format string is missing its $0/$1/$2, contains one of "
"$3-$9, or contains an unescaped $ character (use $$ instead)"); "$3-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
...@@ -439,7 +448,8 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -439,7 +448,8 @@ void SubstituteAndAppend(std::string* output, const char* format,
"this format string is missing its $0-$3, contains one of " "this format string is missing its $0-$3, contains one of "
"$4-$9, or contains an unescaped $ character (use $$ instead)"); "$4-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(absl::Nonnull<std::string*> output,
absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
...@@ -451,13 +461,11 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -451,13 +461,11 @@ void SubstituteAndAppend(std::string* output, const char* format,
"this format string is missing its $0-$4, contains one of " "this format string is missing its $0-$4, contains one of "
"$5-$9, or contains an unescaped $ character (use $$ instead)"); "$5-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend(std::string* output, const char* format, void SubstituteAndAppend(
const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5)
const substitute_internal::Arg& a4,
const substitute_internal::Arg& a5)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 63, substitute_internal::PlaceholderBitmask(format) != 63,
"There were 6 substitution arguments given, but " "There were 6 substitution arguments given, but "
...@@ -465,10 +473,11 @@ void SubstituteAndAppend(std::string* output, const char* format, ...@@ -465,10 +473,11 @@ void SubstituteAndAppend(std::string* output, const char* format,
"$6-$9, or contains an unescaped $ character (use $$ instead)"); "$6-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend( void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 127, substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but " "There were 7 substitution arguments given, but "
...@@ -476,11 +485,11 @@ void SubstituteAndAppend( ...@@ -476,11 +485,11 @@ void SubstituteAndAppend(
"$7-$9, or contains an unescaped $ character (use $$ instead)"); "$7-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend( void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
const substitute_internal::Arg& a7) const substitute_internal::Arg& a6, const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 255, substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but " "There were 8 substitution arguments given, but "
...@@ -488,11 +497,12 @@ void SubstituteAndAppend( ...@@ -488,11 +497,12 @@ void SubstituteAndAppend(
"$8-$9, or contains an unescaped $ character (use $$ instead)"); "$8-$9, or contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend( void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
const substitute_internal::Arg& a8)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 511, substitute_internal::PlaceholderBitmask(format) != 511,
"There were 9 substitution arguments given, but " "There were 9 substitution arguments given, but "
...@@ -500,12 +510,12 @@ void SubstituteAndAppend( ...@@ -500,12 +510,12 @@ void SubstituteAndAppend(
"contains an unescaped $ character (use $$ instead)"); "contains an unescaped $ character (use $$ instead)");
void SubstituteAndAppend( void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0, absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
const substitute_internal::Arg& a7, const substitute_internal::Arg& a8, const substitute_internal::Arg& a6, const substitute_internal::Arg& a7,
const substitute_internal::Arg& a9) const substitute_internal::Arg& a8, const substitute_internal::Arg& a9)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 1023, substitute_internal::PlaceholderBitmask(format) != 1023,
"There were 10 substitution arguments given, but this " "There were 10 substitution arguments given, but this "
...@@ -633,20 +643,22 @@ ABSL_MUST_USE_RESULT inline std::string Substitute( ...@@ -633,20 +643,22 @@ ABSL_MUST_USE_RESULT inline std::string Substitute(
#if defined(ABSL_BAD_CALL_IF) #if defined(ABSL_BAD_CALL_IF)
// This body of functions catches cases where the number of placeholders // This body of functions catches cases where the number of placeholders
// doesn't match the number of data arguments. // doesn't match the number of data arguments.
std::string Substitute(const char* format) std::string Substitute(absl::Nonnull<const char*> format)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0, ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
"There were no substitution arguments " "There were no substitution arguments "
"but this format string either has a $[0-9] in it or " "but this format string either has a $[0-9] in it or "
"contains an unescaped $ character (use $$ instead)"); "contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0) std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 1, substitute_internal::PlaceholderBitmask(format) != 1,
"There was 1 substitution argument given, but " "There was 1 substitution argument given, but "
"this format string is missing its $0, contains one of $1-$9, " "this format string is missing its $0, contains one of $1-$9, "
"or contains an unescaped $ character (use $$ instead)"); "or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1) const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 3, substitute_internal::PlaceholderBitmask(format) != 3,
...@@ -654,7 +666,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -654,7 +666,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"this format string is missing its $0/$1, contains one of " "this format string is missing its $0/$1, contains one of "
"$2-$9, or contains an unescaped $ character (use $$ instead)"); "$2-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2) const substitute_internal::Arg& a2)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
...@@ -663,7 +676,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -663,7 +676,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"this format string is missing its $0/$1/$2, contains one of " "this format string is missing its $0/$1/$2, contains one of "
"$3-$9, or contains an unescaped $ character (use $$ instead)"); "$3-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3) const substitute_internal::Arg& a3)
...@@ -673,7 +687,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -673,7 +687,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"this format string is missing its $0-$3, contains one of " "this format string is missing its $0-$3, contains one of "
"$4-$9, or contains an unescaped $ character (use $$ instead)"); "$4-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a3,
...@@ -684,7 +699,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -684,7 +699,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"this format string is missing its $0-$4, contains one of " "this format string is missing its $0-$4, contains one of "
"$5-$9, or contains an unescaped $ character (use $$ instead)"); "$5-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(absl::Nonnull<const char*> format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a1,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a3,
...@@ -696,27 +712,23 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -696,27 +712,23 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"this format string is missing its $0-$5, contains one of " "this format string is missing its $0-$5, contains one of "
"$6-$9, or contains an unescaped $ character (use $$ instead)"); "$6-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(
const substitute_internal::Arg& a1, absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
const substitute_internal::Arg& a5,
const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 127, substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but " "There were 7 substitution arguments given, but "
"this format string is missing its $0-$6, contains one of " "this format string is missing its $0-$6, contains one of "
"$7-$9, or contains an unescaped $ character (use $$ instead)"); "$7-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute(const char* format, const substitute_internal::Arg& a0, std::string Substitute(
const substitute_internal::Arg& a1, absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a2, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a7)
const substitute_internal::Arg& a6,
const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF( ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 255, substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but " "There were 8 substitution arguments given, but "
...@@ -724,7 +736,7 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, ...@@ -724,7 +736,7 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
"$8-$9, or contains an unescaped $ character (use $$ instead)"); "$8-$9, or contains an unescaped $ character (use $$ instead)");
std::string Substitute( std::string Substitute(
const char* format, const substitute_internal::Arg& a0, absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
...@@ -736,7 +748,7 @@ std::string Substitute( ...@@ -736,7 +748,7 @@ std::string Substitute(
"contains an unescaped $ character (use $$ instead)"); "contains an unescaped $ character (use $$ instead)");
std::string Substitute( std::string Substitute(
const char* format, const substitute_internal::Arg& a0, absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
......
...@@ -118,6 +118,7 @@ cc_library( ...@@ -118,6 +118,7 @@ cc_library(
deps = [ deps = [
"//absl/algorithm", "//absl/algorithm",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/base:throw_delegate", "//absl/base:throw_delegate",
"//absl/meta:type_traits", "//absl/meta:type_traits",
], ],
...@@ -154,6 +155,7 @@ cc_library( ...@@ -154,6 +155,7 @@ cc_library(
"//absl/base:base_internal", "//absl/base:base_internal",
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:nullability",
"//absl/memory", "//absl/memory",
"//absl/meta:type_traits", "//absl/meta:type_traits",
"//absl/utility", "//absl/utility",
......
...@@ -115,6 +115,7 @@ absl_cc_library( ...@@ -115,6 +115,7 @@ absl_cc_library(
DEPS DEPS
absl::algorithm absl::algorithm
absl::core_headers absl::core_headers
absl::nullability
absl::throw_delegate absl::throw_delegate
absl::type_traits absl::type_traits
PUBLIC PUBLIC
...@@ -175,6 +176,7 @@ absl_cc_library( ...@@ -175,6 +176,7 @@ absl_cc_library(
absl::config absl::config
absl::core_headers absl::core_headers
absl::memory absl::memory
absl::nullability
absl::type_traits absl::type_traits
absl::utility absl::utility
PUBLIC PUBLIC
......
...@@ -61,6 +61,7 @@ ABSL_NAMESPACE_END ...@@ -61,6 +61,7 @@ ABSL_NAMESPACE_END
#include <utility> #include <utility>
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/internal/inline_variable.h" #include "absl/base/internal/inline_variable.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/types/bad_optional_access.h" #include "absl/types/bad_optional_access.h"
...@@ -415,11 +416,11 @@ class optional : private optional_internal::optional_data<T>, ...@@ -415,11 +416,11 @@ class optional : private optional_internal::optional_data<T>,
// `optional` is empty, behavior is undefined. // `optional` is empty, behavior is undefined.
// //
// If you need myOpt->foo in constexpr, use (*myOpt).foo instead. // If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND { absl::Nonnull<const T*> operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_); ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_); return std::addressof(this->data_);
} }
T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND { absl::Nonnull<T*> operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(this->engaged_); ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_); return std::addressof(this->data_);
} }
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include "absl/base/attributes.h" #include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h" #include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h" #include "absl/base/optimization.h"
#include "absl/base/port.h" // TODO(strel): remove this include #include "absl/base/port.h" // TODO(strel): remove this include
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
...@@ -172,8 +173,8 @@ class Span { ...@@ -172,8 +173,8 @@ class Span {
public: public:
using element_type = T; using element_type = T;
using value_type = absl::remove_cv_t<T>; using value_type = absl::remove_cv_t<T>;
using pointer = T*; using pointer = absl::Nullable<T*>;
using const_pointer = const T*; using const_pointer = absl::Nullable<const T*>;
using reference = T&; using reference = T&;
using const_reference = const T&; using const_reference = const T&;
using iterator = pointer; using iterator = pointer;
...@@ -679,12 +680,12 @@ bool operator>=(Span<T> a, const U& b) { ...@@ -679,12 +680,12 @@ bool operator>=(Span<T> a, const U& b) {
// } // }
// //
template <int&... ExplicitArgumentBarrier, typename T> template <int&... ExplicitArgumentBarrier, typename T>
constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept { constexpr Span<T> MakeSpan(absl::Nullable<T*> ptr, size_t size) noexcept {
return Span<T>(ptr, size); return Span<T>(ptr, size);
} }
template <int&... ExplicitArgumentBarrier, typename T> template <int&... ExplicitArgumentBarrier, typename T>
Span<T> MakeSpan(T* begin, T* end) noexcept { Span<T> MakeSpan(absl::Nullable<T*> begin, absl::Nullable<T*> end) noexcept {
return ABSL_HARDENING_ASSERT(begin <= end), return ABSL_HARDENING_ASSERT(begin <= end),
Span<T>(begin, static_cast<size_t>(end - begin)); Span<T>(begin, static_cast<size_t>(end - begin));
} }
...@@ -725,12 +726,14 @@ constexpr Span<T> MakeSpan(T (&array)[N]) noexcept { ...@@ -725,12 +726,14 @@ constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
// ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 })); // ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
// //
template <int&... ExplicitArgumentBarrier, typename T> template <int&... ExplicitArgumentBarrier, typename T>
constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept { constexpr Span<const T> MakeConstSpan(absl::Nullable<T*> ptr,
size_t size) noexcept {
return Span<const T>(ptr, size); return Span<const T>(ptr, size);
} }
template <int&... ExplicitArgumentBarrier, typename T> template <int&... ExplicitArgumentBarrier, typename T>
Span<const T> MakeConstSpan(T* begin, T* end) noexcept { Span<const T> MakeConstSpan(absl::Nullable<T*> begin,
absl::Nullable<T*> end) noexcept {
return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin); return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment