1+ namespace Hexa . NET . Utilities . Text
2+ {
3+ using System ;
4+ using System . Globalization ;
5+ using System . Runtime . CompilerServices ;
6+
7+ public unsafe class Utf8StringBuilder : IDisposable
8+ {
9+ private const int DefaultCapacity = 1024 * 16 ;
10+ public int Index ;
11+ private byte * buffer ;
12+ private int capacity ;
13+
14+ public Utf8StringBuilder ( )
15+ {
16+ buffer = ( byte * ) Alloc ( DefaultCapacity ) ;
17+ capacity = DefaultCapacity ;
18+ }
19+
20+ public static readonly Utf8StringBuilder Shared = new ( ) ;
21+
22+ public byte * Buffer => buffer ;
23+
24+ public int Capacity
25+ {
26+ get => capacity ;
27+ set
28+ {
29+ buffer = ( byte * ) ReAlloc ( buffer , value ) ;
30+ capacity = value ;
31+ }
32+ }
33+
34+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
35+ private void EnsureCapacity ( int newCapacity )
36+ {
37+ if ( newCapacity > capacity )
38+ {
39+ Capacity = Math . Max ( newCapacity , capacity * 2 ) ;
40+ }
41+ }
42+
43+ public void Append ( string text )
44+ {
45+ int result = 0 ;
46+ while ( result == 0 )
47+ {
48+ result = Utf8Formatter . ConvertUtf16ToUtf8 ( text , buffer + Index , capacity - Index ) ;
49+ if ( result == 0 ) EnsureCapacity ( capacity + text . Length * 2 ) ;
50+ }
51+ Index += result ;
52+ }
53+
54+ public void Append ( ReadOnlySpan < byte > text )
55+ {
56+ EnsureCapacity ( capacity + text . Length ) ;
57+ byte * start = buffer + Index ;
58+ byte * ptr = start ;
59+ byte * end = buffer + capacity ;
60+ int i = 0 ;
61+ while ( ptr != end && i < text . Length )
62+ {
63+ * ptr = text [ i ] ;
64+ ptr ++ ; i ++ ;
65+ }
66+ int written = ( int ) ( ptr - start ) ;
67+ Index += written ;
68+ }
69+
70+ public void Append ( char c )
71+ {
72+ int result = 0 ;
73+ while ( result == 0 )
74+ {
75+ result = Utf8Formatter . ConvertUtf16ToUtf8 ( c , buffer + Index , capacity - Index ) ;
76+ if ( result == 0 ) EnsureCapacity ( capacity + 2 ) ;
77+ }
78+ Index += result ;
79+ }
80+
81+ public void Append ( byte c )
82+ {
83+ EnsureCapacity ( capacity + 1 ) ;
84+ if ( Index + 1 >= capacity ) return ;
85+ buffer [ Index ++ ] = c ;
86+ }
87+
88+ public void Append ( double value , int digits = - 1 )
89+ {
90+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , digits ) ;
91+ }
92+
93+ public void Append ( float value , int digits = - 1 )
94+ {
95+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , digits ) ;
96+ }
97+
98+ public void Append ( int value )
99+ {
100+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
101+ }
102+
103+ public void Append ( uint value )
104+ {
105+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
106+ }
107+
108+ public void Append ( long value )
109+ {
110+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
111+ }
112+
113+ public void Append ( ulong value )
114+ {
115+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
116+ }
117+
118+ public void Append ( short value )
119+ {
120+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
121+ }
122+
123+ public void Append ( ushort value )
124+ {
125+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
126+ }
127+
128+ public void Append ( DateTime value , string format , CultureInfo cultureInfo )
129+ {
130+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , format , cultureInfo ) ;
131+ }
132+
133+ public void Append ( DateTime value , string format )
134+ {
135+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , format ) ;
136+ }
137+
138+ public void Append ( DateTime value )
139+ {
140+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
141+ }
142+
143+ public void Append ( TimeSpan value , string format , CultureInfo cultureInfo )
144+ {
145+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , format , cultureInfo ) ;
146+ }
147+
148+ public void Append ( TimeSpan value , string format )
149+ {
150+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index , format ) ;
151+ }
152+
153+ public void Append ( TimeSpan value )
154+ {
155+ Index += Utf8Formatter . Format ( value , buffer + Index , capacity - Index ) ;
156+ }
157+
158+ public void AppendByteSize ( long value , bool addSuffixSpace , int digits = - 1 )
159+ {
160+ Index += Utf8Formatter . FormatByteSize ( buffer + Index , capacity - Index , value , addSuffixSpace , digits ) ;
161+ }
162+
163+ public void End ( )
164+ {
165+ if ( Index >= capacity )
166+ {
167+ Index = capacity - 1 ;
168+ }
169+ buffer [ Index ] = 0 ;
170+ }
171+
172+ public void Reset ( )
173+ {
174+ Index = 0 ;
175+ }
176+
177+ public void Dispose ( )
178+ {
179+ if ( buffer != null )
180+ {
181+ Free ( buffer ) ;
182+ buffer = null ;
183+ capacity = 0 ;
184+ Index = 0 ;
185+ }
186+ }
187+
188+ public static implicit operator byte * ( Utf8StringBuilder builder ) => builder . buffer ;
189+ }
190+ }
0 commit comments