Просмотр исходного кода

Merge pull request #406 from nextgenappsllc/hex_string_to_bytes

Faster Array(hex:)
Marcin Krzyzanowski 8 лет назад
Родитель
Сommit
83033dc174

+ 3 - 2
README.md

@@ -107,11 +107,12 @@ In the project, you'll find [single scheme](http://promisekit.org/news/2016/08/M
 You can use [CocoaPods](http://cocoapods.org/?q=cryptoSwift).
 
 ```ruby
-source 'https://github.com/CocoaPods/Specs.git'
 platform :ios, '8.0'
 use_frameworks!
 
-pod 'CryptoSwift'
+target 'MyApp' do
+  pod 'CryptoSwift'
+end
 ```
 
 or for newest version from specified branch of code:

+ 38 - 12
Sources/CryptoSwift/Array+Extension.swift

@@ -22,26 +22,52 @@ extension Array {
         for idx in stride(from: chunksize, through: self.count, by: chunksize) {
             words.append(Array(self[idx - chunksize ..< idx])) // slow for large table
         }
-        let reminder = self.suffix(self.count % chunksize)
-        if !reminder.isEmpty {
-            words.append(Array(reminder))
+        let remainder = self.suffix(self.count % chunksize)
+        if !remainder.isEmpty {
+            words.append(Array(remainder))
         }
         return words
     }
 }
 
 extension Array where Element: Integer, Element.IntegerLiteralType == UInt8 {
-
+    
     public init(hex: String) {
-        self.init()
-
-        let utf8 = Array<Element.IntegerLiteralType>(hex.utf8)
-        let skip0x = hex.hasPrefix("0x") ? 2 : 0
-        for idx in stride(from: utf8.startIndex.advanced(by: skip0x), to: utf8.endIndex, by: utf8.startIndex.advanced(by: 2)) {
-            let byteHex = "\(UnicodeScalar(utf8[idx]))\(UnicodeScalar(utf8[idx.advanced(by: 1)]))"
-            if let byte = UInt8(byteHex, radix: 16) {
-                self.append(byte as! Element)
+        self.init(reserveCapacity: hex.unicodeScalars.lazy.underestimatedCount)
+        var buffer:UInt8?
+        var skip = hex.hasPrefix("0x") ? 2 : 0
+        for char in hex.unicodeScalars.lazy {
+            guard skip == 0 else {
+                skip -= 1
+                continue
+            }
+            guard char.value >= 48 && char.value <= 102 else {
+                self.removeAll()
+                return
             }
+            let v:UInt8
+            let c:UInt8 = UInt8(char.value)
+            switch c{
+            case let c where c <= 57:
+                v = c - 48
+            case let c where c >= 65 && c <= 70:
+                v = c - 55
+            case let c where c >= 97:
+                v = c - 87
+            default:
+                self.removeAll()
+                return
+            }
+            if let b = buffer {
+                self.append(b << 4 | v as! Element)
+                buffer = nil
+            } else {
+                buffer = v
+            }
+        }
+        if let b = buffer{
+            self.append(b as! Element)
         }
     }
+    
 }

+ 1 - 0
Sources/CryptoSwift/String+Extension.swift

@@ -58,4 +58,5 @@ extension String {
     public func authenticate<A: Authenticator>(with authenticator: A) throws -> String {
         return try self.utf8.lazy.map({ $0 as UInt8 }).authenticate(with: authenticator).toHexString()
     }
+    
 }

+ 11 - 0
Tests/CryptoSwiftTests/ExtensionsTest.swift

@@ -62,6 +62,17 @@ final class ExtensionsTest: XCTestCase {
         let hex = array.toHexString()
         XCTAssertEqual(str, hex)
     }
+    
+    func testArrayInitHexPerformance(){
+        var str = "b1b2b3b3b3b3b3b3b1b2b3b3b3b3b3b3"
+        for _ in 0...12{
+            str += str
+        }
+        measure {
+            let _ = Array<UInt8>(hex: str)
+        }
+    }
+    
 }
 
 #if !CI