diff options
author | Mike Buland <eichlan@xagasoft.com> | 2019-11-11 05:01:29 -0800 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2019-11-11 05:01:29 -0800 |
commit | 96759377ae8a4394d325747f597fe5b60afabf6e (patch) | |
tree | dd2daea517d126edb782924cf6003b5ae24cbe50 /src/unstable/textbuilder.cpp | |
parent | d5098782e5645d39b5e92f150e187e7194ef055a (diff) | |
download | libbu++-96759377ae8a4394d325747f597fe5b60afabf6e.tar.gz libbu++-96759377ae8a4394d325747f597fe5b60afabf6e.tar.bz2 libbu++-96759377ae8a4394d325747f597fe5b60afabf6e.tar.xz libbu++-96759377ae8a4394d325747f597fe5b60afabf6e.zip |
Working on TextBuilder & Text.
Seriously thinking about changing Text to just use full codepoints. It
would be much less work, more reliable and predictable, easier to use,
but would use twice the memory.
Diffstat (limited to 'src/unstable/textbuilder.cpp')
-rw-r--r-- | src/unstable/textbuilder.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/src/unstable/textbuilder.cpp b/src/unstable/textbuilder.cpp index 73271f8..af4dbac 100644 --- a/src/unstable/textbuilder.cpp +++ b/src/unstable/textbuilder.cpp | |||
@@ -5,4 +5,285 @@ | |||
5 | * terms of the license contained in the file LICENSE. | 5 | * terms of the license contained in the file LICENSE. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bu/textbuilder.h" | ||
9 | |||
10 | #include "bu/exceptionbase.h" | ||
11 | #include "bu/text.h" | ||
12 | |||
13 | #define PAGE_SIZE 16 | ||
14 | |||
15 | Bu::TextBuilderCore::Chunk::Chunk( const CodePoint *pSrc, int32_t iLength ) : | ||
16 | iLength( iLength ), | ||
17 | pData( 0 ), | ||
18 | pNext( 0 ) | ||
19 | { | ||
20 | if( iLength < PAGE_SIZE ) | ||
21 | { | ||
22 | pData = new CodePoint[PAGE_SIZE]; | ||
23 | } | ||
24 | else | ||
25 | { | ||
26 | pData = new CodePoint[iLength]; | ||
27 | } | ||
28 | memcpy( pData, pSrc, iLength*sizeof(CodePoint) ); | ||
29 | } | ||
30 | |||
31 | Bu::TextBuilderCore::Chunk::~Chunk() | ||
32 | { | ||
33 | delete[] pData; | ||
34 | pData = 0; | ||
35 | pNext = 0; | ||
36 | } | ||
37 | |||
38 | void Bu::TextBuilderCore::Chunk::append( const Bu::CodePoint *&pSrc, | ||
39 | int32_t &iLength ) | ||
40 | { | ||
41 | if( this->iLength >= PAGE_SIZE ) | ||
42 | { | ||
43 | // This chink is full, just return. | ||
44 | return; | ||
45 | } | ||
46 | int32_t iCopy = PAGE_SIZE-this->iLength; | ||
47 | if( iCopy > iLength ) | ||
48 | { | ||
49 | iCopy = iLength; | ||
50 | } | ||
51 | memcpy( pData+this->iLength, pSrc, iCopy*sizeof(Bu::CodePoint) ); | ||
52 | this->iLength += iCopy; | ||
53 | pSrc += iCopy; | ||
54 | iLength -= iCopy; | ||
55 | } | ||
56 | |||
57 | Bu::TextBuilderCore::Chunk *Bu::TextBuilderCore::Chunk::split( int32_t iIndex ) | ||
58 | { | ||
59 | if( iIndex == 0 ) | ||
60 | return NULL; | ||
61 | |||
62 | if( iIndex >= iLength ) | ||
63 | return NULL; | ||
64 | |||
65 | Chunk *pNew = new Chunk( pData+iIndex, iLength-iIndex ); | ||
66 | iLength -= iIndex; | ||
67 | pNew->pNext = pNext; | ||
68 | pNext = pNew; | ||
69 | |||
70 | return pNew; | ||
71 | } | ||
72 | |||
73 | |||
74 | ////// | ||
75 | // TextBuilderCore | ||
76 | // | ||
77 | Bu::TextBuilderCore::TextBuilderCore() : | ||
78 | pFirst( 0 ), | ||
79 | pLast( 0 ), | ||
80 | iLength( 0 ) | ||
81 | { | ||
82 | } | ||
83 | |||
84 | Bu::TextBuilderCore::TextBuilderCore( const TextBuilderCore &rSrc ) : | ||
85 | pFirst( 0 ), | ||
86 | pLast( 0 ), | ||
87 | iLength( rSrc.iLength ) | ||
88 | { | ||
89 | throw Bu::ExceptionBase("Not yet implemented."); | ||
90 | } | ||
91 | |||
92 | Bu::TextBuilderCore::~TextBuilderCore() | ||
93 | { | ||
94 | clear(); | ||
95 | } | ||
96 | |||
97 | void Bu::TextBuilderCore::clear() | ||
98 | { | ||
99 | Chunk *pCur = pFirst; | ||
100 | while( pCur ) | ||
101 | { | ||
102 | Chunk *pNext = pCur->pNext; | ||
103 | delete pCur; | ||
104 | pCur = pNext; | ||
105 | } | ||
106 | pFirst = pLast = 0; | ||
107 | iLength = 0; | ||
108 | } | ||
109 | |||
110 | void Bu::TextBuilderCore::append( const CodePoint *pSrc, int32_t iLength ) | ||
111 | { | ||
112 | this->iLength += iLength; | ||
113 | if( pFirst == 0 ) | ||
114 | { | ||
115 | // Nothing in the list, just add a chunk. | ||
116 | pFirst = pLast = new Chunk( pSrc, iLength ); | ||
117 | return; | ||
118 | } | ||
119 | else if( pLast->iLength < PAGE_SIZE ) | ||
120 | { | ||
121 | // Append to the last chunk first, this will modify pSrc & iLength. | ||
122 | pLast->append( pSrc, iLength ); | ||
123 | } | ||
124 | |||
125 | // If there's unused data at the end, append it now. | ||
126 | if( iLength > 0 ) | ||
127 | { | ||
128 | pLast->pNext = new Chunk( pSrc, iLength ); | ||
129 | pLast = pLast->pNext; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void Bu::TextBuilderCore::prepend( const CodePoint *pSrc, int32_t iLength ) | ||
134 | { | ||
135 | if( pFirst == 0 ) | ||
136 | { | ||
137 | pFirst = pLast = new Chunk( pSrc, iLength ); | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | Chunk *pNew = new Chunk( pSrc, iLength ); | ||
142 | pNew->pNext = pFirst; | ||
143 | pFirst = pNew; | ||
144 | } | ||
145 | this->iLength += iLength; | ||
146 | } | ||
147 | |||
148 | void Bu::TextBuilderCore::insert( int32_t iBefore, const CodePoint *pSrc, int32_t iLength ) | ||
149 | { | ||
150 | if( iBefore <= 0 ) | ||
151 | { | ||
152 | prepend( pSrc, iLength ); | ||
153 | return; | ||
154 | } | ||
155 | if( iBefore >= this->iLength ) | ||
156 | { | ||
157 | append( pSrc, iLength ); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | Chunk *pCur = pFirst; | ||
162 | while( pCur ) | ||
163 | { | ||
164 | if( iBefore == 0 ) | ||
165 | { | ||
166 | // Insert between chunks, no splitting required. | ||
167 | Chunk *pNew = new Chunk( pSrc, iLength ); | ||
168 | pNew->pNext = pCur->pNext; | ||
169 | pCur->pNext = pNew; | ||
170 | if( pLast == pCur ) | ||
171 | pLast = pNew; | ||
172 | } | ||
173 | if( iBefore < pCur->iLength ) | ||
174 | { | ||
175 | // This is the chunk we need to split. | ||
176 | Chunk *pNew = pCur->split( iBefore ); | ||
177 | if( pLast == pCur ) | ||
178 | pLast = pNew; | ||
179 | continue; | ||
180 | } | ||
181 | pCur = pCur->pNext; | ||
182 | } | ||
183 | this->iLength = iLength; | ||
184 | } | ||
185 | |||
186 | void Bu::TextBuilderCore::set( const CodePoint *pSrc, int32_t iLength ) | ||
187 | { | ||
188 | clear(); | ||
189 | append( pSrc, iLength ); | ||
190 | } | ||
191 | |||
192 | void Bu::TextBuilderCore::copyTo( void *pDestRaw, int32_t iLength ) | ||
193 | { | ||
194 | |||
195 | } | ||
196 | |||
197 | Bu::CodePoint Bu::TextBuilderCore::getAt( int32_t iIndex ) const | ||
198 | { | ||
199 | if( iIndex < 0 || iIndex >= iLength ) | ||
200 | throw Bu::ExceptionBase("Requested index is out of range."); | ||
201 | |||
202 | Chunk *pCur = pFirst; | ||
203 | while( iIndex >= pCur->iLength ) | ||
204 | { | ||
205 | iIndex -= pCur->iLength; | ||
206 | pCur = pCur->pNext; | ||
207 | } | ||
208 | return pCur->pData[iIndex]; | ||
209 | } | ||
210 | |||
211 | ///// | ||
212 | // TextBuilder | ||
213 | // | ||
214 | |||
215 | Bu::TextBuilder::TextBuilder() | ||
216 | { | ||
217 | } | ||
218 | |||
219 | Bu::TextBuilder::TextBuilder( const Text &rSrc ) | ||
220 | { | ||
221 | } | ||
222 | |||
223 | Bu::TextBuilder::TextBuilder( const TextBuilder &rSrc ) : | ||
224 | Bu::SharedCore<Bu::TextBuilder, Bu::TextBuilderCore>( rSrc ) | ||
225 | { | ||
226 | } | ||
227 | |||
228 | Bu::TextBuilder::~TextBuilder() | ||
229 | { | ||
230 | } | ||
231 | |||
232 | void Bu::TextBuilder::set( const Text &rSrc ) | ||
233 | { | ||
234 | _hardCopy(); | ||
235 | core->set( rSrc.getData(), rSrc.getSize() ); | ||
236 | } | ||
237 | |||
238 | void Bu::TextBuilder::append( const Text &rSrc ) | ||
239 | { | ||
240 | _hardCopy(); | ||
241 | } | ||
242 | |||
243 | void Bu::TextBuilder::append( const CodePoint *pSrc, int32_t iLength ) | ||
244 | { | ||
245 | _hardCopy(); | ||
246 | } | ||
247 | |||
248 | void Bu::TextBuilder::prepend( const Text &rSrc ) | ||
249 | { | ||
250 | _hardCopy(); | ||
251 | } | ||
252 | |||
253 | void Bu::TextBuilder::insert( const Text &rSrc ) | ||
254 | { | ||
255 | _hardCopy(); | ||
256 | } | ||
257 | |||
258 | void Bu::TextBuilder::clear() | ||
259 | { | ||
260 | _hardCopy(); | ||
261 | } | ||
262 | |||
263 | int32_t Bu::TextBuilder::getSize() const | ||
264 | { | ||
265 | return core->iLength; | ||
266 | } | ||
267 | |||
268 | Bu::Text Bu::TextBuilder::getText() const | ||
269 | { | ||
270 | return Text( *this ); | ||
271 | } | ||
272 | |||
273 | Bu::CodePoint Bu::TextBuilder::operator[]( int32_t iIndex ) const | ||
274 | { | ||
275 | return core->getAt( iIndex ); | ||
276 | } | ||
277 | |||
278 | Bu::TextBuilder &Bu::TextBuilder::operator=( const Text &rSrc ) | ||
279 | { | ||
280 | set( rSrc ); | ||
281 | return *this; | ||
282 | } | ||
283 | |||
284 | Bu::TextBuilder &Bu::TextBuilder::operator==( const Text &rSrc ) | ||
285 | { | ||
286 | set( pSrc ); | ||
287 | return *this; | ||
288 | } | ||
8 | 289 | ||