source: NonGTP/FCollada/FUtils/FUStringBuilder.hpp @ 964

Revision 964, 7.0 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*
2        Copyright (C) 2005-2006 Feeling Software Inc.
3        MIT License: http://www.opensource.org/licenses/mit-license.php
4*/
5/*
6        Based on the FS Import classes:
7        Copyright (C) 2005-2006 Feeling Software Inc
8        Copyright (C) 2005-2006 Autodesk Media Entertainment
9        MIT License: http://www.opensource.org/licenses/mit-license.php
10*/
11
12#include <limits>
13
14#ifdef WIN32
15#include <float.h>
16#endif
17
18#ifndef SAFE_DELETE_ARRAY
19#define SAFE_DELETE_ARRAY(ptr) if (ptr != NULL) { delete [] ptr; ptr = NULL; }
20#endif
21
22template <class Char, class SPrintF>
23FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(const String& sz)
24{
25        this->buffer = NULL;
26        this->size = 0;
27        this->reserved = 0;
28       
29        reserve(sz.size() + 32);
30        append(sz.c_str());
31}
32
33template <class Char, class SPrintF>
34FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(const Char* sz)
35{
36        this->buffer = NULL;
37        this->size = 0;
38        this->reserved = 0;
39
40        SPrintF s;
41        reserve(s.StrLen(sz) + 32);
42        append(sz);
43}
44
45template <class Char, class SPrintF>
46FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(Char ch, size_t count)
47{
48        this->buffer = NULL;
49        this->size = 0;
50        this->reserved = 0;
51
52        reserve(count + 32);
53        for (size_t i = 0; i < count; ++i) buffer[size++] = ch;
54}
55
56template <class Char, class SPrintF>
57FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(size_t reservation)
58{
59        this->buffer = NULL;
60        this->size = 0;
61        this->reserved = 0;
62
63        reserve(reservation);
64}
65
66template <class Char, class SPrintF>
67FUStringBuilderT<Char,SPrintF>::FUStringBuilderT()
68{
69        this->buffer = NULL;
70        this->size = 0;
71        this->reserved = 0;
72
73#ifndef _DEBUG
74        reserve(32);
75#endif
76}
77
78template <class Char, class SPrintF>
79FUStringBuilderT<Char,SPrintF>::~FUStringBuilderT()
80{
81        reserve(0);
82}
83
84template <class Char, class SPrintF>
85void FUStringBuilderT<Char,SPrintF>::enlarge(size_t minimum)
86{
87        reserve(max(reserved + minimum + 32, 2 * reserved + 32));
88}
89
90template <class Char, class SPrintF>
91void FUStringBuilderT<Char,SPrintF>::clear()
92{
93        size = 0;
94}
95
96template <class Char, class SPrintF>
97void FUStringBuilderT<Char,SPrintF>::reserve(size_t _length)
98{
99        FUAssert(size <= reserved, );
100        if (_length > reserved)
101        {
102                Char* b = new Char[_length];
103                memcpy(b, buffer, size * sizeof(Char));
104                SAFE_DELETE_ARRAY(buffer);
105                buffer = b;
106                reserved = _length;
107        }
108        else if (_length == 0)
109        {
110                SAFE_DELETE_ARRAY(buffer);
111                size = reserved = 0;
112        }
113        else if (_length < reserved)
114        {
115                size_t realSize = min(size, _length);
116                Char* b = new Char[_length];
117                memcpy(b, buffer, realSize * sizeof(Char));
118                SAFE_DELETE_ARRAY(buffer);
119                buffer = b;
120                reserved = _length;
121                size = realSize;
122        }
123}
124
125template <class Char, class SPrintF>
126void FUStringBuilderT<Char,SPrintF>::append(Char c)
127{
128        if (size + 1 >= reserved) enlarge(2);
129
130        buffer[size++] = c;
131}
132
133template <class Char, class SPrintF>
134void FUStringBuilderT<Char,SPrintF>::append(const String& sz) { append(sz.c_str()); }
135template <class Char, class SPrintF>
136void FUStringBuilderT<Char,SPrintF>::append(const Char* sz)
137{
138        // This is optimized for SMALL strings.
139        for (; *sz != 0; ++sz)
140        {
141                if (size >= reserved) enlarge(64);
142                buffer[size++] = *sz;
143        }
144}
145template <class Char, class SPrintF>
146void FUStringBuilderT<Char,SPrintF>::append(const FUStringBuilderT& b)
147{
148        if (size + b.size >= reserved) enlarge(64 + size + b.size - reserved);
149        memcpy(buffer + size, b.buffer, b.size * sizeof(Char));
150        size += b.size;
151}
152
153template <class Char, class SPrintF>
154void FUStringBuilderT<Char,SPrintF>::append(uint32 i)
155{
156        Char sz[128];
157        SPrintF writer; writer.PrintUInt32(sz, 128, i);
158        append(sz);
159}
160
161template <class Char, class SPrintF>
162void FUStringBuilderT<Char,SPrintF>::append(uint64 i)
163{
164        Char sz[128];
165        SPrintF writer; writer.PrintUInt64(sz, 128, i);
166        append(sz);
167}
168
169template <class Char, class SPrintF>
170void FUStringBuilderT<Char,SPrintF>::append(int32 i)
171{
172        Char sz[128];
173        SPrintF writer; writer.PrintInt32(sz, 128, i);
174        append(sz);
175}
176
177template <class Char, class SPrintF>
178void FUStringBuilderT<Char,SPrintF>::append(float f)
179{
180        if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN())
181        {
182                if (IsEquivalent(f, 0.0f, std::numeric_limits<float>::epsilon())) append('0');
183                else
184                {
185                        Char sz[128];
186                        SPrintF writer; writer.PrintFloat(sz, 128, f);
187                        append(sz);
188                }
189        }
190        else if (f == std::numeric_limits<float>::infinity())
191        { append('I'); append('N'); append('F'); }
192        else if (f == -std::numeric_limits<float>::infinity())
193        { append('-'); append('I'); append('N'); append('F'); }
194        else
195        { append('N'); append('a'); append('N'); }
196}
197
198template <class Char, class SPrintF>
199void FUStringBuilderT<Char,SPrintF>::append(double f)
200{
201        if (f != std::numeric_limits<double>::infinity() && f != -std::numeric_limits<double>::infinity() && f != std::numeric_limits<double>::quiet_NaN() && f != std::numeric_limits<double>::signaling_NaN())
202        {
203                if (IsEquivalent(f, 0.0, std::numeric_limits<double>::epsilon())) append('0');
204                else
205                {
206                        Char sz[128];
207                        SPrintF writer; writer.PrintFloat(sz, 128, f);
208                        append(sz);
209                }
210        }
211        else if (f == std::numeric_limits<double>::infinity())
212        { append('I'); append('N'); append('F'); }
213        else if (f == -std::numeric_limits<double>::infinity())
214        { append('-'); append('I'); append('N'); append('F'); }
215        else
216        { append('N'); append('a'); append('N'); }
217}
218
219template <class Char, class SPrintF>
220void FUStringBuilderT<Char,SPrintF>::appendLine(const Char* sz)
221{
222        append(sz);
223        append("\n");
224}
225
226template <class Char, class SPrintF>
227void FUStringBuilderT<Char,SPrintF>::remove(int32 start)
228{
229        if ((int32)size > start && start >= 0) size = start;
230}
231
232template <class Char, class SPrintF>
233void FUStringBuilderT<Char,SPrintF>::remove(int32 start, int32 end)
234{
235        int32 diff = end - start;
236        if ((int32)size >= end && start >= 0 && diff > 0)
237        {
238                const Char* stop = buffer + size - diff;
239                for (Char* p = buffer + start; p != stop; ++p)
240                {
241                        *p = *(p + diff);
242                }
243                size -= diff;
244        }
245}
246
247template <class Char, class SPrintF>
248typename FUStringBuilderT<Char,SPrintF>::String FUStringBuilderT<Char,SPrintF>::ToString()
249{
250        return String((const Char*)*this);
251}
252
253template <class Char, class SPrintF>
254const Char* FUStringBuilderT<Char,SPrintF>::ToCharPtr()
255{
256        if (size + 1 > reserved) enlarge(1);
257        buffer[size] = 0;
258        return buffer;
259}
260
261template <class Char, class SPrintF>
262int32 FUStringBuilderT<Char,SPrintF>::index(Char c)
263{
264        if (buffer != NULL && size > 0)
265        {
266                const Char* end = buffer + size + 1;
267                for (const Char* p = buffer; p != end; ++p)
268                {
269                        if (*p == c) return (int32)(p - buffer);
270                }
271        }
272        return -1;
273}
274
275template <class Char, class SPrintF>
276int32 FUStringBuilderT<Char,SPrintF>::rindex(Char c)
277{
278        if (buffer != NULL && size > 0)
279        {
280                for (const Char* p = buffer + size - 1; p != buffer; --p)
281                {
282                        if (*p == c) return (int32)(p - buffer);
283                }
284        }
285        return -1;
286}
Note: See TracBrowser for help on using the repository browser.