95
96
svn_stringbuf_t *buf;
97
98
apr_size_t len, keylen, vallen;
98
char c, *end, *keybuf, *valbuf;
99
char c, *keybuf, *valbuf;
99
100
apr_pool_t *iterpool = svn_pool_create(pool);
103
107
svn_pool_clear(iterpool);
105
109
/* Read a key length line. Might be END, though. */
118
122
if ((buf->len >= 3) && (buf->data[0] == 'K') && (buf->data[1] == ' '))
120
124
/* Get the length of the key */
121
keylen = (size_t) strtoul(buf->data + 2, &end, 10);
122
if (keylen == (size_t) ULONG_MAX || *end != '\0')
123
return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
125
err = svn_cstring_strtoui64(&ui64, buf->data + 2,
126
0, APR_SIZE_MAX, 10);
128
return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
124
129
_("Serialized hash malformed"));
130
keylen = (apr_size_t)ui64;
126
132
/* Now read that much into a buffer. */
127
133
keybuf = apr_palloc(pool, keylen + 1);
141
147
if ((buf->data[0] == 'V') && (buf->data[1] == ' '))
143
vallen = (size_t) strtoul(buf->data + 2, &end, 10);
144
if (vallen == (size_t) ULONG_MAX || *end != '\0')
145
return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
149
err = svn_cstring_strtoui64(&ui64, buf->data + 2,
150
0, APR_SIZE_MAX, 10);
152
return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
146
153
_("Serialized hash malformed"));
154
vallen = (apr_size_t)ui64;
148
156
valbuf = apr_palloc(iterpool, vallen + 1);
149
157
SVN_ERR(svn_stream_read(stream, valbuf, &vallen));
168
176
&& (buf->data[0] == 'D') && (buf->data[1] == ' '))
170
178
/* Get the length of the key */
171
keylen = (size_t) strtoul(buf->data + 2, &end, 10);
172
if (keylen == (size_t) ULONG_MAX || *end != '\0')
173
return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
179
err = svn_cstring_strtoui64(&ui64, buf->data + 2,
180
0, APR_SIZE_MAX, 10);
182
return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
174
183
_("Serialized hash malformed"));
184
keylen = (apr_size_t)ui64;
176
186
/* Now read that much into a buffer. */
177
187
keybuf = apr_palloc(iterpool, keylen + 1);
243
return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
244
_("Cannot serialize negative length"));
232
246
/* Write it out. */
233
247
SVN_ERR(svn_stream_printf(stream, subpool,
234
"K %" APR_SSIZE_T_FMT "\n%s\n"
248
"K %" APR_SIZE_T_FMT "\n%s\n"
235
249
"V %" APR_SIZE_T_FMT "\n",
236
item->klen, (const char *) item->key,
250
(apr_size_t) item->klen,
251
(const char *) item->key,
238
253
len = valstr->len;
239
254
SVN_ERR(svn_stream_write(stream, valstr->data, &len));
240
SVN_ERR(svn_stream_printf(stream, subpool, "\n"));
255
SVN_ERR(svn_stream_puts(stream, "\n"));
495
510
apr_pool_t *pool)
498
apr_hash_t *hash = apr_hash_make(pool);
513
apr_hash_t *hash = svn_hash__make(pool);
499
514
for (i = 0; i < keys->nelts; i++)
501
516
const char *key =
502
517
apr_pstrdup(pool, APR_ARRAY_IDX(keys, i, const char *));
503
apr_hash_set(hash, key, APR_HASH_KEY_STRING, key);
518
svn_hash_sets(hash, key, key);
506
521
return SVN_NO_ERROR;
511
svn_hash__clear(apr_hash_t *hash, apr_pool_t *pool)
525
#if !APR_VERSION_AT_LEAST(1, 3, 0)
527
svn_hash__clear(apr_hash_t *hash)
513
#if APR_VERSION_AT_LEAST(1, 3, 0)
514
apr_hash_clear(hash);
516
529
apr_hash_index_t *hi;
518
531
apr_ssize_t klen;
520
for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
533
for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi))
522
535
apr_hash_this(hi, &key, &klen, NULL);
523
536
apr_hash_set(hash, key, klen, NULL);
540
const char *value = apr_hash_get(hash, key, APR_HASH_KEY_STRING);
552
const char *value = svn_hash_gets(hash, key);
541
553
return value ? value : default_value;
560
572
return default_value;
577
/*** Optimized hash function ***/
579
/* Optimized version of apr_hashfunc_default in APR 1.4.5 and earlier.
580
* It assumes that the CPU has 32-bit multiplications with high throughput
581
* of at least 1 operation every 3 cycles. Latency is not an issue. Another
582
* optimization is a mildly unrolled main loop and breaking the dependency
583
* chain within the loop.
585
* Note that most CPUs including Intel Atom, VIA Nano, ARM feature the
586
* assumed pipelined multiplication circuitry. They can do one MUL every
587
* or every other cycle.
589
* The performance is ultimately limited by the fact that most CPUs can
590
* do only one LOAD and only one BRANCH operation per cycle. The best we
591
* can do is to process one character per cycle - provided the processor
592
* is wide enough to do 1 LOAD, COMPARE, BRANCH, MUL and ADD per cycle.
595
hashfunc_compatible(const char *char_key, apr_ssize_t *klen)
597
unsigned int hash = 0;
598
const unsigned char *key = (const unsigned char *)char_key;
599
const unsigned char *p;
602
if (*klen == APR_HASH_KEY_STRING)
604
for (p = key; ; p+=4)
606
unsigned int new_hash = hash * 33 * 33 * 33 * 33;
608
new_hash += p[0] * 33 * 33 * 33;
610
new_hash += p[1] * 33 * 33;
612
new_hash += p[2] * 33;
614
hash = new_hash + p[3];
617
hash = hash * 33 + *p;
623
for (p = key, i = *klen; i >= 4; i-=4, p+=4)
625
hash = hash * 33 * 33 * 33 * 33
626
+ p[0] * 33 * 33 * 33
632
hash = hash * 33 + *p;
639
svn_hash__make(apr_pool_t *pool)
641
return apr_hash_make_custom(pool, hashfunc_compatible);