blocxx
StringBuffer.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38
39#include "blocxx/BLOCXX_config.h"
41#include "blocxx/Char16.hpp"
42
43#include <cstring>
44#include <cstdio>
45#include <cctype>
46#if defined(BLOCXX_HAVE_ISTREAM) && defined(BLOCXX_HAVE_OSTREAM)
47#include <istream>
48#include <ostream>
49#else
50#include <iostream>
51#endif
52#include <algorithm> // for std::swap
53#include <cfloat> // for DBL_MANT_DIG
54
55namespace BLOCXX_NAMESPACE
56{
57
58#if defined(BLOCXX_AIX)
60#endif // BLOCXX_AIX
62StringBuffer::StringBuffer(size_t allocSize) :
63 m_len(0),
64 m_allocated(allocSize > 0 ? allocSize : BLOCXX_DEFAULT_ALLOCATION_UNIT),
65 m_bfr(new char[m_allocated])
66{
67 m_bfr[0] = 0;
68}
69
71 m_len(strlen(arg)),
73 m_bfr(new char[m_allocated])
74{
75 ::strcpy(m_bfr, arg);
76}
77
79 m_len(arg.length()),
81 m_bfr(new char[m_allocated])
82{
83 ::strcpy(m_bfr, arg.c_str());
84}
85
88 m_bfr(new char[arg.m_allocated])
89{
90 ::memmove(m_bfr, arg.m_bfr, arg.m_len + 1);
91}
92
95{
96 StringBuffer(arg).swap(*this);
97 return *this;
98}
99
102{
103 StringBuffer(str).swap(*this);
104 return *this;
105}
106
109{
110 StringBuffer(arg).swap(*this);
111 return *this;
112}
113
114void
116{
117 std::swap(m_len, x.m_len);
118 std::swap(m_allocated, x.m_allocated);
119 std::swap(m_bfr, x.m_bfr);
120}
121
122void
124{
125 m_len = 0;
126 m_bfr[0] = '\0';
127}
128
130void
132{
133 if (index < m_len)
134 {
135 m_bfr[index] = '\0';
136 m_len = index;
137 }
138}
139
141char
143{
144 return (ndx > m_len) ? 0 : m_bfr[ndx];
145}
146
147// This operator must write "TRUE"/"FALSE" to StringBuffer
150{
151 return append(v.toString());
152}
153#if defined(BLOCXX_WIN32)
154#define snprintf _snprintf // stupid windoze...
155#endif
159{
160 char bfr[6];
161 ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
162 return append(bfr);
163}
164
167{
168 char bfr[6];
169 ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
170 return append(bfr);
171}
172
175{
176 char bfr[16];
177 ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
178 return append(bfr);
179}
180
183{
184 char bfr[16];
185 ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
186 return append(bfr);
187}
188
191{
192 char bfr[16];
193 ::snprintf(bfr, sizeof(bfr), "%u", v);
194 return append(bfr);
195}
196
199{
200 char bfr[16];
201 ::snprintf(bfr, sizeof(bfr), "%d", v);
202 return append(bfr);
203}
204#if defined(BLOCXX_INT32_IS_INT) && defined(BLOCXX_INT64_IS_LONG_LONG)
207StringBuffer::operator += (unsigned long v)
208{
209 char bfr[28];
210 ::snprintf(bfr, sizeof(bfr), "%lu", v);
211 return append(bfr);
212}
214StringBuffer&
216{
217 char bfr[28];
218 ::snprintf(bfr, sizeof(bfr), "%ld", v);
219 return append(bfr);
220}
221#endif
225{
226 char bfr[28];
227#if BLOCXX_SIZEOF_LONG_INT == 8
228 ::snprintf(bfr, sizeof(bfr), "%lu", v);
229#else
230 ::snprintf(bfr, sizeof(bfr), "%llu", v);
231#endif
232 return append(bfr);
233}
234
237{
238 char bfr[28];
239#if BLOCXX_SIZEOF_LONG_INT == 8
240 ::snprintf(bfr, sizeof(bfr), "%ld", v);
241#else
242 ::snprintf(bfr, sizeof(bfr), "%lld", v);
243#endif
244 return append(bfr);
245}
246
247// decimal digits = ceiling((bits)*ln(2)/ln(10))
250{
251 char bfr[128];
252#if FLT_RADIX == 2
253#if defined(BLOCXX_REAL32_IS_FLOAT)
254 ::snprintf(bfr, sizeof(bfr), "%.*g", FLT_MANT_DIG * 3 / 10 + 1, static_cast<double>(v));
255#elif defined(BLOCXX_REAL32_IS_DOUBLE)
256 ::snprintf(bfr, sizeof(bfr), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, v);
257#endif
258#else
259#error "The formula for computing the number of digits of precision for a floating point needs to be implmented. It's ceiling(bits * log(FLT_RADIX) / log(10))"
260#endif
261 return append(bfr);
262}
263
266{
267 char bfr[32];
268#if FLT_RADIX == 2
269#if defined(BLOCXX_REAL64_IS_DOUBLE)
270 ::snprintf(bfr, sizeof(bfr), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, v);
271#elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
272 ::snprintf(bfr, sizeof(bfr), "%.*Lg", LDBL_MANT_DIG * 3 / 10 + 1, v);
273#endif
274#else
275#error "The formula for computing the number of digits of precision for a floating point needs to be implmented. It's ceiling(bits * log(FLT_RADIX) / log(10))"
276#endif
277 return append(bfr);
278}
279#if defined(BLOCXX_WIN32)
280#undef snprintf
281#endif
284StringBuffer::append(const char* str, const size_t len)
285{
286 checkAvail(len+1);
287 ::strncpy(m_bfr+m_len, str, len);
288 m_len += len;
289 m_bfr[m_len] = '\0';
290 return *this;
291}
292
293bool
294StringBuffer::equals(const char* arg) const
295{
296 return ::strcmp(arg, m_bfr) == 0;
297}
298
300bool
302{
303 return ::strcmp(arg.m_bfr, m_bfr) == 0;
304}
305
307bool
309{
310 return (m_len && m_bfr[m_len-1] == ch);
311}
312
314bool
316{
317 return (m_len && m_bfr[0] == ch);
318}
319
321void
323{
324 if (m_len)
325 {
326 truncate(m_len-1);
327 }
328}
329
331void
333{
334 if (m_len)
335 {
336 while (m_len && isspace(m_bfr[m_len-1]))
337 {
338 m_bfr[--m_len] = 0;
339 }
340
341 if (m_len)
342 {
343 char *p = m_bfr;
344 while (*p && isspace(*p))
345 {
346 ++p;
347 }
348
349 if (*p && p > m_bfr)
350 {
351 m_len -= (p - m_bfr);
352 memmove(m_bfr, p, m_len+1);
353 }
354 }
355 }
356}
357
359// Get one line from an input stream. This StringBuffer object will be
360// reset (cleared) before an attempt is made to retrieve the line.
361const char*
362StringBuffer::getLine(std::istream& is, bool resetBuffer)
363{
364 if (resetBuffer)
365 {
366 reset();
367 }
368
369 if (is)
370 {
371 size_t count = 0;
372 std::streambuf *sb = is.rdbuf();
373
374 while (1)
375 {
376 int ch = sb->sbumpc();
377 if (ch == EOF)
378 {
379 is.setstate(count == 0
380 ? (std::ios::failbit | std::ios::eofbit) : std::ios::eofbit);
381 break;
382 }
383
384 ++count;
385
386 if (ch == '\n')
387 {
388 break;
389 }
390
391 append(static_cast<char>(ch));
392 }
393 }
394
395 const char* p = ::strchr(m_bfr, '\r');
396 if (p)
397 {
398 truncate(size_t(p-m_bfr));
399 }
400
401 return m_bfr;
402}
403
405std::ostream& operator<<(std::ostream& ostr, const StringBuffer& b)
406{
407 ostr.write(b.c_str(), b.length());
408 return ostr;
409}
410
412bool operator==(const StringBuffer& x, const StringBuffer& y)
413{
414 return x.equals(y);
415}
416
418bool operator!=(const StringBuffer& x, const StringBuffer& y)
419{
420 return !(x == y);
421}
422
424bool operator==(const StringBuffer& x, const String& y)
425{
426 return x.equals(y.c_str());
427}
428
430bool operator!=(const StringBuffer& x, const String& y)
431{
432 return !(x == y);
433}
434
436bool operator==(const String& x, const StringBuffer& y)
437{
438 return x.equals(y.c_str());
439}
440
442bool operator!=(const String& x, const StringBuffer& y)
443{
444 return !(x == y);
445}
446
447} // end namespace BLOCXX_NAMESPACE
448
The Bool class is an abstraction for the boolean data type.
Definition Bool.hpp:57
String toString() const
Definition Bool.cpp:71
StringBuffer(size_t allocSize=BLOCXX_DEFAULT_ALLOCATION_UNIT)
StringBuffer & append(char c)
const char * getLine(std::istream &is, bool resetBuffer=true)
Fill this StringBuffer object with the next line from the given input stream.
StringBuffer & operator+=(char c)
static const size_t BLOCXX_DEFAULT_ALLOCATION_UNIT
void truncate(size_t index)
Truncate the string at the given index.
bool equals(const char *arg) const
char operator[](size_t ndx) const
StringBuffer & operator=(const StringBuffer &arg)
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
const char * c_str() const
Definition String.cpp:905
bool equals(const String &arg) const
Determine if another String object is equal to this String object.
Definition String.cpp:517
Taken from RFC 1321.
unsigned char UInt8
Definition Types.hpp:66
signed char Int8
Definition Types.hpp:67
bool operator==(const Array< T > &x, const Array< T > &y)
ostream & operator<<(ostream &ostrm, const Bool &arg)
Definition Bool.cpp:77
bool operator!=(const Array< T > &x, const Array< T > &y)
Determine two Arrays are not equal.
Definition Array.hpp:446