Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hash value of String that would be stable across iOS releases?

In documentation String.hash for iOS it says:

You should not rely on this property having the same hash value across releases of OS X.

(strange why they speak of OS X in iOS documentation)

Well, I need a hasshing function that will not change with iOS releases. It can be simple I do not need anything like SHA. Is there some library for that?

There is another question about this here but the accepted (and only) answer there simply states that we should respect the note in documentation.

like image 599
Rasto Avatar asked Mar 09 '16 03:03

Rasto


People also ask

What is swift hash?

In Swift, a Hashable is a protocol that provides a hashValue to our object. The hashValue is used to compare two instances. To use the hashValue , we first have to conform (associate) the type (struct, class, etc) to Hashable property.

How do you hash a string in Java?

The hashCode() method returns the hash code of a string. where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation.

Is string a collection in Swift?

A string is a series of characters, such as "Swift" , that forms a collection. Strings in Swift are Unicode correct and locale insensitive, and are designed to be efficient.

How do I print a character in Swift?

The backslash character \ acts as an escape character when used in a string. This means you can use, for example, double quotes, in a string by pre-pending them with \ . The same also applies for the backslash character itself, which is to say that println("\\") will result in just \ being printed.


1 Answers

Here is a non-crypto hash, for Swift 3:

 func strHash(_ str: String) -> UInt64 {
    var result = UInt64 (5381)
    let buf = [UInt8](str.utf8)
    for b in buf {
        result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
    }
    return result
 }

It was derived somewhat from a C++11 constexpr

    constexpr uint64_t str2int(char const *input) {
    return *input                      // test for null terminator
    ? (static_cast<uint64_t>(*input) + // add char to end
       127 * ((str2int(input + 1)      // prime 127 shifts left almost 7 bits
               & 0x00ffffffffffffff))) // mask right 56 bits
    : 5381;                            // start with prime number 5381
}

Unfortunately, the two don't yield the same hash. To do that you'd need to reverse the iterator order in strHash:

for b in buf.reversed() {...}

But that will run 13x slower, somewhat comparable to the djb2hash String extension that I got from https://useyourloaf.com/blog/swift-hashable/

Here are some benchmarks, for a million iterations:

hashValue execution time: 0.147760987281799
strHash execution time:   1.45974600315094
strHashReversed time:    18.7755110263824
djb2hash execution time: 16.0091370344162
sdbmhash crashed

For C++, the str2Int is roughly as fast as Swift 3's hashValue:

str2int execution time: 0.136421
like image 89
Warren Stringer Avatar answered Sep 26 '22 03:09

Warren Stringer