PostGIS  2.2.8dev-r@@SVN_REVISION@@
stringbuffer.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * Copyright 2002 Thamer Alharbash
5  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  *
19  * The name of the author may not be used to endorse or promote
20  * products derived from this software without specific prior
21  * written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  **********************************************************************/
37 
38 
39 #include "liblwgeom_internal.h"
40 #include "stringbuffer.h"
41 
47 {
49 }
50 
56 {
58 
59  s = lwalloc(sizeof(stringbuffer_t));
60  s->str_start = lwalloc(size);
61  s->str_end = s->str_start;
62  s->capacity = size;
63  memset(s->str_start,0,size);
64  return s;
65 }
66 
70 void
72 {
73  if ( s->str_start ) lwfree(s->str_start);
74  if ( s ) lwfree(s);
75 }
76 
82 void
84 {
85  s->str_start[0] = '\0';
86  s->str_end = s->str_start;
87 }
88 
93 static inline void
94 stringbuffer_makeroom(stringbuffer_t *s, size_t size_to_add)
95 {
96  size_t current_size = (s->str_end - s->str_start);
97  size_t capacity = s->capacity;
98  size_t required_size = current_size + size_to_add;
99 
100  while (capacity < required_size)
101  capacity *= 2;
102 
103  if ( capacity > s->capacity )
104  {
105  s->str_start = lwrealloc(s->str_start, capacity);
106  s->capacity = capacity;
107  s->str_end = s->str_start + current_size;
108  }
109 }
110 
114 char
116 {
117  if( s->str_end == s->str_start )
118  return 0;
119 
120  return *(s->str_end - 1);
121 }
122 
126 void
128 {
129  int alen = strlen(a); /* Length of string to append */
130  int alen0 = alen + 1; /* Length including null terminator */
131  stringbuffer_makeroom(s, alen0);
132  memcpy(s->str_end, a, alen0);
133  s->str_end += alen;
134 }
135 
141 const char*
143 {
144  return s->str_start;
145 }
146 
152 char*
154 {
155  size_t size = (s->str_end - s->str_start) + 1;
156  char *str = lwalloc(size);
157  memcpy(str, s->str_start, size);
158  str[size - 1] = '\0';
159  return str;
160 }
161 
166 int
168 {
169  return (s->str_end - s->str_start);
170 }
171 
175 void
177 {
179  stringbuffer_append(s, str);
180 }
181 
185 void
187 {
189 }
190 
196 static int
197 stringbuffer_avprintf(stringbuffer_t *s, const char *fmt, va_list ap)
198 {
199  int maxlen = (s->capacity - (s->str_end - s->str_start));
200  int len = 0; /* Length of the output */
201  va_list ap2;
202 
203  /* Make a copy of the variadic arguments, in case we need to print twice */
204  /* Print to our buffer */
205  va_copy(ap2, ap);
206  len = vsnprintf(s->str_end, maxlen, fmt, ap2);
207  va_end(ap2);
208 
209  /* Propogate errors up */
210  if ( len < 0 )
211  #if defined(__MINGW64_VERSION_MAJOR)
212  len = _vscprintf(fmt, ap2);
213  #else
214  return len;
215  #endif
216 
217  /* We didn't have enough space! */
218  /* Either Unix vsnprint returned write length larger than our buffer */
219  /* or Windows vsnprintf returned an error code. */
220  if ( len >= maxlen )
221  {
222  stringbuffer_makeroom(s, len + 1);
223  maxlen = (s->capacity - (s->str_end - s->str_start));
224 
225  /* Try to print a second time */
226  len = vsnprintf(s->str_end, maxlen, fmt, ap);
227 
228  /* Printing error? Error! */
229  if ( len < 0 ) return len;
230  /* Too long still? Error! */
231  if ( len >= maxlen ) return -1;
232  }
233 
234  /* Move end pointer forward and return. */
235  s->str_end += len;
236  return len;
237 }
238 
245 int
247 {
248  int r;
249  va_list ap;
250  va_start(ap, fmt);
251  r = stringbuffer_avprintf(s, fmt, ap);
252  va_end(ap);
253  return r;
254 }
255 
260 int
262 {
263  char *ptr = s->str_end;
264  int dist = 0;
265 
266  /* Roll backwards until we hit a non-space. */
267  while( ptr > s->str_start )
268  {
269  ptr--;
270  if( (*ptr == ' ') || (*ptr == '\t') )
271  {
272  continue;
273  }
274  else
275  {
276  ptr++;
277  dist = s->str_end - ptr;
278  *ptr = '\0';
279  s->str_end = ptr;
280  return dist;
281  }
282  }
283  return dist;
284 }
285 
296 int
298 {
299  char *ptr = s->str_end;
300  char *decimal_ptr = NULL;
301  int dist;
302 
303  if ( s->str_end - s->str_start < 2)
304  return 0;
305 
306  /* Roll backwards to find the decimal for this number */
307  while( ptr > s->str_start )
308  {
309  ptr--;
310  if ( *ptr == '.' )
311  {
312  decimal_ptr = ptr;
313  break;
314  }
315  if ( (*ptr >= '0') && (*ptr <= '9' ) )
316  continue;
317  else
318  break;
319  }
320 
321  /* No decimal? Nothing to trim! */
322  if ( ! decimal_ptr )
323  return 0;
324 
325  ptr = s->str_end;
326 
327  /* Roll backwards again, with the decimal as stop point, trimming contiguous zeroes */
328  while( ptr >= decimal_ptr )
329  {
330  ptr--;
331  if ( *ptr == '0' )
332  continue;
333  else
334  break;
335  }
336 
337  /* Huh, we get anywhere. Must not have trimmed anything. */
338  if ( ptr == s->str_end )
339  return 0;
340 
341  /* If we stopped at the decimal, we want to null that out.
342  It we stopped on a numeral, we want to preserve that, so push the
343  pointer forward one space. */
344  if ( *ptr != '.' )
345  ptr++;
346 
347  /* Add null terminator re-set the end of the stringbuffer. */
348  *ptr = '\0';
349  dist = s->str_end - ptr;
350  s->str_end = ptr;
351  return dist;
352 }
353 
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:46
char * r
Definition: cu_in_wkt.c:24
void lwfree(void *mem)
Definition: lwutil.c:214
void stringbuffer_set(stringbuffer_t *s, const char *str)
Clear the stringbuffer_t and re-start it with the specified string.
Definition: stringbuffer.c:176
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string...
Definition: stringbuffer.c:153
def fmt
Definition: pixval.py:92
char * str_start
Definition: stringbuffer.h:52
stringbuffer_t * stringbuffer_create_with_size(size_t size)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:55
int stringbuffer_trim_trailing_white(stringbuffer_t *s)
Trims whitespace off the end of the stringbuffer.
Definition: stringbuffer.c:261
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided...
Definition: stringbuffer.c:246
int stringbuffer_getlength(stringbuffer_t *s)
Returns the length of the current string, not including the null terminator (same behavior as strlen(...
Definition: stringbuffer.c:167
void stringbuffer_clear(stringbuffer_t *s)
Reset the stringbuffer_t.
Definition: stringbuffer.c:83
char * s
Definition: cu_in_wkt.c:23
static int stringbuffer_avprintf(stringbuffer_t *s, const char *fmt, va_list ap)
Appends a formatted string to the current string buffer, using the format and argument list provided...
Definition: stringbuffer.c:197
void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.c:127
#define STRINGBUFFER_STARTSIZE
Definition: stringbuffer.h:46
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:71
static void stringbuffer_makeroom(stringbuffer_t *s, size_t size_to_add)
If necessary, expand the stringbuffer_t internal buffer to accomodate the specified additional size...
Definition: stringbuffer.c:94
void stringbuffer_copy(stringbuffer_t *dst, stringbuffer_t *src)
Copy the contents of src into dst.
Definition: stringbuffer.c:186
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:207
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:142
char stringbuffer_lastchar(stringbuffer_t *s)
Return the last character in the buffer.
Definition: stringbuffer.c:115
void * lwalloc(size_t size)
Definition: lwutil.c:199
int stringbuffer_trim_trailing_zeroes(stringbuffer_t *s)
Trims zeroes off the end of the last number in the stringbuffer.
Definition: stringbuffer.c:297