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 
39 #include "blocxx/BLOCXX_config.h"
40 #include "blocxx/StringBuffer.hpp"
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 
55 namespace BLOCXX_NAMESPACE
56 {
57 
58 #if defined(BLOCXX_AIX)
60 #endif // BLOCXX_AIX
61 
62 StringBuffer::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 }
70 StringBuffer::StringBuffer(const char* arg) :
71  m_len(strlen(arg)),
72  m_allocated(m_len + BLOCXX_DEFAULT_ALLOCATION_UNIT),
73  m_bfr(new char[m_allocated])
74 {
75  ::strcpy(m_bfr, arg);
76 }
79  m_len(arg.length()),
80  m_allocated(m_len + BLOCXX_DEFAULT_ALLOCATION_UNIT),
81  m_bfr(new char[m_allocated])
82 {
83  ::strcpy(m_bfr, arg.c_str());
84 }
87  m_len(arg.m_len), m_allocated(arg.m_allocated),
88  m_bfr(new char[arg.m_allocated])
89 {
90  ::memmove(m_bfr, arg.m_bfr, arg.m_len + 1);
91 }
95 {
96  StringBuffer(arg).swap(*this);
97  return *this;
98 }
101 StringBuffer::operator= (const char* str)
102 {
103  StringBuffer(str).swap(*this);
104  return *this;
105 }
109 {
110  StringBuffer(arg).swap(*this);
111  return *this;
112 }
114 void
116 {
117  std::swap(m_len, x.m_len);
119  std::swap(m_bfr, x.m_bfr);
120 }
122 void
124 {
125  m_len = 0;
126  m_bfr[0] = '\0';
127 }
128 
130 void
132 {
133  if (index < m_len)
134  {
135  m_bfr[index] = '\0';
136  m_len = index;
137  }
138 }
139 
141 char
142 StringBuffer::operator[] (size_t ndx) const
143 {
144  return (ndx > m_len) ? 0 : m_bfr[ndx];
145 }
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
156 
159 {
160  char bfr[6];
161  ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
162  return append(bfr);
163 }
167 {
168  char bfr[6];
169  ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
170  return append(bfr);
171 }
175 {
176  char bfr[16];
177  ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
178  return append(bfr);
179 }
183 {
184  char bfr[16];
185  ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
186  return append(bfr);
187 }
191 {
192  char bfr[16];
193  ::snprintf(bfr, sizeof(bfr), "%u", v);
194  return append(bfr);
195 }
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)
205 
207 StringBuffer::operator += (unsigned long v)
208 {
209  char bfr[28];
210  ::snprintf(bfr, sizeof(bfr), "%lu", v);
211  return append(bfr);
212 }
214 StringBuffer&
216 {
217  char bfr[28];
218  ::snprintf(bfr, sizeof(bfr), "%ld", v);
219  return append(bfr);
220 }
221 #endif
222 
223 StringBuffer&
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 }
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 }
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 }
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
282 
284 StringBuffer::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 }
293 bool
294 StringBuffer::equals(const char* arg) const
295 {
296  return ::strcmp(arg, m_bfr) == 0;
297 }
298 
300 bool
302 {
303  return ::strcmp(arg.m_bfr, m_bfr) == 0;
304 }
305 
307 bool
309 {
310  return (m_len && m_bfr[m_len-1] == ch);
311 }
312 
314 bool
316 {
317  return (m_len && m_bfr[0] == ch);
318 }
319 
321 void
323 {
324  if (m_len)
325  {
326  truncate(m_len-1);
327  }
328 }
329 
331 void
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.
361 const char*
362 StringBuffer::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 
405 std::ostream& operator<<(std::ostream& ostr, const StringBuffer& b)
406 {
407  ostr.write(b.c_str(), b.length());
408  return ostr;
409 }
410 
412 bool operator==(const StringBuffer& x, const StringBuffer& y)
413 {
414  return x.equals(y);
415 }
416 
418 bool operator!=(const StringBuffer& x, const StringBuffer& y)
419 {
420  return !(x == y);
421 }
422 
424 bool operator==(const StringBuffer& x, const String& y)
425 {
426  return x.equals(y.c_str());
427 }
428 
430 bool operator!=(const StringBuffer& x, const String& y)
431 {
432  return !(x == y);
433 }
434 
436 bool operator==(const String& x, const StringBuffer& y)
437 {
438  return x.equals(y.c_str());
439 }
440 
442 bool operator!=(const String& x, const StringBuffer& y)
443 {
444  return !(x == y);
445 }
446 
447 } // end namespace BLOCXX_NAMESPACE
448