nfx-stringbuilder 0.7.0
Cross-platform C++20 library for zero-allocation string building with Small Buffer Optimization
Loading...
Searching...
No Matches
StringBuilder.h
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2025 nfx
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
70
71#pragma once
72
73#include <cstdint>
74#include <format>
75#include <memory>
76#include <string>
77#include <string_view>
78
83#if defined( _MSC_VER )
84# define NFX_STRINGBUILDER_FORCE_INLINE __forceinline
85#elif defined( __GNUC__ ) || defined( __clang__ )
86# define NFX_STRINGBUILDER_FORCE_INLINE __attribute__( ( always_inline ) ) inline
87#else
88# define NFX_STRINGBUILDER_FORCE_INLINE inline
89#endif
90
91namespace nfx::string
92{
93 //=====================================================================
94 // StringBuilder class
95 //=====================================================================
96
107 class StringBuilder final
108 {
109 public:
110 //----------------------------------------------
111 // Construction
112 //----------------------------------------------
113
116
122 explicit StringBuilder( size_t initialCapacity );
123
129
134 StringBuilder( StringBuilder&& other ) noexcept;
135
136 //----------------------------------------------
137 // Destruction
138 //----------------------------------------------
139
141 ~StringBuilder() = default;
142
143 //----------------------------------------------
144 // Assignment
145 //----------------------------------------------
146
153
160
161 //----------------------------------------------
162 // Capacity and size information
163 //----------------------------------------------
164
171 [[nodiscard]] inline size_t size() const noexcept;
172
179 [[nodiscard]] inline size_t capacity() const noexcept;
180
186 [[nodiscard]] inline bool isEmpty() const noexcept;
187
188 //----------------------------------------------
189 // Data access
190 //----------------------------------------------
191
198 [[nodiscard]] inline char* data() noexcept;
199
206 [[nodiscard]] inline const char* data() const noexcept;
207
214 inline char& operator[]( size_t index );
215
222 inline const char& operator[]( size_t index ) const;
223
224 //----------------------------------------------
225 // Buffer management
226 //----------------------------------------------
227
232 inline void clear() noexcept;
233
240
241 inline void reserve( size_t newCapacity );
242
249 inline void resize( size_t newSize );
250
251 //----------------------------------------------
252 // Append operations
253 //----------------------------------------------
254
260 inline StringBuilder& append( std::string_view str );
261
267 inline StringBuilder& append( const std::string& str );
268
274 inline StringBuilder& append( const char* str );
275
282 template <size_t N>
284
290 inline StringBuilder& append( char c );
291
297 inline StringBuilder& append( std::int8_t value );
298
304 inline StringBuilder& append( std::uint8_t value );
305
311 inline StringBuilder& append( std::int16_t value );
312
318 inline StringBuilder& append( std::uint16_t value );
319
325 inline StringBuilder& append( std::int32_t value );
326
332 inline StringBuilder& append( std::uint32_t value );
333
339 inline StringBuilder& append( std::int64_t value );
340
346 inline StringBuilder& append( std::uint64_t value );
347
353 inline StringBuilder& append( float value );
354
360 inline StringBuilder& append( double value );
361
362 //----------------------------------------------
363 // Line operations
364 //----------------------------------------------
365
381 inline StringBuilder& appendLine( std::string_view str = "" );
382
388 inline StringBuilder& appendLine( const std::string& str );
389
395 inline StringBuilder& appendLine( const char* str );
396
397 //----------------------------------------------
398 // Prepend operations
399 //----------------------------------------------
400
408 StringBuilder& prepend( std::string_view str );
409
415 inline StringBuilder& prepend( const std::string& str );
416
422 inline StringBuilder& prepend( const char* str );
423
429 inline StringBuilder& prepend( char c );
430
436 inline StringBuilder& prepend( std::int8_t value );
437
443 inline StringBuilder& prepend( std::uint8_t value );
444
450 inline StringBuilder& prepend( std::int16_t value );
451
457 inline StringBuilder& prepend( std::uint16_t value );
458
464 inline StringBuilder& prepend( std::int32_t value );
465
471 inline StringBuilder& prepend( std::uint32_t value );
472
478 inline StringBuilder& prepend( std::int64_t value );
479
485 inline StringBuilder& prepend( std::uint64_t value );
486
492 inline StringBuilder& prepend( float value );
493
499 inline StringBuilder& prepend( double value );
500
501 //----------------------------------------------
502 // Batch operations
503 //----------------------------------------------
504
518 template <typename T, typename... Args, typename = std::enable_if_t<( sizeof...( Args ) > 0 )>>
519 inline StringBuilder& append( T&& first, Args&&... args );
520
521 //----------------------------------------------
522 // Join operations
523 //----------------------------------------------
524
544 template <typename Container>
545 inline StringBuilder& join( const Container& items, std::string_view delimiter );
546
561 template <typename Container>
562 inline StringBuilder& join( const Container& items, char delimiter );
563
564 //----------------------------------------------
565 // Stream operators
566 //----------------------------------------------
567
573 inline StringBuilder& operator<<( std::string_view str );
574
580 inline StringBuilder& operator<<( const std::string& str );
581
587 inline StringBuilder& operator<<( const char* str );
588
595 template <size_t N>
596 NFX_STRINGBUILDER_FORCE_INLINE StringBuilder& operator<<( const char ( &str )[N] );
597
603 inline StringBuilder& operator<<( char c );
604
610 inline StringBuilder& operator<<( std::int8_t value );
611
617 inline StringBuilder& operator<<( std::uint8_t value );
618
624 inline StringBuilder& operator<<( std::int16_t value );
625
631 inline StringBuilder& operator<<( std::uint16_t value );
632
638 inline StringBuilder& operator<<( std::int32_t value );
639
645 inline StringBuilder& operator<<( std::uint32_t value );
646
652 inline StringBuilder& operator<<( std::int64_t value );
653
659 inline StringBuilder& operator<<( std::uint64_t value );
660
666 inline StringBuilder& operator<<( float value );
667
673 inline StringBuilder& operator<<( double value );
674
675 //----------------------------------------------
676 // Formatting operations
677 //----------------------------------------------
678
689 template <typename... Args>
690 inline StringBuilder& format( std::format_string<Args...> fmt, Args&&... args );
691
692 //----------------------------------------------
693 // String conversion
694 //----------------------------------------------
695
701 [[nodiscard]] inline std::string toString() const&;
702
710 [[nodiscard]] std::string toString() &&;
711
718 [[nodiscard]] inline std::string_view toStringView() const noexcept;
719
720 //----------------------------------------------
721 // STL support
722 //----------------------------------------------
723
729 inline void push_back( char c );
730
731 //----------------------------------------------
732 // Iterator interface
733 //----------------------------------------------
734
736 using value_type = char;
737
739 using Iterator = char*;
740
742 using ConstIterator = const char*;
743
746
749
756 [[nodiscard]] inline Iterator begin() noexcept;
757
764 [[nodiscard]] inline ConstIterator begin() const noexcept;
765
772 [[nodiscard]] inline Iterator end() noexcept;
773
780 [[nodiscard]] inline ConstIterator end() const noexcept;
781
782 private:
783 //----------------------------------------------
784 // Private members
785 //----------------------------------------------
786
788 static constexpr size_t STACK_BUFFER_SIZE = 256;
789
801 static constexpr size_t GROWTH_THRESHOLD = 8192;
802 static constexpr double AGGRESSIVE_GROWTH_FACTOR = 2.0;
803 static constexpr double STANDARD_GROWTH_FACTOR = 1.5;
804
806 alignas( 32 ) char m_stackBuffer[STACK_BUFFER_SIZE];
807
809 std::unique_ptr<char[]> m_heapBuffer;
810
812 char* m_buffer;
813
815 size_t m_size;
816
818 size_t m_capacity;
819
821 bool m_onHeap;
822
823 //----------------------------------------------
824 // Private methods
825 //----------------------------------------------
826
831 void ensureCapacity( size_t neededCapacity );
832 };
833} // namespace nfx::string
834
835#include "nfx/detail/string/StringBuilder.inl"
#define NFX_STRINGBUILDER_FORCE_INLINE
Cross-platform forced inline macro for critical hot-path methods.
void push_back(char c)
Appends single character to the buffer (for STL compatibility).
size_t capacity() const noexcept
Get current buffer capacity in bytes.
char * Iterator
Mutable iterator type for buffer traversal.
StringBuilder & format(std::format_string< Args... > fmt, Args &&... args)
Format and append text using std::format.
StringBuilder & appendLine(std::string_view str="")
Appends string_view contents followed by a newline character.
char * data() noexcept
Get mutable pointer to buffer data.
StringBuilder & prepend(std::string_view str)
Prepends string_view contents to the buffer.
size_t size() const noexcept
Get current buffer size in bytes.
std::string toString() const &
Convert buffer content to std::string.
ConstIterator const_iterator
Type alias for const iterator.
bool isEmpty() const noexcept
Check if buffer is empty.
StringBuilder(const StringBuilder &other)
Copy constructor.
StringBuilder & operator=(const StringBuilder &other)
Copy assignment operator.
StringBuilder(StringBuilder &&other) noexcept
Move constructor.
std::string_view toStringView() const noexcept
Get string_view of buffer content.
Iterator begin() noexcept
Get mutable iterator to beginning of buffer.
StringBuilder(size_t initialCapacity)
Constructor with specified initial capacity.
const char * ConstIterator
Immutable iterator type for buffer traversal.
void reserve(size_t newCapacity)
Reserve minimum capacity for buffer.
StringBuilder & join(const Container &items, std::string_view delimiter)
Join container elements with delimiter.
char value_type
Character type for iterator compatibility.
StringBuilder & operator=(StringBuilder &&other) noexcept
Move assignment operator.
void resize(size_t newSize)
Resize buffer to specified size.
~StringBuilder()=default
Destructor.
Iterator end() noexcept
Get mutable iterator to end of buffer.
void clear() noexcept
Clear buffer content without deallocating memory.
StringBuilder & append(std::string_view str)
Appends string_view contents to the buffer efficiently.
StringBuilder()
Default constructor.
Iterator iterator
Type alias for iterator.