aboutsummaryrefslogtreecommitdiff
path: root/src/unstable/textbuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/unstable/textbuilder.cpp')
-rw-r--r--src/unstable/textbuilder.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/src/unstable/textbuilder.cpp b/src/unstable/textbuilder.cpp
index 73271f8..acd3501 100644
--- a/src/unstable/textbuilder.cpp
+++ b/src/unstable/textbuilder.cpp
@@ -5,4 +5,310 @@
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
15Bu::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
31Bu::TextBuilderCore::Chunk::~Chunk()
32{
33 delete[] pData;
34 pData = 0;
35 pNext = 0;
36}
37
38void 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
57Bu::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//
77Bu::TextBuilderCore::TextBuilderCore() :
78 pFirst( 0 ),
79 pLast( 0 ),
80 iLength( 0 )
81{
82}
83
84Bu::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
92Bu::TextBuilderCore::~TextBuilderCore()
93{
94 clear();
95}
96
97void 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
110void 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
133void 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
148void 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
186void Bu::TextBuilderCore::set( const CodePoint *pSrc, int32_t iLength )
187{
188 clear();
189 append( pSrc, iLength );
190}
191
192void Bu::TextBuilderCore::copyTo( void *pDestRaw, int32_t iLength )
193{
194 CodePoint *pDest = reinterpret_cast<CodePoint *>( pDestRaw );
195
196 Chunk *pCur = pFirst;
197 while( pCur && iLength )
198 {
199 int32_t iChunkLen = pCur->iLength;
200 if( iChunkLen > iLength )
201 iChunkLen = iLength;
202
203 memcpy( pDest, pCur->pData, iChunkLen*sizeof(CodePoint) );
204 pDest += iChunkLen;
205 iLength -= iChunkLen;
206
207 pCur = pCur->pNext;
208 }
209}
210
211Bu::CodePoint Bu::TextBuilderCore::getAt( int32_t iIndex ) const
212{
213 if( iIndex < 0 || iIndex >= iLength )
214 throw Bu::ExceptionBase("Requested index is out of range.");
215
216 Chunk *pCur = pFirst;
217 while( iIndex >= pCur->iLength )
218 {
219 iIndex -= pCur->iLength;
220 pCur = pCur->pNext;
221 }
222 return pCur->pData[iIndex];
223}
224
225/////
226// TextBuilder
227//
228
229Bu::TextBuilder::TextBuilder()
230{
231}
232
233Bu::TextBuilder::TextBuilder( const Text &rSrc )
234{
235 core->append( rSrc.getData(), rSrc.getSize() );
236}
237
238Bu::TextBuilder::TextBuilder( const TextBuilder &rSrc ) :
239 Bu::SharedCore<Bu::TextBuilder, Bu::TextBuilderCore>( rSrc )
240{
241}
242
243Bu::TextBuilder::~TextBuilder()
244{
245}
246
247void Bu::TextBuilder::set( const Text &rSrc )
248{
249 _hardCopy();
250 core->set( rSrc.getData(), rSrc.getSize() );
251}
252
253void Bu::TextBuilder::append( const Text &rSrc )
254{
255 _hardCopy();
256 core->append( rSrc.getData(), rSrc.getSize() );
257}
258
259void Bu::TextBuilder::append( const CodePoint *pSrc, int32_t iLength )
260{
261 _hardCopy();
262 core->append( pSrc, iLength );
263}
264
265void Bu::TextBuilder::prepend( const Text &rSrc )
266{
267 _hardCopy();
268 core->prepend( rSrc.getData(), rSrc.getSize() );
269}
270
271void Bu::TextBuilder::insert( int32_t iBefore, const Text &rSrc )
272{
273 _hardCopy();
274 core->insert( iBefore, rSrc.getData(), rSrc.getSize() );
275}
276
277void Bu::TextBuilder::clear()
278{
279 _hardCopy();
280 core->clear();
281}
282
283int32_t Bu::TextBuilder::getSize() const
284{
285 return core->iLength;
286}
287
288Bu::Text Bu::TextBuilder::getText() const
289{
290 return Text( *this );
291}
292
293void Bu::TextBuilder::copyTo( void *pDestRaw, int32_t iDestSize ) const
294{
295 core->copyTo( pDestRaw, iDestSize );
296}
297
298Bu::CodePoint Bu::TextBuilder::operator[]( int32_t iIndex ) const
299{
300 return core->getAt( iIndex );
301}
302
303Bu::TextBuilder &Bu::TextBuilder::operator=( const Text &rSrc )
304{
305 set( rSrc );
306 return *this;
307}
308
309Bu::TextBuilder &Bu::TextBuilder::operator==( const Text &rSrc )
310{
311
312 return *this;
313}
8 314