Success build TortoiseMerge.
[TortoiseGit.git] / src / TortoiseMerge / libsvn_diff / svn_string.c
blobc665eb73de14bda9b3cb7587c2fea79a77c7e81b
1 /*
2 * svn_string.h: routines to manipulate counted-length strings
3 * (svn_stringbuf_t and svn_string_t) and C strings.
6 * ====================================================================
7 * Copyright (c) 2000-2008 CollabNet. All rights reserved.
9 * This software is licensed as described in the file COPYING, which
10 * you should have received as part of this distribution. The terms
11 * are also available at http://subversion.tigris.org/license-1.html.
12 * If newer versions of this license are posted there, you may use a
13 * newer version instead, at your option.
15 * This software consists of voluntary contributions made by many
16 * individuals. For exact contribution history, see the revision
17 * history and logs, available at http://subversion.tigris.org/.
18 * ====================================================================
23 #include <string.h> /* for memcpy(), memcmp(), strlen() */
24 #include <apr_lib.h> /* for apr_isspace() */
25 #include <apr_fnmatch.h>
26 #include "svn_string.h" /* loads "svn_types.h" and <apr_pools.h> */
27 #include "svn_ctype.h"
31 /* Our own realloc, since APR doesn't have one. Note: this is a
32 generic realloc for memory pools, *not* for strings. */
33 static void *
34 my__realloc(char *data, apr_size_t oldsize, apr_size_t request,
35 apr_pool_t *pool)
37 void *new_area;
39 /* kff todo: it's a pity APR doesn't give us this -- sometimes it
40 could realloc the block merely by extending in place, sparing us
41 a memcpy(), but only the pool would know enough to be able to do
42 this. We should add a realloc() to APR if someone hasn't
43 already. */
45 /* malloc new area */
46 new_area = apr_palloc(pool, request);
48 /* copy data to new area */
49 memcpy(new_area, data, oldsize);
51 /* I'm NOT freeing old area here -- cuz we're using pools, ugh. */
53 /* return new area */
54 return new_area;
57 static APR_INLINE svn_boolean_t
58 string_compare(const char *str1,
59 const char *str2,
60 apr_size_t len1,
61 apr_size_t len2)
63 /* easy way out :) */
64 if (len1 != len2)
65 return FALSE;
67 /* now the strings must have identical lenghths */
69 if ((memcmp(str1, str2, len1)) == 0)
70 return TRUE;
71 else
72 return FALSE;
75 static APR_INLINE apr_size_t
76 string_first_non_whitespace(const char *str, apr_size_t len)
78 apr_size_t i;
80 for (i = 0; i < len; i++)
82 if (! apr_isspace(str[i]))
83 return i;
86 /* if we get here, then the string must be entirely whitespace */
87 return len;
90 static APR_INLINE apr_size_t
91 find_char_backward(const char *str, apr_size_t len, char ch)
93 apr_size_t i = len;
95 while (i != 0)
97 if (str[--i] == ch)
98 return i;
101 /* char was not found, return len */
102 return len;
106 /* svn_string functions */
108 static svn_string_t *
109 create_string(const char *data, apr_size_t size,
110 apr_pool_t *pool)
112 svn_string_t *new_string;
114 new_string = apr_palloc(pool, sizeof(*new_string));
116 new_string->data = data;
117 new_string->len = size;
119 return new_string;
122 svn_string_t *
123 svn_string_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
125 char *data;
127 data = apr_palloc(pool, size + 1);
128 memcpy(data, bytes, size);
130 /* Null termination is the convention -- even if we suspect the data
131 to be binary, it's not up to us to decide, it's the caller's
132 call. Heck, that's why they call it the caller! */
133 data[size] = '\0';
135 /* wrap an svn_string_t around the new data */
136 return create_string(data, size, pool);
140 svn_string_t *
141 svn_string_create(const char *cstring, apr_pool_t *pool)
143 return svn_string_ncreate(cstring, strlen(cstring), pool);
147 svn_string_t *
148 svn_string_create_from_buf(const svn_stringbuf_t *strbuf, apr_pool_t *pool)
150 return svn_string_ncreate(strbuf->data, strbuf->len, pool);
154 svn_string_t *
155 svn_string_createv(apr_pool_t *pool, const char *fmt, va_list ap)
157 char *data = apr_pvsprintf(pool, fmt, ap);
159 /* wrap an svn_string_t around the new data */
160 return create_string(data, strlen(data), pool);
164 svn_string_t *
165 svn_string_createf(apr_pool_t *pool, const char *fmt, ...)
167 svn_string_t *str;
169 va_list ap;
170 va_start(ap, fmt);
171 str = svn_string_createv(pool, fmt, ap);
172 va_end(ap);
174 return str;
178 svn_boolean_t
179 svn_string_isempty(const svn_string_t *str)
181 return (str->len == 0);
185 svn_string_t *
186 svn_string_dup(const svn_string_t *original_string, apr_pool_t *pool)
188 return (svn_string_ncreate(original_string->data,
189 original_string->len, pool));
194 svn_boolean_t
195 svn_string_compare(const svn_string_t *str1, const svn_string_t *str2)
197 return
198 string_compare(str1->data, str2->data, str1->len, str2->len);
203 apr_size_t
204 svn_string_first_non_whitespace(const svn_string_t *str)
206 return
207 string_first_non_whitespace(str->data, str->len);
211 apr_size_t
212 svn_string_find_char_backward(const svn_string_t *str, char ch)
214 return find_char_backward(str->data, str->len, ch);
219 /* svn_stringbuf functions */
221 static svn_stringbuf_t *
222 create_stringbuf(char *data, apr_size_t size, apr_size_t blocksize, apr_pool_t *pool)
224 svn_stringbuf_t *new_string;
226 new_string = apr_palloc(pool, sizeof(*new_string));
228 new_string->data = data;
229 new_string->len = size;
230 new_string->blocksize = blocksize;
231 new_string->pool = pool;
233 return new_string;
236 svn_stringbuf_t *
237 svn_stringbuf_create_ensure(apr_size_t blocksize, apr_pool_t *pool)
239 char *data = apr_palloc(pool, ++blocksize); /* + space for '\0' */
241 data[0] = '\0';
243 /* wrap an svn_stringbuf_t around the new data buffer. */
244 return create_stringbuf(data, 0, blocksize, pool);
247 svn_stringbuf_t *
248 svn_stringbuf_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
250 /* Ensure string buffer of size + 1 */
251 svn_stringbuf_t *strbuf = svn_stringbuf_create_ensure(size, pool);
253 memcpy(strbuf->data, bytes, size);
255 /* Null termination is the convention -- even if we suspect the data
256 to be binary, it's not up to us to decide, it's the caller's
257 call. Heck, that's why they call it the caller! */
258 strbuf->data[size] = '\0';
259 strbuf->len = size;
261 return strbuf;
265 svn_stringbuf_t *
266 svn_stringbuf_create(const char *cstring, apr_pool_t *pool)
268 return svn_stringbuf_ncreate(cstring, strlen(cstring), pool);
272 svn_stringbuf_t *
273 svn_stringbuf_create_from_string(const svn_string_t *str, apr_pool_t *pool)
275 return svn_stringbuf_ncreate(str->data, str->len, pool);
279 svn_stringbuf_t *
280 svn_stringbuf_createv(apr_pool_t *pool, const char *fmt, va_list ap)
282 char *data = apr_pvsprintf(pool, fmt, ap);
283 apr_size_t size = strlen(data);
285 /* wrap an svn_stringbuf_t around the new data */
286 return create_stringbuf(data, size, size + 1, pool);
290 svn_stringbuf_t *
291 svn_stringbuf_createf(apr_pool_t *pool, const char *fmt, ...)
293 svn_stringbuf_t *str;
295 va_list ap;
296 va_start(ap, fmt);
297 str = svn_stringbuf_createv(pool, fmt, ap);
298 va_end(ap);
300 return str;
304 void
305 svn_stringbuf_fillchar(svn_stringbuf_t *str, unsigned char c)
307 memset(str->data, c, str->len);
311 void
312 svn_stringbuf_set(svn_stringbuf_t *str, const char *value)
314 apr_size_t amt = strlen(value);
316 svn_stringbuf_ensure(str, amt + 1);
317 memcpy(str->data, value, amt + 1);
318 str->len = amt;
321 void
322 svn_stringbuf_setempty(svn_stringbuf_t *str)
324 if (str->len > 0)
325 str->data[0] = '\0';
327 str->len = 0;
331 void
332 svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes)
334 if (nbytes > str->len)
335 str->len = 0;
336 else
337 str->len -= nbytes;
339 str->data[str->len] = '\0';
343 svn_boolean_t
344 svn_stringbuf_isempty(const svn_stringbuf_t *str)
346 return (str->len == 0);
350 void
351 svn_stringbuf_ensure(svn_stringbuf_t *str, apr_size_t minimum_size)
353 /* Keep doubling capacity until have enough. */
354 if (str->blocksize < minimum_size)
356 if (str->blocksize == 0)
357 str->blocksize = minimum_size;
358 else
359 while (str->blocksize < minimum_size)
361 apr_size_t prev_size = str->blocksize;
362 str->blocksize *= 2;
363 /* check for apr_size_t overflow */
364 if (prev_size > str->blocksize)
366 str->blocksize = minimum_size;
367 break;
371 str->data = (char *) my__realloc(str->data,
372 str->len + 1,
373 /* We need to maintain (and thus copy)
374 the trailing nul */
375 str->blocksize,
376 str->pool);
381 void
382 svn_stringbuf_appendbytes(svn_stringbuf_t *str, const char *bytes,
383 apr_size_t count)
385 apr_size_t total_len;
386 void *start_address;
388 total_len = str->len + count; /* total size needed */
390 /* +1 for null terminator. */
391 svn_stringbuf_ensure(str, (total_len + 1));
393 /* get address 1 byte beyond end of original bytestring */
394 start_address = (str->data + str->len);
396 memcpy(start_address, bytes, count);
397 str->len = total_len;
399 str->data[str->len] = '\0'; /* We don't know if this is binary
400 data or not, but convention is
401 to null-terminate. */
405 void
406 svn_stringbuf_appendstr(svn_stringbuf_t *targetstr,
407 const svn_stringbuf_t *appendstr)
409 svn_stringbuf_appendbytes(targetstr, appendstr->data, appendstr->len);
413 void
414 svn_stringbuf_appendcstr(svn_stringbuf_t *targetstr, const char *cstr)
416 svn_stringbuf_appendbytes(targetstr, cstr, strlen(cstr));
420 svn_stringbuf_t *
421 svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool)
423 return (svn_stringbuf_ncreate(original_string->data,
424 original_string->len, pool));
429 svn_boolean_t
430 svn_stringbuf_compare(const svn_stringbuf_t *str1,
431 const svn_stringbuf_t *str2)
433 return string_compare(str1->data, str2->data, str1->len, str2->len);
438 apr_size_t
439 svn_stringbuf_first_non_whitespace(const svn_stringbuf_t *str)
441 return string_first_non_whitespace(str->data, str->len);
445 void
446 svn_stringbuf_strip_whitespace(svn_stringbuf_t *str)
448 /* Find first non-whitespace character */
449 apr_size_t offset = svn_stringbuf_first_non_whitespace(str);
451 /* Go ahead! Waste some RAM, we've got pools! :) */
452 str->data += offset;
453 str->len -= offset;
454 str->blocksize -= offset;
456 /* Now that we've trimmed the front, trim the end, wasting more RAM. */
457 while ((str->len > 0) && apr_isspace(str->data[str->len - 1]))
458 str->len--;
459 str->data[str->len] = '\0';
463 apr_size_t
464 svn_stringbuf_find_char_backward(const svn_stringbuf_t *str, char ch)
466 return find_char_backward(str->data, str->len, ch);
470 svn_boolean_t
471 svn_string_compare_stringbuf(const svn_string_t *str1,
472 const svn_stringbuf_t *str2)
474 return string_compare(str1->data, str2->data, str1->len, str2->len);
479 /*** C string stuff. ***/
481 void
482 svn_cstring_split_append(apr_array_header_t *array,
483 const char *input,
484 const char *sep_chars,
485 svn_boolean_t chop_whitespace,
486 apr_pool_t *pool)
488 char *last;
489 char *pats;
490 char *p;
492 pats = apr_pstrdup(pool, input); /* strtok wants non-const data */
493 p = apr_strtok(pats, sep_chars, &last);
495 while (p)
497 if (chop_whitespace)
499 while (apr_isspace(*p))
500 p++;
503 char *e = p + (strlen(p) - 1);
504 while ((e >= p) && (apr_isspace(*e)))
505 e--;
506 *(++e) = '\0';
510 if (p[0] != '\0')
511 APR_ARRAY_PUSH(array, const char *) = p;
513 p = apr_strtok(NULL, sep_chars, &last);
516 return;
520 apr_array_header_t *
521 svn_cstring_split(const char *input,
522 const char *sep_chars,
523 svn_boolean_t chop_whitespace,
524 apr_pool_t *pool)
526 apr_array_header_t *a = apr_array_make(pool, 5, sizeof(input));
527 svn_cstring_split_append(a, input, sep_chars, chop_whitespace, pool);
528 return a;
532 svn_boolean_t svn_cstring_match_glob_list(const char *str,
533 apr_array_header_t *list)
535 int i;
537 for (i = 0; i < list->nelts; i++)
539 const char *this_pattern = APR_ARRAY_IDX(list, i, char *);
541 if (apr_fnmatch(this_pattern, str, 0) == APR_SUCCESS)
542 return TRUE;
545 return FALSE;
548 int svn_cstring_count_newlines(const char *msg)
550 int count = 0;
551 const char *p;
553 for (p = msg; *p; p++)
555 if (*p == '\n')
557 count++;
558 if (*(p + 1) == '\r')
559 p++;
561 else if (*p == '\r')
563 count++;
564 if (*(p + 1) == '\n')
565 p++;
569 return count;
572 char *
573 svn_cstring_join(const apr_array_header_t *strings,
574 const char *separator,
575 apr_pool_t *pool)
577 svn_stringbuf_t *new_str = svn_stringbuf_create("", pool);
578 int sep_len = strlen(separator);
579 int i;
581 for (i = 0; i < strings->nelts; i++)
583 const char *string = APR_ARRAY_IDX(strings, i, const char *);
584 svn_stringbuf_appendbytes(new_str, string, strlen(string));
585 svn_stringbuf_appendbytes(new_str, separator, sep_len);
587 return new_str->data;
591 svn_cstring_casecmp(const char *str1, const char *str2)
593 for (;;)
595 const int a = *str1++;
596 const int b = *str2++;
597 const int cmp = svn_ctype_casecmp(a, b);
598 if (cmp || !a || !b)
599 return cmp;