20
20
*
21
21
*/
22
22
23
+ #include <limits.h>
24
+ #include <assert.h>
23
25
#include "xinclude.h"
24
26
25
27
@@ -276,6 +278,109 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
276
278
return ha ;
277
279
}
278
280
281
+ #ifdef XDL_FAST_HASH
282
+
283
+ #define ONEBYTES 0x0101010101010101ul
284
+ #define NEWLINEBYTES 0x0a0a0a0a0a0a0a0aul
285
+ #define HIGHBITS 0x8080808080808080ul
286
+
287
+ /* Return the high bit set in the first byte that is a zero */
288
+ static inline unsigned long has_zero (unsigned long a )
289
+ {
290
+ return ((a - ONEBYTES ) & ~a ) & HIGHBITS ;
291
+ }
292
+
293
+ static inline long count_masked_bytes (unsigned long mask )
294
+ {
295
+ if (sizeof (long ) == 8 ) {
296
+ /*
297
+ * Jan Achrenius on G+: microoptimized version of
298
+ * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
299
+ * that works for the bytemasks without having to
300
+ * mask them first.
301
+ */
302
+ return mask * 0x0001020304050608 >> 56 ;
303
+ } else {
304
+ /*
305
+ * Modified Carl Chatfield G+ version for 32-bit *
306
+ *
307
+ * (a) gives us
308
+ * -1 (0, ff), 0 (ffff) or 1 (ffffff)
309
+ * (b) gives us
310
+ * 0 for 0, 1 for (ff ffff ffffff)
311
+ * (a+b+1) gives us
312
+ * correct 0-3 bytemask count result
313
+ */
314
+ long a = (mask - 256 ) >> 23 ;
315
+ long b = mask & 1 ;
316
+ return a + b + 1 ;
317
+ }
318
+ }
319
+
320
+ unsigned long xdl_hash_record (char const * * data , char const * top , long flags )
321
+ {
322
+ unsigned long hash = 5381 ;
323
+ unsigned long a = 0 , mask = 0 ;
324
+ char const * ptr = * data ;
325
+ char const * end = top - sizeof (unsigned long ) + 1 ;
326
+
327
+ if (flags & XDF_WHITESPACE_FLAGS )
328
+ return xdl_hash_record_with_whitespace (data , top , flags );
329
+
330
+ ptr -= sizeof (unsigned long );
331
+ do {
332
+ hash += hash << 5 ;
333
+ hash ^= a ;
334
+ ptr += sizeof (unsigned long );
335
+ if (ptr >= end )
336
+ break ;
337
+ a = * (unsigned long * )ptr ;
338
+ /* Do we have any '\n' bytes in this word? */
339
+ mask = has_zero (a ^ NEWLINEBYTES );
340
+ } while (!mask );
341
+
342
+ if (ptr >= end ) {
343
+ /*
344
+ * There is only a partial word left at the end of the
345
+ * buffer. Because we may work with a memory mapping,
346
+ * we have to grab the rest byte by byte instead of
347
+ * blindly reading it.
348
+ *
349
+ * To avoid problems with masking in a signed value,
350
+ * we use an unsigned char here.
351
+ */
352
+ const char * p ;
353
+ for (p = top - 1 ; p >= ptr ; p -- )
354
+ a = (a << 8 ) + * ((const unsigned char * )p );
355
+ mask = has_zero (a ^ NEWLINEBYTES );
356
+ if (!mask )
357
+ /*
358
+ * No '\n' found in the partial word. Make a
359
+ * mask that matches what we read.
360
+ */
361
+ mask = 1UL << (8 * (top - ptr ) + 7 );
362
+ }
363
+
364
+ /* The mask *below* the first high bit set */
365
+ mask = (mask - 1 ) & ~mask ;
366
+ mask >>= 7 ;
367
+ hash += hash << 5 ;
368
+ hash ^= a & mask ;
369
+
370
+ /* Advance past the last (possibly partial) word */
371
+ ptr += count_masked_bytes (mask );
372
+
373
+ if (ptr < top ) {
374
+ assert (* ptr == '\n' );
375
+ ptr ++ ;
376
+ }
377
+
378
+ * data = ptr ;
379
+
380
+ return hash ;
381
+ }
382
+
383
+ #else /* XDL_FAST_HASH */
279
384
280
385
unsigned long xdl_hash_record (char const * * data , char const * top , long flags ) {
281
386
unsigned long ha = 5381 ;
@@ -293,6 +398,7 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
293
398
return ha ;
294
399
}
295
400
401
+ #endif /* XDL_FAST_HASH */
296
402
297
403
unsigned int xdl_hashbits (unsigned int size ) {
298
404
unsigned int val = 1 , bits = 0 ;
0 commit comments