I am creating an iOS version of an existing Android app. On the Android side, hashCode() of a String (username) is sent to the server and based on that hash, a JSON object is returned.
On Swift, I tried hash and hashValue properties but both of them produces values that are different from their Android counterpart.
So I decided to write my own implementation based on Java's implementation:
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
But when I write the above implementation in Swift, I get overflow crash. Can anybody help me here?
Thanks in advance.
Here is the Swift implementation:
I first had to write a Character extension that would return Ascii value of the character:
extension Character {
var asciiValue: UInt32? {
return String(self).unicodeScalars.filter{$0.isASCII}.first?.value
}
}
Then I created a String extension with: 1. a property that returns Ascii values of each character in the String. 2. a hash method to return the hash (copying the Java code)
extension String {
var asciiArray: [UInt32] {
return unicodeScalars.filter{$0.isASCII}.map{$0.value}
}
func myHash() -> Int {
var h = 0 as Int!
for i in 0..<asciiArray.count {
h = 31*h! + Int(array[i])
}
return h!
}
}
As the post is still missing an answer, here is the working code:
1) Write an extension for Characters, to map their ascii representation to an int - we need UInt32, as Java uses for the hashing a 32 bit system, not 64 bit.
2) Make sure our represented string does ONLY contain characters, which are mappable to ASCII
3) Now perform the mentioned hashing function
int h = 0;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
So, we will get the following code snippet, which could be used in your projects.
// 1) Here is our Character extension
extension Character {
var asciiValue: UInt32? {
return String(self).unicodeScalars.filter{$0.isASCII}.first?.value
}
}
extension String {
// 2) ascii array to map our string
var asciiArray: [UInt32] {
return unicodeScalars.filter{$0.isASCII}.map{$0.value}
}
// this is our hashCode function, which produces equal output to the Java or Android hash function
func hashCode() -> Int32 {
var h : Int32 = 0
for i in self.asciiArray {
h = 31 &* h &+ Int32(i) // Be aware of overflow operators,
}
return h
}
}
By default, swift throws an exception on integer overflow (unlike C or the standard Java integer operations). In order to preclude throwing the exception you have to use the special functions provided for that, like 'addWithOverflow'.
Alternatively you can build using the
-Ounchecked flag
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With