From 1290019d9a94eb04c84335b69a9ccf72208f27ed Mon Sep 17 00:00:00 2001 From: Justin King Date: Tue, 27 Oct 2026 18:01:52 -0700 Subject: [PATCH] Migrate `_cel_String` to use C++ PiperOrigin-RevId: 1008513477 --- cel-c/BUILD | 2 +- cel-c/internal/BUILD | 5 +- cel-c/internal/container.h | 192 ++++++++------- cel-c/internal/container_test.cc | 10 +- cel-c/internal/runtime/interpreter.cc | 39 +--- cel-c/internal/runtime/program.cc | 8 - cel-c/internal/runtime/runtime.cc | 14 +- cel-c/internal/string.h | 324 +++++++++++++++++++------- cel-c/internal/string_test.cc | 94 ++++---- cel-c/internal/trivial_relocation.hpp | 21 +- cel-c/status.cc | 78 ++----- 11 files changed, 463 insertions(+), 324 deletions(-) diff --git a/cel-c/BUILD b/cel-c/BUILD index 233e4ed..843657a 100644 --- a/cel-c/BUILD +++ b/cel-c/BUILD @@ -727,7 +727,6 @@ cc_library( ], visibility = ["//visibility:public"], deps = [ - ":alloc", ":assert", ":config", ":error_space", @@ -735,6 +734,7 @@ cc_library( ":string_view", "//cel-c/internal:array", "//cel-c/internal:string", + "//cel-c/internal:trivial_relocation", ], ) diff --git a/cel-c/internal/BUILD b/cel-c/internal/BUILD index 494dd9e..a8b589b 100644 --- a/cel-c/internal/BUILD +++ b/cel-c/internal/BUILD @@ -496,8 +496,8 @@ cc_library( deps = [ ":config", ":string", - "//cel-c:alloc", "//cel-c:assert", + "//cel-c:config", "//cel-c:string_view", ], ) @@ -1190,7 +1190,9 @@ cc_library( deps = [ ":config", ":generic_string", + ":trivial_relocation", "//cel-c:alloc", + "//cel-c:assert", "//cel-c:cstring_view", "//cel-c:string_view", ], @@ -1203,6 +1205,7 @@ cc_test( ":config", ":generic_string", ":string", + ":trivial_relocation", "//cel-c:alloc", "//cel-c:cstring_view", "//cel-c:string_view", diff --git a/cel-c/internal/container.h b/cel-c/internal/container.h index 2028cda..a1efebe 100644 --- a/cel-c/internal/container.h +++ b/cel-c/internal/container.h @@ -15,124 +15,148 @@ #ifndef THIRD_PARTY_CEL_C_INTERNAL_CONTAINER_H_ #define THIRD_PARTY_CEL_C_INTERNAL_CONTAINER_H_ -#include +#include +#include -#include "cel-c/alloc.h" #include "cel-c/assert.h" +#include "cel-c/config.h" #include "cel-c/internal/config.h" #include "cel-c/internal/string.h" #include "cel-c/string_view.h" -CEL_BEGIN_DECLS +struct _cel_ContainerIterator { + cel_StringView name = cel_StringView{.data = "", .size = 0}; + size_t size = 0; -typedef struct { - _cel_String name; - size_t count; -} _cel_Container; + [[nodiscard]] + bool HasNext() const { + return size > 0; + } -typedef struct { - cel_StringView name; - size_t size; -} _cel_ContainerIterator; + [[nodiscard]] + cel_StringView Next() { + CEL_ASSERT_GT(size, 0); + + cel_StringView name = this->name; + --size; + const char* pos = + cel_StringView_FindLast(this->name, cel_StringView_FromString(".")); + if (pos == cel_nullptr) { + CEL_ASSERT_EQ(size, 0); + pos = cel_StringView_Data(this->name); + } + cel_StringView_RemoveSuffix(&this->name, (cel_StringView_Data(this->name) + + cel_StringView_Size(this->name)) - + pos); + return name; + } +}; -static CEL_INLINE void _cel_Container_Construct( - _cel_Container* cel_nonnull container) { - CEL_ASSERT_NOT_NULL(container); +class _cel_Container { + public: + _cel_Container() = default; + _cel_Container(const _cel_Container&) = delete; + _cel_Container& operator=(const _cel_Container&) = delete; - _cel_String_Construct(&container->name); - container->count = 0; -} + CEL_INLINE _cel_Container(_cel_Container&& other) noexcept + : name_(std::move(other.name_)), count_(std::exchange(other.count_, 0)) {} -static CEL_INLINE void _cel_Container_Destruct( - _cel_Container* cel_nonnull container, cel_Allocator* cel_nonnull alloc) { - CEL_ASSERT_NOT_NULL(container); - CEL_ASSERT_NOT_NULL(alloc); + CEL_INLINE _cel_Container& operator=(_cel_Container&& other) noexcept { + if (CEL_LIKELY(this != &other)) { + name_ = std::move(other.name_); + count_ = std::exchange(other.count_, 0); + } + return *this; + } - _cel_String_Destruct(&container->name, alloc); -} + [[nodiscard]] + CEL_INLINE bool empty() const { + return count() == 0; + } + + [[nodiscard]] + CEL_INLINE size_t count() const { + return count_; + } + + [[nodiscard]] + CEL_INLINE cel_StringView name() const CEL_ATTRIBUTE_LIFETIME_BOUND { + return _cel_String_ToStringView(&name_); + } + + [[nodiscard]] + CEL_INLINE bool Update(cel_StringView name) { + _cel_String_Clear(&name_); + count_ = 0; + _cel_String_Reserve(&name_, cel_StringView_Size(name)); + + cel_StringViewTokenizer tokenizer = + cel_StringView_Tokenize(name, cel_StringView_FromString(".")); + cel_StringView token; + while (cel_StringViewTokenizer_Next(&tokenizer, &token)) { + if (cel_StringView_Empty(token)) { + continue; + } + ++count_; + if (!_cel_String_Empty(&name_)) { + if (!_cel_String_PushBack(&name_, '.')) { + return false; + } + } + if (!_cel_String_Append(&name_, token)) { + return false; + } + } + return true; + } + + [[nodiscard]] + CEL_INLINE _cel_ContainerIterator Iterate() const { + _cel_ContainerIterator iter; + iter.name = _cel_String_ToStringView(&name_); + iter.size = count_; + return iter; + } + + private: + _cel_String name_; + size_t count_ = 0; +}; CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_Container_Empty( +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_Container_Empty( const _cel_Container* cel_nonnull container) { - return container->count == 0; + return container->empty(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE size_t +CEL_DEPRECATE_AND_INLINE CEL_INLINE size_t _cel_Container_Count(const _cel_Container* cel_nonnull container) { - return container->count; + return container->count(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_Container_Update( - _cel_Container* cel_nonnull container, cel_StringView name, - cel_Allocator* cel_nonnull alloc) { - CEL_ASSERT_NOT_NULL(container); - CEL_ASSERT_NOT_NULL(alloc); - - _cel_String_Clear(&container->name); - container->count = 0; - _cel_String_Reserve(&container->name, alloc, cel_StringView_Size(name)); - - cel_StringViewTokenizer tokenizer = - cel_StringView_Tokenize(name, cel_StringView_FromString(".")); - cel_StringView token; - while (cel_StringViewTokenizer_Next(&tokenizer, &token)) { - if (cel_StringView_Empty(token)) { - continue; - } - ++container->count; - if (!_cel_String_Empty(&container->name)) { - if (!_cel_String_PushBack(&container->name, alloc, '.')) { - return false; - } - } - if (!_cel_String_Append(&container->name, alloc, token)) { - return false; - } - } - return true; +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_Container_Update( + _cel_Container* cel_nonnull container, cel_StringView name) { + return container->Update(name); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE _cel_ContainerIterator +CEL_DEPRECATE_AND_INLINE CEL_INLINE _cel_ContainerIterator _cel_Container_Iterate(const _cel_Container* cel_nonnull container) { - CEL_ASSERT_NOT_NULL(container); - - _cel_ContainerIterator iter; - iter.name = _cel_String_ToStringView(&container->name); - iter.size = container->count; - return iter; + return container->Iterate(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_ContainerIterator_HasNext( +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_ContainerIterator_HasNext( const _cel_ContainerIterator* cel_nonnull iter) { - CEL_ASSERT_NOT_NULL(iter); - - return iter->size > 0; + return iter->HasNext(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_StringView +CEL_DEPRECATE_AND_INLINE CEL_INLINE cel_StringView _cel_ContainerIterator_Next(_cel_ContainerIterator* cel_nonnull iter) { - CEL_ASSERT_NOT_NULL(iter); - CEL_ASSERT_GT(iter->size, 0); - - cel_StringView name = iter->name; - --iter->size; - const char* pos = - cel_StringView_FindLast(iter->name, cel_StringView_FromString(".")); - if (pos == cel_nullptr) { - CEL_ASSERT_EQ(iter->size, 0); - pos = cel_StringView_Data(iter->name); - } - cel_StringView_RemoveSuffix(&iter->name, (cel_StringView_Data(iter->name) + - cel_StringView_Size(iter->name)) - - pos); - return name; + return iter->Next(); } -CEL_END_DECLS - #endif // THIRD_PARTY_CEL_C_INTERNAL_CONTAINER_H_ diff --git a/cel-c/internal/container_test.cc b/cel-c/internal/container_test.cc index 843f956..ac3f59e 100644 --- a/cel-c/internal/container_test.cc +++ b/cel-c/internal/container_test.cc @@ -27,10 +27,6 @@ namespace { class ContainerTest : public ::testing::Test { public: - void SetUp() override { _cel_Container_Construct(&cont_); } - - void TearDown() override { _cel_Container_Destruct(cont(), alloc()); } - cel_Allocator* alloc() { return cel_DefaultAllocator; } _cel_Container* cont() { return &cont_; } @@ -45,8 +41,7 @@ TEST_F(ContainerTest, Empty) { _cel_ContainerIterator cont_it = _cel_Container_Iterate(cont()); EXPECT_FALSE(_cel_ContainerIterator_HasNext(&cont_it)); - ASSERT_TRUE( - _cel_Container_Update(cont(), cel_StringView_FromString(""), alloc())); + ASSERT_TRUE(_cel_Container_Update(cont(), cel_StringView_FromString(""))); EXPECT_TRUE(_cel_Container_Empty(cont())); EXPECT_EQ(_cel_Container_Count(cont()), 0); @@ -66,8 +61,7 @@ class ContainerTestWithParam TEST_P(ContainerTestWithParam, Match) { const auto& param = GetParam(); ASSERT_TRUE(_cel_Container_Update( - cont(), cel_StringView_FromAbsl(absl::string_view(param.subject)), - alloc())); + cont(), cel_StringView_FromAbsl(absl::string_view(param.subject)))); EXPECT_EQ(_cel_Container_Count(cont()), param.results.size()); _cel_ContainerIterator cont_it = _cel_Container_Iterate(cont()); for (const auto& part : param.results) { diff --git a/cel-c/internal/runtime/interpreter.cc b/cel-c/internal/runtime/interpreter.cc index 4234263..39512c5 100644 --- a/cel-c/internal/runtime/interpreter.cc +++ b/cel-c/internal/runtime/interpreter.cc @@ -66,17 +66,6 @@ struct _cel_InterpreterNspaceVar { _cel_String name; }; -static void _cel_InterpreterNspaceVar_Construct( - _cel_InterpreterNspaceVar* cel_nonnull nspace_var) { - _cel_String_Construct(&nspace_var->name); -} - -static void _cel_InterpreterNspaceVar_Destruct( - _cel_InterpreterNspaceVar* cel_nonnull nspace_var, - cel_Allocator* cel_nonnull alloc) { - _cel_String_Destruct(&nspace_var->name, alloc); -} - struct _cel_InterpreterBinaryCond { const cel_BinaryExpr* cel_nullability_unknown node = nullptr; uint32_t pc = 0; @@ -558,12 +547,11 @@ static uint32_t _cel_Interpreter_InternString( cel_OutOfMemoryStatus(interp->status); _cel_longjmp(interp->jmp); } - _cel_String_Construct(string_ptr); - if (!_cel_String_Assign(string_ptr, interp->alloc, string)) { + if (!_cel_String_Assign(string_ptr, string)) { cel_OutOfMemoryStatus(interp->status); _cel_longjmp(interp->jmp); } - if (!_cel_String_Stabilize(string_ptr, interp->alloc)) { + if (!_cel_String_Stabilize(string_ptr)) { cel_OutOfMemoryStatus(interp->status); _cel_longjmp(interp->jmp); } @@ -655,20 +643,17 @@ static void _cel_Interpreter_PlanIdent(_cel_Interpreter* cel_nonnull interp, _cel_longjmp(interp->jmp); } _cel_String candidate_name; - _cel_String_Construct(&candidate_name); _cel_ContainerIterator cont_iter = _cel_Container_Iterate(&interp->rt->container); for (size_t i = 0; i < candidate_names->size - 1; ++i) { _cel_String_Clear(&candidate_name); CEL_ASSERT(_cel_ContainerIterator_HasNext(&cont_iter)); cel_StringView prefix = _cel_ContainerIterator_Next(&cont_iter); - _cel_String_Reserve( - &candidate_name, interp->alloc, - cel_StringView_Size(prefix) + 1 + cel_StringView_Size(name)); - if (!_cel_String_Append(&candidate_name, interp->alloc, prefix) || - !_cel_String_PushBack(&candidate_name, interp->alloc, '.') || - !_cel_String_Append(&candidate_name, interp->alloc, name)) { - _cel_String_Destruct(&candidate_name, interp->alloc); + _cel_String_Reserve(&candidate_name, cel_StringView_Size(prefix) + 1 + + cel_StringView_Size(name)); + if (!_cel_String_Append(&candidate_name, prefix) || + !_cel_String_PushBack(&candidate_name, '.') || + !_cel_String_Append(&candidate_name, name)) { cel_Allocator_FreeSized(interp->alloc, candidate_names->data, candidate_names->size * sizeof(uint32_t)); _cel_Array_Pop(&interp->prog->candidate_names_table); @@ -966,15 +951,15 @@ static void _cel_Interpreter_BuildIdentName(_cel_Interpreter* interp, _cel_InterpreterNspaceVarSelect* const selects = _cel_Array_MutableData(&interp->nspace_var.selects); _cel_String_Clear(&interp->nspace_var.name); - if (!_cel_String_Append(&interp->nspace_var.name, interp->alloc, + if (!_cel_String_Append(&interp->nspace_var.name, cel_IdentExpr_Name(interp->nspace_var.ident.expr))) { cel_OutOfMemoryStatus(interp->status); _cel_longjmp(interp->jmp); } for (size_t i = 0; i < selects_num; ++i) { - if (!_cel_String_PushBack(&interp->nspace_var.name, interp->alloc, '.') || + if (!_cel_String_PushBack(&interp->nspace_var.name, '.') || !_cel_String_Append( - &interp->nspace_var.name, interp->alloc, + &interp->nspace_var.name, cel_SelectExpr_Field(selects[selects_count - i - 1].expr))) { cel_OutOfMemoryStatus(interp->status); _cel_longjmp(interp->jmp); @@ -1914,7 +1899,6 @@ _cel_Interpreter::_cel_Interpreter(const cel_Runtime* cel_nonnull rt, _cel_FlatHashMap_Construct(&candidate_names_indices, &_cel_Interpreter_StringViewHasher, &_cel_Interpreter_StringViewEqualer); - _cel_InterpreterNspaceVar_Construct(&nspace_var); _cel_Deque_Construct(&slots); _cel_FlatHashMap_Construct(&slot_map, &_cel_Interpreter_StringViewHasher, &_cel_Interpreter_StringViewEqualer); @@ -1924,7 +1908,6 @@ _cel_Interpreter::~_cel_Interpreter() { cel_AstTraverser_Delete(traverser); _cel_FlatHashMap_Destruct(&slot_map, alloc); _cel_Deque_Destruct(&slots, alloc); - _cel_InterpreterNspaceVar_Destruct(&nspace_var, alloc); _cel_FlatHashMap_Destruct(&candidate_names_indices, alloc); _cel_FlatHashMap_Destruct(&string_pool_indices, alloc); // interp->prog is only non-null when planning failed, call cel_Program_Delete @@ -2029,7 +2012,7 @@ extern "C" cel_Program* cel_nullable _cel_Interpreter_Compile( _cel_String* string_pool_ptr = _cel_Array_MutableData(&prog->strings_table); size_t string_pool_len = _cel_Array_Size(&prog->strings_table); for (; string_pool_len > 0; ++string_pool_ptr, --string_pool_len) { - _cel_String_Destabilize(string_pool_ptr, interp.alloc); + _cel_String_Destabilize(string_pool_ptr); } // Now that we have destablized strings, we can convert instructions from // their indirect references to direct. diff --git a/cel-c/internal/runtime/program.cc b/cel-c/internal/runtime/program.cc index 83732a1..84a9212 100644 --- a/cel-c/internal/runtime/program.cc +++ b/cel-c/internal/runtime/program.cc @@ -18,16 +18,13 @@ #include #include -#include #include "cel-c/alloc.h" #include "cel-c/assert.h" #include "cel-c/internal/arc.h" -#include "cel-c/internal/array.h" #include "cel-c/internal/config.h" #include "cel-c/internal/runtime/activation.h" #include "cel-c/internal/runtime/runtime.h" -#include "cel-c/internal/string.h" extern "C" cel_ProgramOptions* cel_nonnull cel_ProgramOptions_Default(cel_ProgramOptions* cel_nonnull opts) { @@ -79,11 +76,6 @@ extern "C" void _cel_Program_Delete(cel_Program* cel_nonnull prog) { const cel_Runtime* rt = prog->rt; cel_Allocator* alloc = rt->alloc; - _cel_String* string_ptr = _cel_Array_MutableData(&prog->strings_table); - size_t string_len = _cel_Array_Size(&prog->strings_table); - for (; string_len > 0; ++string_ptr, --string_len) { - _cel_String_Destruct(string_ptr, alloc); - } std::destroy_at(prog); cel_Allocator_FreeSized(alloc, prog, sizeof(*prog)); _cel_Runtime_Unref(rt); diff --git a/cel-c/internal/runtime/runtime.cc b/cel-c/internal/runtime/runtime.cc index 908937a..343165d 100644 --- a/cel-c/internal/runtime/runtime.cc +++ b/cel-c/internal/runtime/runtime.cc @@ -23,7 +23,6 @@ #include "cel-c/internal/config.h" #include "cel-c/internal/container.h" #include "cel-c/internal/runtime/interpreter.h" -#include "cel-c/internal/string.h" #include "cel-c/program.h" #include "cel-c/status.h" #include "cel-c/well_known_types.h" @@ -64,13 +63,13 @@ cel_Runtime* cel_nullable cel_Runtime_New( cel_Allocator_FreeSized(alloc, rt, sizeof(*rt)); return cel_nullptr; } - _cel_Container_Construct(&rt->container); - if (!_cel_Container_Update(&rt->container, rt->opts.container, rt->alloc)) { - _cel_Container_Destruct(&rt->container, rt->alloc); + ::new (static_cast(&rt->container)) _cel_Container(); + if (!_cel_Container_Update(&rt->container, rt->opts.container)) { + rt->container.~_cel_Container(); cel_Allocator_FreeSized(alloc, rt, sizeof(*rt)); return cel_nullptr; } - rt->opts.container = _cel_String_ToStringView(&rt->container.name); + rt->opts.container = rt->container.name(); _cel_AtomicRefCount_Initialize(&rt->rc); return rt; } @@ -128,6 +127,7 @@ void _cel_Runtime_Delete(cel_Runtime* cel_nonnull rt) { CEL_ASSERT(_cel_AtomicRefCount_Expired(&rt->rc)); CEL_ASSERT(rt->deleted); - _cel_Container_Destruct(&rt->container, rt->alloc); - cel_Allocator_FreeSized(rt->alloc, rt, sizeof(*rt)); + cel_Allocator* alloc = rt->alloc; + rt->~cel_Runtime(); + cel_Allocator_FreeSized(alloc, rt, sizeof(*rt)); } diff --git a/cel-c/internal/string.h b/cel-c/internal/string.h index 9e35360..2e0efd7 100644 --- a/cel-c/internal/string.h +++ b/cel-c/internal/string.h @@ -18,156 +18,320 @@ #ifndef THIRD_PARTY_CEL_C_INTERNAL_STRING_H_ #define THIRD_PARTY_CEL_C_INTERNAL_STRING_H_ -#include -#include // IWYU pragma: keep -#include +#include +#include +#include #include "cel-c/alloc.h" +#include "cel-c/assert.h" #include "cel-c/cstring_view.h" #include "cel-c/internal/config.h" #include "cel-c/internal/generic_string.h" +#include "cel-c/internal/trivial_relocation.hpp" #include "cel-c/string_view.h" -CEL_BEGIN_DECLS +class _cel_String : private _cel_GenericString { + public: + using value_type = char; + using reference = char&; + using const_reference = const char&; + using pointer = char*; + using const_pointer = const char*; + using size_type = size_t; + using difference_type = ptrdiff_t; + using iterator = pointer; + using const_iterator = const_pointer; -typedef struct { - _cel_GenericString g; -} _cel_String; + CEL_INLINE _cel_String() { _cel_GenericString_Construct(this); } -static CEL_INLINE void _cel_String_Construct(CEL_NONNULL(_cel_String*) str) { - _cel_GenericString_Construct(&str->g); -} + _cel_String(const _cel_String&) = delete; -static CEL_INLINE void _cel_String_Destruct(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc) { - _cel_GenericString_DestructAllocator(&str->g, alloc); -} + CEL_INLINE _cel_String(_cel_String&& other) noexcept + : _cel_GenericString(other) { + _cel_GenericString_Construct(&other); + } + + CEL_INLINE ~_cel_String() { Deallocate(); } + + _cel_String& operator=(const _cel_String&) = delete; + + CEL_INLINE _cel_String& operator=(_cel_String&& other) noexcept { + if (CEL_LIKELY(this != &other)) { + Deallocate(); + _cel_GenericString_Construct(&other); + } + return *this; + } + + [[nodiscard]] + CEL_INLINE bool empty() const { + return _cel_GenericString_Empty(this); + } + + [[nodiscard]] + CEL_INLINE size_type size() const { + return _cel_GenericString_Size(this); + } + + [[nodiscard]] + CEL_INLINE size_type int_size() const { + return _cel_GenericString_SizeInt(this); + } + + [[nodiscard]] + CEL_INLINE size_type capacity() const { + return _cel_GenericString_Capacity(this); + } + + [[nodiscard]] + CEL_INLINE pointer cel_nonnull data() CEL_ATTRIBUTE_LIFETIME_BOUND { + return _cel_GenericString_MutableData(this); + } + + [[nodiscard]] + CEL_INLINE const_pointer cel_nonnull + data() const CEL_ATTRIBUTE_LIFETIME_BOUND { + return _cel_GenericString_Data(this); + } + + [[nodiscard]] + CEL_INLINE reference front() CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_NOT(empty()); + return data()[0]; + } + + [[nodiscard]] + CEL_INLINE const_reference front() const CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_NOT(empty()); + return data()[0]; + } + + [[nodiscard]] + CEL_INLINE reference back() CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_NOT(empty()); + return data()[size() - 1]; + } + + [[nodiscard]] + CEL_INLINE const_reference back() const CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_NOT(empty()); + return data()[size() - 1]; + } + + CEL_INLINE void clear() { _cel_GenericString_Clear(this); } + + CEL_INLINE void reset() { + _cel_GenericString_ResetAllocator(this, cel_DefaultAllocator); + } + + CEL_INLINE bool shrink_to_fit() { + return _cel_GenericString_ShrinkToFitAllocator(this, cel_DefaultAllocator); + } + + [[nodiscard]] + CEL_INLINE reference operator[](size_type idx) CEL_ATTRIBUTE_LIFETIME_BOUND { + return at(idx); + } + + [[nodiscard]] + CEL_INLINE const_reference + operator[](size_type idx) const CEL_ATTRIBUTE_LIFETIME_BOUND { + return at(idx); + } + + [[nodiscard]] + CEL_INLINE reference at(size_type idx) CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_LT(idx, size()); + return data()[idx]; + } + + [[nodiscard]] + CEL_INLINE const_reference + at(size_type idx) const CEL_ATTRIBUTE_LIFETIME_BOUND { + CEL_ASSERT_LT(idx, size()); + return data()[idx]; + } + + [[nodiscard]] + CEL_INLINE bool Assign(cel_StringView val) { + return _cel_GenericString_AssignAllocator(this, cel_DefaultAllocator, val); + } + + CEL_ATTRIBUTE_VFORMAT(2) + [[nodiscard]] + CEL_INLINE ptrdiff_t VAppendF(const char* cel_nonnull fmt, va_list args) { + return _cel_GenericString_VAppendFAllocator(this, cel_DefaultAllocator, fmt, + args); + } + + [[nodiscard]] + CEL_INLINE ptrdiff_t AppendF(const char* cel_nonnull fmt, ...) { + va_list args; + va_start(args, fmt); + const ptrdiff_t ret = VAppendF(fmt, args); + va_end(args); + return ret; + } + + [[nodiscard]] + CEL_INLINE bool Append(cel_StringView val) { + return _cel_GenericString_AppendAllocator(this, cel_DefaultAllocator, val); + } + + [[nodiscard]] + CEL_INLINE bool PushBack(char val) { + return _cel_GenericString_PushBackAllocator(this, cel_DefaultAllocator, + val); + } + + CEL_INLINE bool Reserve(size_t new_capacity) { + return _cel_GenericString_ReserveAllocator(this, cel_DefaultAllocator, + new_capacity); + } + + [[nodiscard]] + CEL_INLINE bool Stabilize() { + return _cel_GenericString_StabilizeAllocator(this, cel_DefaultAllocator); + } + + CEL_INLINE void Destabilize() { + _cel_GenericString_DestabilizeAllocator(this, cel_DefaultAllocator); + } + + [[nodiscard]] + CEL_INLINE cel_StringView ToStringView() const CEL_ATTRIBUTE_LIFETIME_BOUND { + return _cel_GenericString_ToStringView(this); + } + + [[nodiscard]] + CEL_INLINE cel_CStringView + ToCStringView() const CEL_ATTRIBUTE_LIFETIME_BOUND { + return _cel_GenericString_ToCStringView(this); + } + + private: + CEL_INLINE void Deallocate() { + _cel_GenericString_DestructAllocator(this, cel_DefaultAllocator); + } +}; + +template <> +struct cel_IsTriviallyRelocatable<_cel_String> : std::true_type {}; CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE size_t _cel_String_Size(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_Size(&str->g); +CEL_DEPRECATE_AND_INLINE CEL_INLINE size_t +_cel_String_Size(CEL_NONNULL(const _cel_String*) str) { + return str->size(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE int _cel_String_SizeInt(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_SizeInt(&str->g); +CEL_DEPRECATE_AND_INLINE CEL_INLINE int _cel_String_SizeInt( + CEL_NONNULL(const _cel_String*) str) { + return str->int_size(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_Empty(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_Empty(&str->g); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_Empty( + CEL_NONNULL(const _cel_String*) str) { + return str->empty(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE size_t _cel_String_Capacity(CEL_NONNULL(const _cel_String*) - str) { - return _cel_GenericString_Capacity(&str->g); +CEL_DEPRECATE_AND_INLINE CEL_INLINE size_t +_cel_String_Capacity(CEL_NONNULL(const _cel_String*) str) { + return str->capacity(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE CEL_NONNULL(const char*) +CEL_DEPRECATE_AND_INLINE CEL_INLINE CEL_NONNULL(const char*) _cel_String_Data(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_Data(&str->g); + return str->data(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE CEL_NONNULL(char*) +CEL_DEPRECATE_AND_INLINE CEL_INLINE CEL_NONNULL(char*) _cel_String_MutableData(CEL_NONNULL(_cel_String*) str) { - return _cel_GenericString_MutableData(&str->g); + return str->data(); } -static CEL_INLINE void _cel_String_Clear(CEL_NONNULL(_cel_String*) str) { - _cel_GenericString_Clear(&str->g); +CEL_DEPRECATE_AND_INLINE CEL_INLINE void _cel_String_Clear( + CEL_NONNULL(_cel_String*) str) { + str->clear(); } -static CEL_INLINE void _cel_String_Reset(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc) { - _cel_GenericString_ResetAllocator(&str->g, alloc); +CEL_DEPRECATE_AND_INLINE CEL_INLINE void _cel_String_Reset( + CEL_NONNULL(_cel_String*) str) { + str->reset(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_ShrinkToFit(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) - alloc) { - return _cel_GenericString_ShrinkToFitAllocator(&str->g, alloc); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_ShrinkToFit( + CEL_NONNULL(_cel_String*) str) { + return str->shrink_to_fit(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_Assign(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc, - cel_StringView val) { - return _cel_GenericString_AssignAllocator(&str->g, alloc, val); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_Assign( + CEL_NONNULL(_cel_String*) str, cel_StringView val) { + return str->Assign(val); } CEL_ATTRIBUTE_NODISCARD -CEL_ATTRIBUTE_VFORMAT(3) -static CEL_INLINE ptrdiff_t _cel_String_VAppendF(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) - alloc, - CEL_NONNULL(const char*) fmt, - va_list args) { - return _cel_GenericString_VAppendFAllocator(&str->g, alloc, fmt, args); +CEL_ATTRIBUTE_VFORMAT(2) +CEL_DEPRECATE_AND_INLINE CEL_INLINE ptrdiff_t _cel_String_VAppendF( + CEL_NONNULL(_cel_String*) str, CEL_NONNULL(const char*) fmt, va_list args) { + return str->VAppendF(fmt, args); } CEL_ATTRIBUTE_NODISCARD -CEL_ATTRIBUTE_FORMAT(3, 4) -static CEL_INLINE ptrdiff_t _cel_String_AppendF(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) - alloc, - CEL_NONNULL(const char*) fmt, - ...) { +CEL_ATTRIBUTE_FORMAT(2, 3) +[[deprecated]] CEL_INLINE ptrdiff_t _cel_String_AppendF( + CEL_NONNULL(_cel_String*) str, CEL_NONNULL(const char*) fmt, ...) { va_list args; va_start(args, fmt); - const ptrdiff_t ret = _cel_String_VAppendF(str, alloc, fmt, args); + const ptrdiff_t ret = _cel_String_VAppendF(str, fmt, args); va_end(args); return ret; } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_Append(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc, - cel_StringView val) { - return _cel_GenericString_AppendAllocator(&str->g, alloc, val); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_Append( + CEL_NONNULL(_cel_String*) str, cel_StringView val) { + return str->Append(val); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_PushBack(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc, - char val) { - return _cel_GenericString_PushBackAllocator(&str->g, alloc, val); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_PushBack( + CEL_NONNULL(_cel_String*) str, char val) { + return str->PushBack(val); } -static CEL_INLINE bool _cel_String_Reserve(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) alloc, - size_t capacity) { - return _cel_GenericString_ReserveAllocator(&str->g, alloc, capacity); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_Reserve( + CEL_NONNULL(_cel_String*) str, size_t capacity) { + return str->Reserve(capacity); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE bool _cel_String_Stabilize(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) - alloc) { - return _cel_GenericString_StabilizeAllocator(&str->g, alloc); +CEL_DEPRECATE_AND_INLINE CEL_INLINE bool _cel_String_Stabilize( + CEL_NONNULL(_cel_String*) str) { + return str->Stabilize(); } -static CEL_INLINE void _cel_String_Destabilize(CEL_NONNULL(_cel_String*) str, - CEL_NONNULL(cel_Allocator*) - alloc) { - _cel_GenericString_DestabilizeAllocator(&str->g, alloc); +CEL_DEPRECATE_AND_INLINE CEL_INLINE void _cel_String_Destabilize( + CEL_NONNULL(_cel_String*) str) { + str->Destabilize(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_StringView +CEL_DEPRECATE_AND_INLINE CEL_INLINE cel_StringView _cel_String_ToStringView(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_ToStringView(&str->g); + return str->ToStringView(); } CEL_ATTRIBUTE_NODISCARD -static CEL_INLINE cel_CStringView +CEL_DEPRECATE_AND_INLINE CEL_INLINE cel_CStringView _cel_String_ToCStringView(CEL_NONNULL(const _cel_String*) str) { - return _cel_GenericString_ToCStringView(&str->g); + return str->ToCStringView(); } -CEL_END_DECLS - #endif // THIRD_PARTY_CEL_C_INTERNAL_STRING_H_ diff --git a/cel-c/internal/string_test.cc b/cel-c/internal/string_test.cc index 94449a0..3c1673c 100644 --- a/cel-c/internal/string_test.cc +++ b/cel-c/internal/string_test.cc @@ -22,6 +22,7 @@ #include "cel-c/cstring_view.h" #include "cel-c/internal/config.h" #include "cel-c/internal/generic_string.h" +#include "cel-c/internal/trivial_relocation.hpp" #include "cel-c/string_view.h" namespace { @@ -30,11 +31,6 @@ using ::testing::NotNull; using ::testing::Test; class StringTest : public Test { - public: - void SetUp() override { _cel_String_Construct(&str_); } - - void TearDown() override { _cel_String_Destruct(&str_, alloc()); } - protected: CEL_NONNULL(cel_Allocator*) alloc() { return cel_DefaultAllocator; } @@ -206,7 +202,7 @@ TEST_F(StringTest, Assign) { "erat. Quisque congue turpis id erat egestas pellentesque. Nulla " "fermentum ac massa nec sollicitudin. Fusce sed ultrices tellus."); - ASSERT_TRUE(_cel_String_Assign(str(), alloc(), cel_StringView_From(small))); + ASSERT_TRUE(_cel_String_Assign(str(), cel_StringView_From(small))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_CStringView_Size(small)); @@ -218,7 +214,7 @@ TEST_F(StringTest, Assign) { cel_StringView_From(small))); EXPECT_TRUE(cel_CStringView_Equals(_cel_String_ToCStringView(str()), small)); - ASSERT_TRUE(_cel_String_Assign(str(), alloc(), cel_StringView_From(large))); + ASSERT_TRUE(_cel_String_Assign(str(), cel_StringView_From(large))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_CStringView_Size(large)); @@ -230,7 +226,7 @@ TEST_F(StringTest, Assign) { cel_StringView_From(large))); EXPECT_TRUE(cel_CStringView_Equals(_cel_String_ToCStringView(str()), large)); - ASSERT_TRUE(_cel_String_Assign(str(), alloc(), cel_StringView_From(small))); + ASSERT_TRUE(_cel_String_Assign(str(), cel_StringView_From(small))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_CStringView_Size(small)); @@ -242,7 +238,7 @@ TEST_F(StringTest, Assign) { cel_StringView_From(small))); EXPECT_TRUE(cel_CStringView_Equals(_cel_String_ToCStringView(str()), small)); - ASSERT_TRUE(_cel_String_Assign(str(), alloc(), cel_StringView_From(huge))); + ASSERT_TRUE(_cel_String_Assign(str(), cel_StringView_From(huge))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_CStringView_Size(huge)); @@ -396,7 +392,7 @@ TEST_F(StringTest, AppendF) { "erat. Quisque congue turpis id erat egestas pellentesque. Nulla " "fermentum ac massa nec sollicitudin. Fusce sed ultrices tellus."); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), CEL_CSTRINGVIEW_FMT, + ASSERT_EQ(_cel_String_AppendF(str(), CEL_CSTRINGVIEW_FMT, CEL_CSTRINGVIEW_ARGS(small)), cel_CStringView_Size(small)); @@ -410,7 +406,7 @@ TEST_F(StringTest, AppendF) { cel_StringView_From(small))); EXPECT_TRUE(cel_CStringView_Equals(_cel_String_ToCStringView(str()), small)); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), "%s", ""), 0); + ASSERT_EQ(_cel_String_AppendF(str(), "%s", ""), 0); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_CStringView_Size(small)); @@ -422,7 +418,7 @@ TEST_F(StringTest, AppendF) { cel_StringView_From(small))); EXPECT_TRUE(cel_CStringView_Equals(_cel_String_ToCStringView(str()), small)); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), CEL_CSTRINGVIEW_FMT, + ASSERT_EQ(_cel_String_AppendF(str(), CEL_CSTRINGVIEW_FMT, CEL_CSTRINGVIEW_ARGS(large)), cel_CStringView_Size(large)); @@ -442,7 +438,7 @@ TEST_F(StringTest, AppendF) { EXPECT_TRUE( cel_CStringView_StartsWith(_cel_String_ToCStringView(str()), small)); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), "%s", ""), 0); + ASSERT_EQ(_cel_String_AppendF(str(), "%s", ""), 0); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -460,7 +456,7 @@ TEST_F(StringTest, AppendF) { EXPECT_TRUE( cel_CStringView_StartsWith(_cel_String_ToCStringView(str()), small)); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), CEL_CSTRINGVIEW_FMT, + ASSERT_EQ(_cel_String_AppendF(str(), CEL_CSTRINGVIEW_FMT, CEL_CSTRINGVIEW_ARGS(small)), cel_CStringView_Size(small)); @@ -480,7 +476,7 @@ TEST_F(StringTest, AppendF) { EXPECT_TRUE( cel_CStringView_StartsWith(_cel_String_ToCStringView(str()), small)); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -509,7 +505,7 @@ TEST_F(StringTest, AppendF) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_CStringView_Empty(_cel_String_ToCStringView(str()))); - ASSERT_EQ(_cel_String_AppendF(str(), alloc(), CEL_CSTRINGVIEW_FMT, + ASSERT_EQ(_cel_String_AppendF(str(), CEL_CSTRINGVIEW_FMT, CEL_CSTRINGVIEW_ARGS(huge)), cel_CStringView_Size(huge)); @@ -525,7 +521,7 @@ TEST_F(StringTest, AppendF) { _cel_String_Clear(str()); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_TRUE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), 0); @@ -536,7 +532,7 @@ TEST_F(StringTest, AppendF) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_CStringView_Empty(_cel_String_ToCStringView(str()))); - _cel_String_Reset(str(), alloc()); + _cel_String_Reset(str()); } TEST_F(StringTest, Append) { @@ -680,7 +676,7 @@ TEST_F(StringTest, Append) { "erat. Quisque congue turpis id erat egestas pellentesque. Nulla " "fermentum ac massa nec sollicitudin. Fusce sed ultrices tellus."); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), small)); + ASSERT_TRUE(_cel_String_Append(str(), small)); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_StringView_Size(small)); @@ -691,7 +687,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), cel_StringView_From(""))); + ASSERT_TRUE(_cel_String_Append(str(), cel_StringView_From(""))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_StringView_Size(small)); @@ -702,7 +698,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), large)); + ASSERT_TRUE(_cel_String_Append(str(), large)); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -719,7 +715,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE( cel_StringView_StartsWith(_cel_String_ToStringView(str()), small)); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), cel_StringView_From(""))); + ASSERT_TRUE(_cel_String_Append(str(), cel_StringView_From(""))); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -736,7 +732,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE( cel_StringView_StartsWith(_cel_String_ToStringView(str()), small)); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), small)); + ASSERT_TRUE(_cel_String_Append(str(), small)); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -753,7 +749,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE( cel_StringView_StartsWith(_cel_String_ToStringView(str()), small)); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -781,7 +777,7 @@ TEST_F(StringTest, Append) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), huge)); + ASSERT_TRUE(_cel_String_Append(str(), huge)); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_StringView_Size(huge)); @@ -794,7 +790,7 @@ TEST_F(StringTest, Append) { _cel_String_Clear(str()); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_TRUE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), 0); @@ -805,15 +801,14 @@ TEST_F(StringTest, Append) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); - _cel_String_Reset(str(), alloc()); + _cel_String_Reset(str()); } -void DoAppendViaPushBack(_cel_String* str, cel_Allocator* alloc, - cel_StringView to_append) { +void DoAppendViaPushBack(_cel_String* str, cel_StringView to_append) { const char* data = cel_StringView_Data(to_append); size_t size = cel_StringView_Size(to_append); for (size_t i = 0; i < size; ++i) { - ASSERT_TRUE(_cel_String_PushBack(str, alloc, data[i])); + ASSERT_TRUE(_cel_String_PushBack(str, data[i])); } } @@ -958,7 +953,7 @@ TEST_F(StringTest, PushBack) { "erat. Quisque congue turpis id erat egestas pellentesque. Nulla " "fermentum ac massa nec sollicitudin. Fusce sed ultrices tellus."); - DoAppendViaPushBack(str(), alloc(), small); + DoAppendViaPushBack(str(), small); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_StringView_Size(small)); @@ -978,7 +973,7 @@ TEST_F(StringTest, PushBack) { EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); EXPECT_TRUE(cel_StringView_Equals(_cel_String_ToStringView(str()), small)); - DoAppendViaPushBack(str(), alloc(), large); + DoAppendViaPushBack(str(), large); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -1010,7 +1005,7 @@ TEST_F(StringTest, PushBack) { EXPECT_TRUE( cel_StringView_StartsWith(_cel_String_ToStringView(str()), small)); - DoAppendViaPushBack(str(), alloc(), small); + DoAppendViaPushBack(str(), small); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -1027,7 +1022,7 @@ TEST_F(StringTest, PushBack) { EXPECT_TRUE( cel_StringView_StartsWith(_cel_String_ToStringView(str()), small)); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), @@ -1055,7 +1050,7 @@ TEST_F(StringTest, PushBack) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); - DoAppendViaPushBack(str(), alloc(), huge); + DoAppendViaPushBack(str(), huge); EXPECT_FALSE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), cel_StringView_Size(huge)); @@ -1068,7 +1063,7 @@ TEST_F(StringTest, PushBack) { _cel_String_Clear(str()); - EXPECT_TRUE(_cel_String_ShrinkToFit(str(), alloc())); + EXPECT_TRUE(_cel_String_ShrinkToFit(str())); EXPECT_TRUE(_cel_String_Empty(str())); EXPECT_EQ(_cel_String_Size(str()), 0); @@ -1079,33 +1074,34 @@ TEST_F(StringTest, PushBack) { EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); EXPECT_TRUE(cel_StringView_Empty(_cel_String_ToStringView(str()))); - _cel_String_Reset(str(), alloc()); + _cel_String_Reset(str()); } TEST_F(StringTest, Reserve) { EXPECT_EQ(_cel_String_Capacity(str()), _cel_GenericStringSmall_kCapacity); - ASSERT_TRUE( - _cel_String_Reserve(str(), alloc(), _cel_GenericStringSmall_kCapacity)); + ASSERT_TRUE(_cel_String_Reserve(str(), _cel_GenericStringSmall_kCapacity)); EXPECT_EQ(_cel_String_Capacity(str()), _cel_GenericStringSmall_kCapacity); - ASSERT_TRUE(_cel_String_Reserve(str(), alloc(), - _cel_GenericStringSmall_kCapacity + 1)); + ASSERT_TRUE( + _cel_String_Reserve(str(), _cel_GenericStringSmall_kCapacity + 1)); EXPECT_GE(_cel_String_Capacity(str()), _cel_GenericStringSmall_kCapacity + 1); - ASSERT_TRUE(_cel_String_Reserve(str(), alloc(), - _cel_GenericStringSmall_kCapacity + 2)); + ASSERT_TRUE( + _cel_String_Reserve(str(), _cel_GenericStringSmall_kCapacity + 2)); EXPECT_GE(_cel_String_Capacity(str()), _cel_GenericStringSmall_kCapacity + 2); } TEST_F(StringTest, Stability) { cel_StringView small = cel_StringView_FromString("Hello World!"); - ASSERT_TRUE(_cel_String_Append(str(), alloc(), small)); - _cel_String other_str = *str(); + ASSERT_TRUE(_cel_String_Append(str(), small)); + _cel_String other_str; + cel_TriviallyCopy(&other_str, str()); EXPECT_NE(_cel_String_Data(&other_str), _cel_String_Data(str())); - ASSERT_TRUE(_cel_String_Stabilize(str(), alloc())); - other_str = *str(); + ASSERT_TRUE(_cel_String_Stabilize(str())); + cel_TriviallyCopy(&other_str, str()); EXPECT_EQ(_cel_String_Data(&other_str), _cel_String_Data(str())); - _cel_String_Destabilize(str(), alloc()); - other_str = *str(); + _cel_String_Destabilize(str()); + cel_TriviallyCopy(&other_str, str()); EXPECT_NE(_cel_String_Data(&other_str), _cel_String_Data(str())); + cel_TriviallyClear(&other_str); } } // namespace diff --git a/cel-c/internal/trivial_relocation.hpp b/cel-c/internal/trivial_relocation.hpp index df0b46a..02e1ed1 100644 --- a/cel-c/internal/trivial_relocation.hpp +++ b/cel-c/internal/trivial_relocation.hpp @@ -51,7 +51,7 @@ CEL_INLINE void cel_TriviallyCopy(void* cel_nullability_unknown dst, template CEL_INLINE void cel_TriviallyCopy(T* cel_nullability_unknown dst, const T* cel_nullability_unknown src, - size_t count) { + size_t count = 1) { static_assert(!std::is_void_v, "T must not be void"); static_assert(cel_kIsTriviallyRelocatable, "T must be trivially relocatable"); @@ -71,7 +71,7 @@ CEL_INLINE void cel_TriviallyMove(void* cel_nullability_unknown dst, template CEL_INLINE void cel_TriviallyMove(T* cel_nullability_unknown dst, const T* cel_nullability_unknown src, - size_t count) { + size_t count = 1) { static_assert(!std::is_void_v, "T must not be void"); static_assert(cel_kIsTriviallyRelocatable, "T must be trivially relocatable"); @@ -79,4 +79,21 @@ CEL_INLINE void cel_TriviallyMove(T* cel_nullability_unknown dst, reinterpret_cast(src), count * sizeof(T)); } +// Performs trivial default initialization via memset. +CEL_INLINE void cel_TriviallyClear(void* cel_nullability_unknown dst, + size_t count) { + memset(dst, 0, count); +} + +// Performs trivial default initialization via memset, silencing undefined +// behavior warnings if cel_kIsTriviallyRelocatable is true. +template +CEL_INLINE void cel_TriviallyClear(T* cel_nullability_unknown dst, + size_t count = 1) { + static_assert(!std::is_void_v, "T must not be void"); + static_assert(cel_kIsTriviallyRelocatable, + "T must be trivially relocatable"); + (cel_TriviallyClear)(reinterpret_cast(dst), count * sizeof(T)); +} + #endif // THIRD_PARTY_CEL_C_INTERNAL_TRIVIAL_RELOCATION_HPP_ diff --git a/cel-c/status.cc b/cel-c/status.cc index fd1d70b..4836770 100644 --- a/cel-c/status.cc +++ b/cel-c/status.cc @@ -22,14 +22,14 @@ #include #include -#include +#include -#include "cel-c/alloc.h" #include "cel-c/assert.h" #include "cel-c/config.h" #include "cel-c/error_space.h" #include "cel-c/internal/array.h" #include "cel-c/internal/string.h" +#include "cel-c/internal/trivial_relocation.hpp" #include "cel-c/status_code.h" #include "cel-c/string_view.h" @@ -45,17 +45,23 @@ typedef struct { _cel_String value; } _cel_StatusRepPayload; -typedef struct alignas(cel_Status) { +template <> +struct cel_IsTriviallyRelocatable<_cel_StatusRepPayload> : std::true_type {}; + +struct alignas(cel_Status) _cel_StatusRep { + explicit _cel_StatusRep(const cel_ErrorSpace* cel_nonnull space) + : space(space) {} + // code **must** be first. - unsigned int code; + unsigned int code = 0; - int raw_code; + int raw_code = 0; CEL_NONNULL(const cel_ErrorSpace*) space; _cel_String message; _cel_Array(_cel_StatusRepPayload) payloads; - CEL_NULLABLE(const char*) file; - int line; -} _cel_StatusRep; + CEL_NULLABLE(const char*) file = nullptr; + int line = 0; +}; CEL_STATIC_ASSERT(sizeof(_cel_StatusRep) <= sizeof(cel_Status)); CEL_STATIC_ASSERT(alignof(_cel_StatusRep) == alignof(cel_Status)); @@ -73,30 +79,13 @@ static CEL_INLINE CEL_NONNULL(_cel_StatusRep*) return (_cel_StatusRep*)status; } -static void _cel_StatusRepPayload_Construct(CEL_NONNULL(_cel_StatusRepPayload*) - payload) { - _cel_String_Construct(&payload->type_url); - _cel_String_Construct(&payload->value); -} - -static void _cel_StatusRepPayload_Destruct(CEL_NONNULL(_cel_StatusRepPayload*) - payload) { - _cel_String_Destruct(&payload->value, cel_DefaultAllocator); - _cel_String_Destruct(&payload->type_url, cel_DefaultAllocator); -} - static void _cel_StatusRep_ResetMessage(CEL_NONNULL(_cel_StatusRep*) status_rep) { - _cel_String_Reset(&status_rep->message, cel_DefaultAllocator); + _cel_String_Reset(&status_rep->message); } static void _cel_StatusRep_ResetPayloads(CEL_NONNULL(_cel_StatusRep*) status_rep) { - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } _cel_Array_Reset(&status_rep->payloads); } @@ -109,36 +98,19 @@ static unsigned int _cel_StatusRep_EncodeCanonical(cel_StatusCode code, extern "C" void cel_Status_Construct(CEL_NONNULL(cel_Status*) status) { CEL_ASSERT_NOT_NULL(status); - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - memset(status, '\0', sizeof(*status)); - status_rep->space = cel_CanonicalErrorSpace; - _cel_String_Construct(&status_rep->message); - ::new (static_cast(&status_rep->payloads)) - cel_Array<_cel_StatusRepPayload>(); + ::new (static_cast(status)) _cel_StatusRep(cel_CanonicalErrorSpace); } extern "C" void cel_Status_Destruct(CEL_NONNULL(cel_Status*) status) { CEL_ASSERT_NOT_NULL(status); - CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } - std::destroy_at(&status_rep->payloads); - _cel_String_Destruct(&status_rep->message, cel_DefaultAllocator); + std::destroy_at(_cel_Status_Rep(status)); } extern "C" void cel_Status_Clear(CEL_NONNULL(cel_Status*) status) { CEL_ASSERT_NOT_NULL(status); CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); - const size_t payloads_size = _cel_Array_Size(&status_rep->payloads); - for (size_t i = 0; i < payloads_size; ++i) { - _cel_StatusRepPayload_Destruct( - _cel_Array_MutableAt(&status_rep->payloads, i)); - } _cel_Array_Clear(&status_rep->payloads); _cel_String_Clear(&status_rep->message); status_rep->code = @@ -214,8 +186,7 @@ extern "C" bool cel_Status_SetMessage(CEL_NONNULL(cel_Status*) status, return true; } - if (!_cel_String_Assign(&_cel_Status_Rep(status)->message, - cel_DefaultAllocator, message)) { + if (!_cel_String_Assign(&_cel_Status_Rep(status)->message, message)) { cel_OutOfMemoryStatus(status, file, line); return false; } @@ -251,8 +222,7 @@ extern "C" bool cel_Status_VFormatMessage(CEL_NONNULL(cel_Status*) status, CEL_NONNULL(_cel_StatusRep*) status_rep = _cel_Status_Rep(status); _cel_String_Clear(&status_rep->message); - if (!_cel_String_VAppendF(&status_rep->message, cel_DefaultAllocator, fmt, - args)) { + if (!_cel_String_VAppendF(&status_rep->message, fmt, args)) { cel_OutOfMemoryStatus(status, file, line); return false; } @@ -306,8 +276,7 @@ extern "C" bool cel_Status_SetPayload(CEL_NONNULL(cel_Status*) status, payload_at = _cel_Array_MutableAt(&status_rep->payloads, i); if (cel_StringView_Equals(_cel_String_ToStringView(&payload_at->type_url), type_url)) { - if (!_cel_String_Assign(&payload_at->value, cel_DefaultAllocator, - value)) { + if (!_cel_String_Assign(&payload_at->value, value)) { cel_OutOfMemoryStatus(status, file, line); return false; } @@ -322,14 +291,12 @@ extern "C" bool cel_Status_SetPayload(CEL_NONNULL(cel_Status*) status, return false; } - _cel_StatusRepPayload_Construct(payload); - - if (!_cel_String_Assign(&payload->type_url, cel_DefaultAllocator, type_url)) { + if (!_cel_String_Assign(&payload->type_url, type_url)) { cel_OutOfMemoryStatus(status, file, line); return false; } - if (!_cel_String_Assign(&payload->value, cel_DefaultAllocator, value)) { + if (!_cel_String_Assign(&payload->value, value)) { cel_OutOfMemoryStatus(status, file, line); return false; } @@ -352,7 +319,6 @@ extern "C" bool cel_Status_DeletePayload(CEL_NONNULL(cel_Status*) status, payload_at = _cel_Array_MutableAt(&status_rep->payloads, i); if (cel_StringView_Equals(_cel_String_ToStringView(&payload_at->type_url), type_url)) { - _cel_StatusRepPayload_Destruct(payload_at); _cel_Array_Erase(&status_rep->payloads, i); return true; }