Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
kcenon::logger::small_string< SSO_SIZE > Class Template Reference

Small String Optimization (SSO) implementation. More...

#include <small_string.h>

Collaboration diagram for kcenon::logger::small_string< SSO_SIZE >:
Collaboration graph

Classes

union  data_union
 
struct  memory_stats
 Get memory usage statistics. More...
 

Public Member Functions

 small_string () noexcept
 Default constructor.
 
 small_string (const char *str)
 Construct from C-string.
 
 small_string (const std::string &str)
 Construct from std::string.
 
 small_string (std::string_view str)
 Construct from string_view.
 
 small_string (const small_string &other)
 Copy constructor.
 
 small_string (small_string &&other) noexcept
 Move constructor.
 
 ~small_string ()
 Destructor.
 
small_stringoperator= (const small_string &other)
 Copy assignment.
 
small_stringoperator= (small_string &&other) noexcept
 Move assignment.
 
void assign (const char *str, size_t len)
 Assign from string data.
 
const char * c_str () const noexcept
 Get C-string pointer.
 
const char * data () const noexcept
 Get data pointer.
 
size_t size () const noexcept
 Get size.
 
size_t length () const noexcept
 Get length (same as size)
 
bool empty () const noexcept
 Check if empty.
 
bool is_small () const noexcept
 Check if using small string optimization.
 
size_t capacity () const noexcept
 Get capacity.
 
void clear () noexcept
 Clear the string.
 
void reserve (size_t new_capacity)
 Reserve capacity.
 
void append (const char *str, size_t len)
 Append a string.
 
void append (const std::string &str)
 Append a string.
 
small_stringoperator+= (const char *str)
 Append operator.
 
small_stringoperator+= (const std::string &str)
 Append operator.
 
std::string to_string () const
 Convert to std::string.
 
 operator std::string_view () const noexcept
 Implicit conversion to string_view.
 
bool operator== (const small_string &other) const noexcept
 Equality comparison.
 
bool operator!= (const small_string &other) const noexcept
 Inequality comparison.
 
bool operator== (const std::string &str) const noexcept
 Comparison with std::string.
 
memory_stats get_memory_stats () const noexcept
 

Static Public Attributes

static constexpr size_t SSO_CAPACITY = SSO_SIZE - 1
 

Static Private Member Functions

static size_t calculate_capacity (size_t required)
 Calculate capacity for heap allocation.
 

Private Attributes

union kcenon::logger::small_string::data_union data_
 
size_t size_
 
bool is_small_
 

Detailed Description

template<size_t SSO_SIZE = 256>
class kcenon::logger::small_string< SSO_SIZE >

Small String Optimization (SSO) implementation.

This class implements a string with Small String Optimization. Strings smaller than SSO_CAPACITY are stored inline, avoiding heap allocation. Larger strings use heap allocation like std::string.

Template Parameters
SSO_SIZESize threshold for SSO (default 256 bytes)

Definition at line 32 of file small_string.h.

Constructor & Destructor Documentation

◆ small_string() [1/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( )
inlinenoexcept

Default constructor.

Definition at line 39 of file small_string.h.

39 : size_(0), is_small_(true) {
40 data_.small[0] = '\0';
41 }
union kcenon::logger::small_string::data_union data_

References kcenon::logger::small_string< SSO_SIZE >::data_, and kcenon::logger::small_string< SSO_SIZE >::data_union::small.

◆ small_string() [2/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( const char * str)
inline

Construct from C-string.

Definition at line 46 of file small_string.h.

46 : small_string() {
47 if (str) {
48 assign(str, std::strlen(str));
49 }
50 }
void assign(const char *str, size_t len)
Assign from string data.
small_string() noexcept
Default constructor.

References kcenon::logger::small_string< SSO_SIZE >::assign().

Here is the call graph for this function:

◆ small_string() [3/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( const std::string & str)
inline

Construct from std::string.

Definition at line 55 of file small_string.h.

55 : small_string() {
56 assign(str.data(), str.size());
57 }

References kcenon::logger::small_string< SSO_SIZE >::assign().

Here is the call graph for this function:

◆ small_string() [4/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( std::string_view str)
inline

Construct from string_view.

Definition at line 62 of file small_string.h.

62 : small_string() {
63 assign(str.data(), str.size());
64 }

References kcenon::logger::small_string< SSO_SIZE >::assign().

Here is the call graph for this function:

◆ small_string() [5/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( const small_string< SSO_SIZE > & other)
inline

Copy constructor.

Definition at line 69 of file small_string.h.

69 : small_string() {
70 if (other.is_small_) {
71 std::memcpy(data_.small, other.data_.small, other.size_ + 1);
72 size_ = other.size_;
73 is_small_ = true;
74 } else {
75 assign(other.data(), other.size());
76 }
77 }

References kcenon::logger::small_string< SSO_SIZE >::is_small_.

◆ small_string() [6/6]

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::small_string ( small_string< SSO_SIZE > && other)
inlinenoexcept

Move constructor.

Definition at line 82 of file small_string.h.

83 : size_(other.size_), is_small_(other.is_small_) {
84 if (is_small_) {
85 std::memcpy(data_.small, other.data_.small, size_ + 1);
86 } else {
87 data_.heap.ptr = other.data_.heap.ptr;
88 data_.heap.capacity = other.data_.heap.capacity;
89 other.data_.heap.ptr = nullptr;
90 other.size_ = 0;
91 other.is_small_ = true;
92 }
93 }
struct kcenon::logger::small_string::data_union::@0 heap

References kcenon::logger::small_string< SSO_SIZE >::data_union::capacity, kcenon::logger::small_string< SSO_SIZE >::data_, kcenon::logger::small_string< SSO_SIZE >::data_union::heap, kcenon::logger::small_string< SSO_SIZE >::is_small_, kcenon::logger::small_string< SSO_SIZE >::data_union::ptr, kcenon::logger::small_string< SSO_SIZE >::size_, and kcenon::logger::small_string< SSO_SIZE >::data_union::small.

◆ ~small_string()

Member Function Documentation

◆ append() [1/2]

template<size_t SSO_SIZE = 256>
void kcenon::logger::small_string< SSO_SIZE >::append ( const char * str,
size_t len )
inline

Append a string.

Definition at line 267 of file small_string.h.

267 {
268 size_t new_size = size_ + len;
269
270 if (new_size <= SSO_CAPACITY && is_small_) {
271 // Can still use SSO
272 std::memcpy(data_.small + size_, str, len);
273 data_.small[new_size] = '\0';
274 size_ = new_size;
275 } else {
276 // Need heap allocation
277 if (is_small_ || data_.heap.capacity < new_size + 1) {
278 // Need to reallocate
279 size_t new_capacity = calculate_capacity(new_size);
280 char* new_ptr = new char[new_capacity];
281
282 // Copy existing data
283 std::memcpy(new_ptr, data(), size_);
284 // Append new data
285 std::memcpy(new_ptr + size_, str, len);
286 new_ptr[new_size] = '\0';
287
288 // Clean up old allocation
289 if (!is_small_ && data_.heap.ptr) {
290 delete[] data_.heap.ptr;
291 }
292
293 data_.heap.ptr = new_ptr;
294 data_.heap.capacity = new_capacity;
295 is_small_ = false;
296 } else {
297 // Existing heap buffer is large enough
298 std::memcpy(data_.heap.ptr + size_, str, len);
299 data_.heap.ptr[new_size] = '\0';
300 }
301 size_ = new_size;
302 }
303 }
const char * data() const noexcept
Get data pointer.
static size_t calculate_capacity(size_t required)
Calculate capacity for heap allocation.
static constexpr size_t SSO_CAPACITY

References kcenon::logger::small_string< SSO_SIZE >::calculate_capacity(), kcenon::logger::small_string< SSO_SIZE >::data_union::capacity, kcenon::logger::small_string< SSO_SIZE >::data(), kcenon::logger::small_string< SSO_SIZE >::data_, kcenon::logger::small_string< SSO_SIZE >::data_union::heap, kcenon::logger::small_string< SSO_SIZE >::is_small_, kcenon::logger::small_string< SSO_SIZE >::data_union::ptr, kcenon::logger::small_string< SSO_SIZE >::size_, kcenon::logger::small_string< SSO_SIZE >::data_union::small, and kcenon::logger::small_string< SSO_SIZE >::SSO_CAPACITY.

Referenced by kcenon::logger::small_string< SSO_SIZE >::append(), kcenon::logger::small_string< SSO_SIZE >::operator+=(), and kcenon::logger::small_string< SSO_SIZE >::operator+=().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ append() [2/2]

template<size_t SSO_SIZE = 256>
void kcenon::logger::small_string< SSO_SIZE >::append ( const std::string & str)
inline

Append a string.

Definition at line 308 of file small_string.h.

308 {
309 append(str.data(), str.size());
310 }
void append(const char *str, size_t len)
Append a string.

References kcenon::logger::small_string< SSO_SIZE >::append().

Here is the call graph for this function:

◆ assign()

template<size_t SSO_SIZE = 256>
void kcenon::logger::small_string< SSO_SIZE >::assign ( const char * str,
size_t len )
inline

Assign from string data.

Definition at line 143 of file small_string.h.

143 {
144 if (len <= SSO_CAPACITY) {
145 // Use small string optimization
146 if (!is_small_ && data_.heap.ptr) {
147 delete[] data_.heap.ptr;
148 }
149 std::memcpy(data_.small, str, len);
150 data_.small[len] = '\0';
151 size_ = len;
152 is_small_ = true;
153 } else {
154 // Use heap allocation
155 if (is_small_ || data_.heap.capacity < len + 1) {
156 // Need to allocate new buffer
157 if (!is_small_ && data_.heap.ptr) {
158 delete[] data_.heap.ptr;
159 }
160
161 size_t new_capacity = calculate_capacity(len);
162 data_.heap.ptr = new char[new_capacity];
163 data_.heap.capacity = new_capacity;
164 is_small_ = false;
165 }
166
167 std::memcpy(data_.heap.ptr, str, len);
168 data_.heap.ptr[len] = '\0';
169 size_ = len;
170 }
171 }

References kcenon::logger::small_string< SSO_SIZE >::calculate_capacity(), kcenon::logger::small_string< SSO_SIZE >::data_union::capacity, kcenon::logger::small_string< SSO_SIZE >::data_, kcenon::logger::small_string< SSO_SIZE >::data_union::heap, kcenon::logger::small_string< SSO_SIZE >::is_small_, kcenon::logger::small_string< SSO_SIZE >::data_union::ptr, kcenon::logger::small_string< SSO_SIZE >::size_, kcenon::logger::small_string< SSO_SIZE >::data_union::small, and kcenon::logger::small_string< SSO_SIZE >::SSO_CAPACITY.

Referenced by kcenon::logger::small_string< SSO_SIZE >::operator=(), kcenon::logger::small_string< SSO_SIZE >::small_string(), kcenon::logger::small_string< SSO_SIZE >::small_string(), and kcenon::logger::small_string< SSO_SIZE >::small_string().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ c_str()

template<size_t SSO_SIZE = 256>
const char * kcenon::logger::small_string< SSO_SIZE >::c_str ( ) const
inlinenoexcept

Get C-string pointer.

Definition at line 176 of file small_string.h.

176 {
177 return data();
178 }

References kcenon::logger::small_string< SSO_SIZE >::data().

Here is the call graph for this function:

◆ calculate_capacity()

template<size_t SSO_SIZE = 256>
static size_t kcenon::logger::small_string< SSO_SIZE >::calculate_capacity ( size_t required)
inlinestaticprivate

Calculate capacity for heap allocation.

Definition at line 390 of file small_string.h.

390 {
391 // Round up to next power of 2 for better allocation patterns
392 size_t capacity = required + 1; // +1 for null terminator
393 capacity = capacity * 3 / 2; // 1.5x growth factor
394
395 // Align to 16 bytes for better memory alignment
396 return (capacity + 15) & ~15;
397 }
size_t capacity() const noexcept
Get capacity.

References kcenon::logger::small_string< SSO_SIZE >::capacity().

Referenced by kcenon::logger::small_string< SSO_SIZE >::append(), kcenon::logger::small_string< SSO_SIZE >::assign(), and kcenon::logger::small_string< SSO_SIZE >::reserve().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ capacity()

◆ clear()

◆ data()

◆ empty()

template<size_t SSO_SIZE = 256>
bool kcenon::logger::small_string< SSO_SIZE >::empty ( ) const
inlinenoexcept

Check if empty.

Definition at line 204 of file small_string.h.

204 {
205 return size_ == 0;
206 }

References kcenon::logger::small_string< SSO_SIZE >::size_.

◆ get_memory_stats()

◆ is_small()

template<size_t SSO_SIZE = 256>
bool kcenon::logger::small_string< SSO_SIZE >::is_small ( ) const
inlinenoexcept

Check if using small string optimization.

Definition at line 211 of file small_string.h.

211 {
212 return is_small_;
213 }

References kcenon::logger::small_string< SSO_SIZE >::is_small_.

◆ length()

template<size_t SSO_SIZE = 256>
size_t kcenon::logger::small_string< SSO_SIZE >::length ( ) const
inlinenoexcept

Get length (same as size)

Definition at line 197 of file small_string.h.

197 {
198 return size_;
199 }

References kcenon::logger::small_string< SSO_SIZE >::size_.

◆ operator std::string_view()

template<size_t SSO_SIZE = 256>
kcenon::logger::small_string< SSO_SIZE >::operator std::string_view ( ) const
inlinenoexcept

Implicit conversion to string_view.

Definition at line 338 of file small_string.h.

338 {
339 return std::string_view(data(), size_);
340 }

References kcenon::logger::small_string< SSO_SIZE >::data(), and kcenon::logger::small_string< SSO_SIZE >::size_.

Here is the call graph for this function:

◆ operator!=()

template<size_t SSO_SIZE = 256>
bool kcenon::logger::small_string< SSO_SIZE >::operator!= ( const small_string< SSO_SIZE > & other) const
inlinenoexcept

Inequality comparison.

Definition at line 353 of file small_string.h.

353 {
354 return !(*this == other);
355 }

◆ operator+=() [1/2]

template<size_t SSO_SIZE = 256>
small_string & kcenon::logger::small_string< SSO_SIZE >::operator+= ( const char * str)
inline

Append operator.

Definition at line 315 of file small_string.h.

315 {
316 append(str, std::strlen(str));
317 return *this;
318 }

References kcenon::logger::small_string< SSO_SIZE >::append().

Here is the call graph for this function:

◆ operator+=() [2/2]

template<size_t SSO_SIZE = 256>
small_string & kcenon::logger::small_string< SSO_SIZE >::operator+= ( const std::string & str)
inline

Append operator.

Definition at line 323 of file small_string.h.

323 {
324 append(str);
325 return *this;
326 }

References kcenon::logger::small_string< SSO_SIZE >::append().

Here is the call graph for this function:

◆ operator=() [1/2]

template<size_t SSO_SIZE = 256>
small_string & kcenon::logger::small_string< SSO_SIZE >::operator= ( const small_string< SSO_SIZE > & other)
inline

Copy assignment.

Definition at line 107 of file small_string.h.

107 {
108 if (this != &other) {
109 assign(other.data(), other.size());
110 }
111 return *this;
112 }

References kcenon::logger::small_string< SSO_SIZE >::assign(), kcenon::logger::small_string< SSO_SIZE >::data(), and kcenon::logger::small_string< SSO_SIZE >::size().

Here is the call graph for this function:

◆ operator=() [2/2]

template<size_t SSO_SIZE = 256>
small_string & kcenon::logger::small_string< SSO_SIZE >::operator= ( small_string< SSO_SIZE > && other)
inlinenoexcept

Move assignment.

Definition at line 117 of file small_string.h.

117 {
118 if (this != &other) {
119 // Clean up current heap allocation if any
120 if (!is_small_ && data_.heap.ptr) {
121 delete[] data_.heap.ptr;
122 }
123
124 size_ = other.size_;
125 is_small_ = other.is_small_;
126
127 if (is_small_) {
128 std::memcpy(data_.small, other.data_.small, size_ + 1);
129 } else {
130 data_.heap.ptr = other.data_.heap.ptr;
131 data_.heap.capacity = other.data_.heap.capacity;
132 other.data_.heap.ptr = nullptr;
133 other.size_ = 0;
134 other.is_small_ = true;
135 }
136 }
137 return *this;
138 }

References kcenon::logger::small_string< SSO_SIZE >::data_union::capacity, kcenon::logger::small_string< SSO_SIZE >::data_, kcenon::logger::small_string< SSO_SIZE >::data_union::heap, kcenon::logger::small_string< SSO_SIZE >::is_small_, kcenon::logger::small_string< SSO_SIZE >::data_union::ptr, kcenon::logger::small_string< SSO_SIZE >::size_, and kcenon::logger::small_string< SSO_SIZE >::data_union::small.

◆ operator==() [1/2]

template<size_t SSO_SIZE = 256>
bool kcenon::logger::small_string< SSO_SIZE >::operator== ( const small_string< SSO_SIZE > & other) const
inlinenoexcept

Equality comparison.

Definition at line 345 of file small_string.h.

345 {
346 return size_ == other.size_ &&
347 std::memcmp(data(), other.data(), size_) == 0;
348 }

References kcenon::logger::small_string< SSO_SIZE >::data(), and kcenon::logger::small_string< SSO_SIZE >::size_.

Here is the call graph for this function:

◆ operator==() [2/2]

template<size_t SSO_SIZE = 256>
bool kcenon::logger::small_string< SSO_SIZE >::operator== ( const std::string & str) const
inlinenoexcept

Comparison with std::string.

Definition at line 360 of file small_string.h.

360 {
361 return size_ == str.size() &&
362 std::memcmp(data(), str.data(), size_) == 0;
363 }

References kcenon::logger::small_string< SSO_SIZE >::data(), and kcenon::logger::small_string< SSO_SIZE >::size_.

Here is the call graph for this function:

◆ reserve()

template<size_t SSO_SIZE = 256>
void kcenon::logger::small_string< SSO_SIZE >::reserve ( size_t new_capacity)
inline

Reserve capacity.

Definition at line 237 of file small_string.h.

237 {
238 if (new_capacity <= capacity()) {
239 return;
240 }
241
242 if (new_capacity <= SSO_CAPACITY) {
243 // Already using SSO, no need to reserve
244 return;
245 }
246
247 // Need heap allocation
248 size_t actual_capacity = calculate_capacity(new_capacity);
249 char* new_ptr = new char[actual_capacity];
250
251 // Copy existing data
252 std::memcpy(new_ptr, data(), size_ + 1);
253
254 // Clean up old allocation
255 if (!is_small_ && data_.heap.ptr) {
256 delete[] data_.heap.ptr;
257 }
258
259 data_.heap.ptr = new_ptr;
260 data_.heap.capacity = actual_capacity;
261 is_small_ = false;
262 }

References kcenon::logger::small_string< SSO_SIZE >::calculate_capacity(), kcenon::logger::small_string< SSO_SIZE >::capacity(), kcenon::logger::small_string< SSO_SIZE >::data_union::capacity, kcenon::logger::small_string< SSO_SIZE >::data(), kcenon::logger::small_string< SSO_SIZE >::data_, kcenon::logger::small_string< SSO_SIZE >::data_union::heap, kcenon::logger::small_string< SSO_SIZE >::is_small_, kcenon::logger::small_string< SSO_SIZE >::data_union::ptr, kcenon::logger::small_string< SSO_SIZE >::size_, and kcenon::logger::small_string< SSO_SIZE >::SSO_CAPACITY.

Here is the call graph for this function:

◆ size()

template<size_t SSO_SIZE = 256>
size_t kcenon::logger::small_string< SSO_SIZE >::size ( ) const
inlinenoexcept

Get size.

Definition at line 190 of file small_string.h.

190 {
191 return size_;
192 }

References kcenon::logger::small_string< SSO_SIZE >::size_.

Referenced by kcenon::logger::small_string< SSO_SIZE >::operator=(), and content_filter::should_log().

Here is the caller graph for this function:

◆ to_string()

Member Data Documentation

◆ data_

◆ is_small_

◆ size_

◆ SSO_CAPACITY


The documentation for this class was generated from the following file: