53
54
/* apr_palloc will allocate multiples of 8.
54
55
* Thus, we would waste some of that memory if we stuck to the
55
56
* smaller size. Note that this is safe even if apr_palloc would
56
* use some other aligment or none at all. */
57
* use some other alignment or none at all. */
57
58
minimum_size = APR_ALIGN_DEFAULT(minimum_size);
58
*data = (!minimum_size ? NULL : apr_palloc(pool, minimum_size));
59
*data = apr_palloc(pool, minimum_size);
59
60
*size = minimum_size;
78
79
apr_size_t new_size = *size;
81
/* APR will increase odd allocation sizes to the next
82
* multiple for 8, for instance. Take advantage of that
83
* knowledge and allow for the extra size to be used. */
84
82
new_size = minimum_size;
86
84
while (new_size < minimum_size)
88
/* new_size is aligned; doubling it should keep it aligned */
89
86
const apr_size_t prev_size = new_size;
121
118
const apr_size_t old_size = membuf->size;
123
120
membuf_ensure(&membuf->data, &membuf->size, size, membuf->pool);
124
if (membuf->data && old_data && old_data != membuf->data)
122
/* If we re-allocated MEMBUF->DATA, it cannot be NULL.
123
* Statically initialized membuffers (OLD_DATA) may be NULL, though. */
124
if (old_data && old_data != membuf->data)
125
125
memcpy(membuf->data, old_data, old_size);
240
240
new_string->data = data;
241
241
new_string->len = size;
243
memcpy(data, bytes, size);
243
/* If SIZE is 0, NULL is valid for BYTES. */
245
memcpy(data, bytes, size);
245
247
/* Null termination is the convention -- even if we suspect the data
246
248
to be binary, it's not up to us to decide, it's the caller's
300
302
svn_string_dup(const svn_string_t *original_string, apr_pool_t *pool)
302
return (svn_string_ncreate(original_string->data,
303
original_string->len, pool));
304
return (original_string ? svn_string_ncreate(original_string->data,
305
original_string->len, pool)
393
396
svn_stringbuf_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
395
398
svn_stringbuf_t *strbuf = svn_stringbuf_create_ensure(size, pool);
396
memcpy(strbuf->data, bytes, size);
400
/* If SIZE is 0, NULL is valid for BYTES. */
402
memcpy(strbuf->data, bytes, size);
398
404
/* Null termination is the convention -- even if we suspect the data
399
405
to be binary, it's not up to us to decide, it's the caller's
418
424
return svn_stringbuf_ncreate(str->data, str->len, pool);
428
svn_stringbuf_create_wrap(char *str, apr_pool_t *pool)
430
svn_stringbuf_t *result = apr_palloc(pool, sizeof(*result));
433
result->len = strlen(str);
434
result->blocksize = result->len + 1;
422
439
svn_stringbuf_t *
423
440
svn_stringbuf_createv(apr_pool_t *pool, const char *fmt, va_list ap)
595
616
to null-terminate. */
620
svn_stringbuf_appendfill(svn_stringbuf_t *str,
624
apr_size_t new_len = str->len + count;
625
svn_stringbuf_ensure(str, new_len);
627
memset(str->data + str->len, byte, count);
629
/* update buffer length and always NUL-terminate it */
631
str->data[new_len] = '\0';
600
636
svn_stringbuf_appendstr(svn_stringbuf_t *targetstr,
616
652
const char *bytes,
617
653
apr_size_t count)
655
/* For COUNT==0, we allow BYTES to be NULL. It's a no-op in that case. */
659
/* special case: BYTES overlaps with this string -> copy the source */
619
660
if (bytes + count > str->data && bytes < str->data + str->blocksize)
621
/* special case: BYTES overlaps with this string -> copy the source */
622
const char *temp = apr_pmemdup(str->pool, bytes, count);
623
svn_stringbuf_insert(str, pos, temp, count);
630
svn_stringbuf_ensure(str, str->len + count);
631
memmove(str->data + pos + count, str->data + pos, str->len - pos + 1);
632
memcpy(str->data + pos, bytes, count);
661
bytes = apr_pmemdup(str->pool, bytes, count);
666
svn_stringbuf_ensure(str, str->len + count);
667
memmove(str->data + pos + count, str->data + pos, str->len - pos + 1);
668
memcpy(str->data + pos, bytes, count);
656
691
const char *bytes,
657
692
apr_size_t new_count)
694
/* For COUNT==0, we allow BYTES to be NULL.
695
* In that case, this is just a substring removal. */
698
svn_stringbuf_remove(str, pos, old_count);
702
/* special case: BYTES overlaps with this string -> copy the source */
659
703
if (bytes + new_count > str->data && bytes < str->data + str->blocksize)
661
/* special case: BYTES overlaps with this string -> copy the source */
662
const char *temp = apr_pmemdup(str->pool, bytes, new_count);
663
svn_stringbuf_replace(str, pos, old_count, temp, new_count);
669
if (pos + old_count > str->len)
670
old_count = str->len - pos;
672
if (old_count < new_count)
674
apr_size_t delta = new_count - old_count;
675
svn_stringbuf_ensure(str, str->len + delta);
678
if (old_count != new_count)
679
memmove(str->data + pos + new_count, str->data + pos + old_count,
680
str->len - pos - old_count + 1);
682
memcpy(str->data + pos, bytes, new_count);
683
str->len += new_count - old_count;
704
bytes = apr_pmemdup(str->pool, bytes, new_count);
708
if (pos + old_count > str->len)
709
old_count = str->len - pos;
711
if (old_count < new_count)
713
apr_size_t delta = new_count - old_count;
714
svn_stringbuf_ensure(str, str->len + delta);
717
if (old_count != new_count)
718
memmove(str->data + pos + new_count, str->data + pos + old_count,
719
str->len - pos - old_count + 1);
721
memcpy(str->data + pos, bytes, new_count);
722
str->len += new_count - old_count;
1014
1052
return SVN_NO_ERROR;
1019
svn__strtoff(apr_off_t *offset, const char *buf, char **end, int base)
1056
svn__strtoul(const char* buffer, const char** end)
1021
#if !APR_VERSION_AT_LEAST(1,0,0)
1023
*offset = strtol(buf, end, base);
1024
return APR_FROM_OS_ERROR(errno);
1026
return apr_strtoff(offset, buf, end, base);
1058
unsigned long result = 0;
1060
/* this loop will execute in just 2 CPU cycles, confirmed by measurement:
1061
7 macro-ops (max 4 / cycle => 2 cycles)
1062
1 load (max 1 / cycle)
1063
1 jumps (compare + conditional jump == 1 macro op; max 1 / cycle)
1064
2 arithmetic ops (subtract, increment; max 3 / cycle)
1065
2 scale-and-add AGU ops (max 3 / cycle)
1066
1 compiler-generated move operation
1067
dependency chain: temp = result * 4 + result; result = temp * 2 + c
1068
(2 ops with latency 1 => 2 cycles)
1072
unsigned long c = (unsigned char)*buffer - (unsigned char)'0';
1076
result = result * 10 + c;
1030
1084
/* "Precalculated" itoa values for 2 places (including leading zeros).
1123
1177
return svn__ui64toa(dest, (apr_uint64_t)number);
1126
return svn__ui64toa(dest + 1, (apr_uint64_t)(0-number)) + 1;
1180
return svn__ui64toa(dest + 1, 0 - (apr_uint64_t)number) + 1;
1130
ui64toa_sep(apr_uint64_t number, char seperator, char *buffer)
1184
ui64toa_sep(apr_uint64_t number, char separator, char *buffer)
1132
1186
apr_size_t length = svn__ui64toa(buffer, number);
1146
svn__ui64toa_sep(apr_uint64_t number, char seperator, apr_pool_t *pool)
1200
svn__ui64toa_sep(apr_uint64_t number, char separator, apr_pool_t *pool)
1148
1202
char buffer[2 * SVN_INT64_BUFFER_SIZE];
1149
ui64toa_sep(number, seperator, buffer);
1203
ui64toa_sep(number, separator, buffer);
1151
1205
return apr_pstrdup(pool, buffer);
1155
svn__i64toa_sep(apr_int64_t number, char seperator, apr_pool_t *pool)
1209
svn__i64toa_sep(apr_int64_t number, char separator, apr_pool_t *pool)
1157
1211
char buffer[2 * SVN_INT64_BUFFER_SIZE];
1158
1212
if (number < 0)
1160
1214
buffer[0] = '-';
1161
ui64toa_sep((apr_uint64_t)(-number), seperator, &buffer[1]);
1215
ui64toa_sep((apr_uint64_t)(-number), separator, &buffer[1]);
1164
ui64toa_sep((apr_uint64_t)(number), seperator, buffer);
1218
ui64toa_sep((apr_uint64_t)(number), separator, buffer);
1166
1220
return apr_pstrdup(pool, buffer);
1224
svn__ui64tobase36(char *dest, apr_uint64_t value)
1226
char *dest_start = dest;
1229
/* pretty frequent and trivial case. Make it fast. */
1230
*(dest++) = (char)(value) + '0';
1234
char buffer[SVN_INT64_BUFFER_SIZE];
1237
/* write result as little-endian to buffer */
1240
char c = (char)(value % 36);
1243
*p = (c <= 9) ? (c + '0') : (c - 10 + 'a');
1247
/* copy as big-endian to DEST */
1253
return dest - dest_start;
1257
svn__base36toui64(const char **next, const char *source)
1259
apr_uint64_t result = 0;
1260
apr_uint64_t factor = 1;
1262
char digits[SVN_INT64_BUFFER_SIZE];
1264
/* convert digits to numerical values and count the number of places.
1265
* Also, prevent buffer overflow. */
1266
while (i < sizeof(digits))
1271
/* includes detection of NUL terminator */
1272
if (c < '0' || c > '9')
1279
if (c < 'a' || c > 'z')
1289
/* fold digits into the result */
1292
result += factor * (apr_uint64_t)digits[--i];
1170
1304
svn_cstring__similarity(const char *stra, const char *strb,
1171
1305
svn_membuf_t *buffer, apr_size_t *rlcs)
1178
1312
return svn_string__similarity(&stringa, &stringb, buffer, rlcs);
1182
1316
svn_string__similarity(const svn_string_t *stringa,
1183
1317
const svn_string_t *stringb,
1184
1318
svn_membuf_t *buffer, apr_size_t *rlcs)
1268
1402
/* Return similarity ratio rounded to 4 significant digits */
1270
return(unsigned int)((2000 * lcs + total/2) / total);
1404
return ((2 * SVN_STRING__SIM_RANGE_MAX * lcs + total/2) / total);
1406
return SVN_STRING__SIM_RANGE_MAX;
1410
svn_cstring__match_length(const char *a,
1416
#if SVN_UNALIGNED_ACCESS_IS_OK
1418
/* Chunky processing is so much faster ...
1420
* We can't make this work on architectures that require aligned access
1421
* because A and B will probably have different alignment. So, skipping
1422
* the first few chars until alignment is reached is not an option.
1424
for (; pos + sizeof(apr_size_t) <= max_len; pos += sizeof(apr_size_t))
1425
if (*(const apr_size_t*)(a + pos) != *(const apr_size_t*)(b + pos))
1430
for (; pos < max_len; ++pos)
1431
if (a[pos] != b[pos])
1438
svn_cstring__reverse_match_length(const char *a,
1444
#if SVN_UNALIGNED_ACCESS_IS_OK
1446
/* Chunky processing is so much faster ...
1448
* We can't make this work on architectures that require aligned access
1449
* because A and B will probably have different alignment. So, skipping
1450
* the first few chars until alignment is reached is not an option.
1452
for (pos = sizeof(apr_size_t); pos <= max_len; pos += sizeof(apr_size_t))
1453
if (*(const apr_size_t*)(a - pos) != *(const apr_size_t*)(b - pos))
1456
pos -= sizeof(apr_size_t);
1460
/* If we find a mismatch at -pos, pos-1 characters matched.
1462
while (++pos <= max_len)
1463
if (a[0-pos] != b[0-pos])
1466
/* No mismatch found -> at least MAX_LEN matching chars.
1472
svn_cstring_skip_prefix(const char *str, const char *prefix)
1474
apr_size_t len = strlen(prefix);
1476
if (strncmp(str, prefix, len) == 0)