@@ -379,7 +379,153 @@ - (XMPPJID *)jidWithNewResource:(NSString *)newResource
379
379
380
380
- (NSUInteger )hash
381
381
{
382
- return [[self full ] hash ];
382
+ // We used to do this:
383
+ // return [[self full] hash];
384
+ //
385
+ // It was functional but less than optimal because it required the creation of a new NSString everytime.
386
+ // Now the hashing of a string itself is extremely fast,
387
+ // so combining 3 hashes is much faster than creating a new string.
388
+ // To accomplish this we use the murmur hashing algorithm.
389
+ //
390
+ // MurmurHash2 was written by Austin Appleby, and is placed in the public domain.
391
+ // http://code.google.com/p/smhasher
392
+
393
+ NSUInteger uhash = [user hash ];
394
+ NSUInteger dhash = [domain hash ];
395
+ NSUInteger rhash = [resource hash ];
396
+
397
+ if (NSUIntegerMax == UINT32_MAX) // Should be optimized out via compiler since these are constants
398
+ {
399
+ // MurmurHash2 (32-bit)
400
+ //
401
+ // uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
402
+ //
403
+ // Normally one would pass a chunk of data ('key') and associated data chunk length ('len').
404
+ // Instead we're going to use our 3 hashes.
405
+ // And we're going to randomly make up a 'seed'.
406
+
407
+ const uint32_t seed = 0xa2f1b6f ; // Some random value I made up
408
+ const uint32_t len = 12 ; // 3 hashes, each 4 bytes = 12 bytes
409
+
410
+ // 'm' and 'r' are mixing constants generated offline.
411
+ // They're not really 'magic', they just happen to work well.
412
+
413
+ const uint32_t m = 0x5bd1e995 ;
414
+ const int r = 24 ;
415
+
416
+ // Initialize the hash to a 'random' value
417
+
418
+ uint32_t h = seed ^ len;
419
+ uint32_t k;
420
+
421
+ // Mix uhash
422
+
423
+ k = uhash;
424
+
425
+ k *= m;
426
+ k ^= k >> r;
427
+ k *= m;
428
+
429
+ h *= m;
430
+ h ^= k;
431
+
432
+ // Mix dhash
433
+
434
+ k = dhash;
435
+
436
+ k *= m;
437
+ k ^= k >> r;
438
+ k *= m;
439
+
440
+ h *= m;
441
+ h ^= k;
442
+
443
+ // Mix rhash
444
+
445
+ k = rhash;
446
+
447
+ k *= m;
448
+ k ^= k >> r;
449
+ k *= m;
450
+
451
+ h *= m;
452
+ h ^= k;
453
+
454
+ // Do a few final mixes of the hash to ensure the last few
455
+ // bytes are well-incorporated.
456
+
457
+ h ^= h >> 13 ;
458
+ h *= m;
459
+ h ^= h >> 15 ;
460
+
461
+ return (NSUInteger )h;
462
+ }
463
+ else
464
+ {
465
+ // MurmurHash2 (64-bit)
466
+ //
467
+ // uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed )
468
+ //
469
+ // Normally one would pass a chunk of data ('key') and associated data chunk length ('len').
470
+ // Instead we're going to use our 3 hashes.
471
+ // And we're going to randomly make up a 'seed'.
472
+
473
+ const uint32_t seed = 0xa2f1b6f ; // Some random value I made up
474
+ const uint32_t len = 24 ; // 3 hashes, each 8 bytes = 24 bytes
475
+
476
+ // 'm' and 'r' are mixing constants generated offline.
477
+ // They're not really 'magic', they just happen to work well.
478
+
479
+ const uint64_t m = 0xc6a4a7935bd1e995LLU;
480
+ const int r = 47 ;
481
+
482
+ // Initialize the hash to a 'random' value
483
+
484
+ uint64_t h = seed ^ (len * m);
485
+ uint64_t k;
486
+
487
+ // Mix uhash
488
+
489
+ k = uhash;
490
+
491
+ k *= m;
492
+ k ^= k >> r;
493
+ k *= m;
494
+
495
+ h ^= k;
496
+ h *= m;
497
+
498
+ // Mix dhash
499
+
500
+ k = dhash;
501
+
502
+ k *= m;
503
+ k ^= k >> r;
504
+ k *= m;
505
+
506
+ h ^= k;
507
+ h *= m;
508
+
509
+ // Mix rhash
510
+
511
+ k = rhash;
512
+
513
+ k *= m;
514
+ k ^= k >> r;
515
+ k *= m;
516
+
517
+ h ^= k;
518
+ h *= m;
519
+
520
+ // Do a few final mixes of the hash to ensure the last few
521
+ // bytes are well-incorporated.
522
+
523
+ h ^= h >> r;
524
+ h *= m;
525
+ h ^= h >> r;
526
+
527
+ return (NSUInteger )h;
528
+ }
383
529
}
384
530
385
531
- (BOOL )isEqual : (id )anObject
0 commit comments