PostGIS  2.3.7dev-r@@SVN_REVISION@@
stringbuffer.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright 2002 Thamer Alharbash
22  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
23  *
24  **********************************************************************/
25 
26 
27 
28 #include "liblwgeom_internal.h"
29 #include "stringbuffer.h"
30 
36 {
38 }
39 
40 static void
42 {
43  s->str_start = lwalloc(size);
44  s->str_end = s->str_start;
45  s->capacity = size;
46  memset(s->str_start, 0, size);
47 }
48 
49 void
51 {
52  if ( s->str_start ) lwfree(s->str_start);
53 }
54 
55 void
57 {
59 }
60 
66 {
68 
69  s = lwalloc(sizeof(stringbuffer_t));
71  return s;
72 }
73 
77 void
79 {
81  if ( s ) lwfree(s);
82 }
83 
89 void
91 {
92  s->str_start[0] = '\0';
93  s->str_end = s->str_start;
94 }
95 
100 static inline void
102 {
103  size_t current_size = (s->str_end - s->str_start);
104  size_t capacity = s->capacity;
105  size_t required_size = current_size + size_to_add;
106 
107  while (capacity < required_size)
108  capacity *= 2;
109 
110  if ( capacity > s->capacity )
111  {
112  s->str_start = lwrealloc(s->str_start, capacity);
113  s->capacity = capacity;
114  s->str_end = s->str_start + current_size;
115  }
116 }
117 
121 char
123 {
124  if( s->str_end == s->str_start )
125  return 0;
126 
127  return *(s->str_end - 1);
128 }
129 
133 void
135 {
136  int alen = strlen(a); /* Length of string to append */
137  int alen0 = alen + 1; /* Length including null terminator */
138  stringbuffer_makeroom(s, alen0);
139  memcpy(s->str_end, a, alen0);
140  s->str_end += alen;
141 }
142 
148 const char*
150 {
151  return s->str_start;
152 }
153 
159 char*
161 {
162  size_t size = (s->str_end - s->str_start) + 1;
163  char *str = lwalloc(size);
164  memcpy(str, s->str_start, size);
165  str[size - 1] = '\0';
166  return str;
167 }
168 
173 int
175 {
176  return (s->str_end - s->str_start);
177 }
178 
182 void
184 {
186  stringbuffer_append(s, str);
187 }
188 
192 void
194 {
196 }
197 
203 static int
204 stringbuffer_avprintf(stringbuffer_t *s, const char *fmt, va_list ap)
205 {
206  int maxlen = (s->capacity - (s->str_end - s->str_start));
207  int len = 0; /* Length of the output */
208  va_list ap2;
209 
210  /* Make a copy of the variadic arguments, in case we need to print twice */
211  /* Print to our buffer */
212  va_copy(ap2, ap);
213  len = vsnprintf(s->str_end, maxlen, fmt, ap2);
214  va_end(ap2);
215 
216  /* Propogate errors up */
217  if ( len < 0 )
218  #if defined(__MINGW64_VERSION_MAJOR)
219  len = _vscprintf(fmt, ap2);
220  #else
221  return len;
222  #endif
223 
224  /* We didn't have enough space! */
225  /* Either Unix vsnprint returned write length larger than our buffer */
226  /* or Windows vsnprintf returned an error code. */
227  if ( len >= maxlen )
228  {
229  stringbuffer_makeroom(s, len + 1);
230  maxlen = (s->capacity - (s->str_end - s->str_start));
231 
232  /* Try to print a second time */
233  len = vsnprintf(s->str_end, maxlen, fmt, ap);
234 
235  /* Printing error? Error! */
236  if ( len < 0 ) return len;
237  /* Too long still? Error! */
238  if ( len >= maxlen ) return -1;
239  }
240 
241  /* Move end pointer forward and return. */
242  s->str_end += len;
243  return len;
244 }
245 
252 int
254 {
255  int r;
256  va_list ap;
257  va_start(ap, fmt);
258  r = stringbuffer_avprintf(s, fmt, ap);
259  va_end(ap);
260  return r;
261 }
262 
267 int
269 {
270  char *ptr = s->str_end;
271  int dist = 0;
272 
273  /* Roll backwards until we hit a non-space. */
274  while( ptr > s->str_start )
275  {
276  ptr--;
277  if( (*ptr == ' ') || (*ptr == '\t') )
278  {
279  continue;
280  }
281  else
282  {
283  ptr++;
284  dist = s->str_end - ptr;
285  *ptr = '\0';
286  s->str_end = ptr;
287  return dist;
288  }
289  }
290  return dist;
291 }
292 
303 int
305 {
306  char *ptr = s->str_end;
307  char *decimal_ptr = NULL;
308  int dist;
309 
310  if ( s->str_end - s->str_start < 2)
311  return 0;
312 
313  /* Roll backwards to find the decimal for this number */
314  while( ptr > s->str_start )
315  {
316  ptr--;
317  if ( *ptr == '.' )
318  {
319  decimal_ptr = ptr;
320  break;
321  }
322  if ( (*ptr >= '0') && (*ptr <= '9' ) )
323  continue;
324  else
325  break;
326  }
327 
328  /* No decimal? Nothing to trim! */
329  if ( ! decimal_ptr )
330  return 0;
331 
332  ptr = s->str_end;
333 
334  /* Roll backwards again, with the decimal as stop point, trimming contiguous zeroes */
335  while( ptr >= decimal_ptr )
336  {
337  ptr--;
338  if ( *ptr == '0' )
339  continue;
340  else
341  break;
342  }
343 
344  /* Huh, we get anywhere. Must not have trimmed anything. */
345  if ( ptr == s->str_end )
346  return 0;
347 
348  /* If we stopped at the decimal, we want to null that out.
349  It we stopped on a numeral, we want to preserve that, so push the
350  pointer forward one space. */
351  if ( *ptr != '.' )
352  ptr++;
353 
354  /* Add null terminator re-set the end of the stringbuffer. */
355  *ptr = '\0';
356  dist = s->str_end - ptr;
357  s->str_end = ptr;
358  return dist;
359 }
360 
void stringbuffer_init(stringbuffer_t *s)
Definition: stringbuffer.c:56
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:35
char * r
Definition: cu_in_wkt.c:24
void lwfree(void *mem)
Definition: lwutil.c:242
void stringbuffer_set(stringbuffer_t *s, const char *str)
Clear the stringbuffer_t and re-start it with the specified string.
Definition: stringbuffer.c:183
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string...
Definition: stringbuffer.c:160
tuple fmt
Definition: pixval.py:92
char * str_start
Definition: stringbuffer.h:41
stringbuffer_t * stringbuffer_create_with_size(size_t size)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:65
int stringbuffer_trim_trailing_white(stringbuffer_t *s)
Trims whitespace off the end of the stringbuffer.
Definition: stringbuffer.c:268
static void stringbuffer_init_with_size(stringbuffer_t *s, size_t size)
Definition: stringbuffer.c:41
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:253
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:174
void stringbuffer_clear(stringbuffer_t *s)
Reset the stringbuffer_t.
Definition: stringbuffer.c:90
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:204
void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.c:134
#define STRINGBUFFER_STARTSIZE
Definition: stringbuffer.h:35
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:78
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:101
void stringbuffer_copy(stringbuffer_t *dst, stringbuffer_t *src)
Copy the contents of src into dst.
Definition: stringbuffer.c:193
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:235
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:149
char stringbuffer_lastchar(stringbuffer_t *s)
Return the last character in the buffer.
Definition: stringbuffer.c:122
void * lwalloc(size_t size)
Definition: lwutil.c:227
void stringbuffer_release(stringbuffer_t *s)
Definition: stringbuffer.c:50
int stringbuffer_trim_trailing_zeroes(stringbuffer_t *s)
Trims zeroes off the end of the last number in the stringbuffer.
Definition: stringbuffer.c:304