Procházet zdrojové kódy

Merge pull request #3 from norio-nomura/refactor

Refactor
Norio Nomura před 10 roky
rodič
revize
42edf2bb7a

+ 34 - 2
Base32.xcodeproj/project.pbxproj

@@ -9,6 +9,17 @@
 /* Begin PBXBuildFile section */
 		6C10E90F1A753A6C006EED90 /* Base32.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CA0A79D1A74E80600AC539F /* Base32.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6C10E91A1A754346006EED90 /* TTTDataTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C10E9141A7540B5006EED90 /* TTTDataTransformer.m */; };
+		6C122F7A1A85DC1E004FD458 /* Base16.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F791A85DC1E004FD458 /* Base16.swift */; };
+		6C122F7B1A85DC1E004FD458 /* Base16.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F791A85DC1E004FD458 /* Base16.swift */; };
+		6C122F7D1A85E52C004FD458 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7C1A85E52C004FD458 /* StringExtension.swift */; };
+		6C122F7E1A85E52C004FD458 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7C1A85E52C004FD458 /* StringExtension.swift */; };
+		6C122F801A85E885004FD458 /* Base16Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7F1A85E885004FD458 /* Base16Tests.swift */; };
+		6C122F811A85E885004FD458 /* Base16Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7F1A85E885004FD458 /* Base16Tests.swift */; };
+		6C122F821A85EA0A004FD458 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7C1A85E52C004FD458 /* StringExtension.swift */; };
+		6C122F831A85EA0B004FD458 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7C1A85E52C004FD458 /* StringExtension.swift */; };
+		6C122F851A85EA52004FD458 /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F841A85EA52004FD458 /* StringExtensionTests.swift */; };
+		6C122F861A85EA52004FD458 /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F841A85EA52004FD458 /* StringExtensionTests.swift */; };
+		6C122F871A85F332004FD458 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C122F7C1A85E52C004FD458 /* StringExtension.swift */; };
 		6CA0A79E1A74E80600AC539F /* Base32.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CA0A79D1A74E80600AC539F /* Base32.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6CA0A7A41A74E80600AC539F /* Base32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CA0A7981A74E80600AC539F /* Base32.framework */; };
 		6CA0A7AB1A74E80600AC539F /* Base32Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CA0A7AA1A74E80600AC539F /* Base32Tests.swift */; };
@@ -42,6 +53,10 @@
 		6C10E9121A7540B4006EED90 /* SecEncodeTransformTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SecEncodeTransformTests-Bridging-Header.h"; sourceTree = "<group>"; };
 		6C10E9131A7540B5006EED90 /* TTTDataTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTTDataTransformer.h; sourceTree = "<group>"; };
 		6C10E9141A7540B5006EED90 /* TTTDataTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTTDataTransformer.m; sourceTree = "<group>"; };
+		6C122F791A85DC1E004FD458 /* Base16.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base16.swift; sourceTree = "<group>"; };
+		6C122F7C1A85E52C004FD458 /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
+		6C122F7F1A85E885004FD458 /* Base16Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base16Tests.swift; sourceTree = "<group>"; };
+		6C122F841A85EA52004FD458 /* StringExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = "<group>"; };
 		6CA0A7981A74E80600AC539F /* Base32.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Base32.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		6CA0A79C1A74E80600AC539F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		6CA0A79D1A74E80600AC539F /* Base32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Base32.h; sourceTree = "<group>"; };
@@ -152,6 +167,8 @@
 			children = (
 				6CA0A79D1A74E80600AC539F /* Base32.h */,
 				6CA0A7EF1A74ECEE00AC539F /* Base32.swift */,
+				6C122F791A85DC1E004FD458 /* Base16.swift */,
+				6C122F7C1A85E52C004FD458 /* StringExtension.swift */,
 				6CA0A79B1A74E80600AC539F /* Supporting Files */,
 			);
 			path = Base32;
@@ -169,6 +186,8 @@
 			isa = PBXGroup;
 			children = (
 				6CA0A7AA1A74E80600AC539F /* Base32Tests.swift */,
+				6C122F7F1A85E885004FD458 /* Base16Tests.swift */,
+				6C122F841A85EA52004FD458 /* StringExtensionTests.swift */,
 				6CA0A7A81A74E80600AC539F /* Supporting Files */,
 			);
 			path = Base32Tests;
@@ -479,7 +498,9 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6C122F7D1A85E52C004FD458 /* StringExtension.swift in Sources */,
 				6CA0A7F01A74ECEE00AC539F /* Base32.swift in Sources */,
+				6C122F7A1A85DC1E004FD458 /* Base16.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -487,7 +508,10 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6C122F851A85EA52004FD458 /* StringExtensionTests.swift in Sources */,
 				6CA0A7AB1A74E80600AC539F /* Base32Tests.swift in Sources */,
+				6C122F801A85E885004FD458 /* Base16Tests.swift in Sources */,
+				6C122F821A85EA0A004FD458 /* StringExtension.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -495,7 +519,9 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6C122F7E1A85E52C004FD458 /* StringExtension.swift in Sources */,
 				6CA0A7F11A74ECEE00AC539F /* Base32.swift in Sources */,
+				6C122F7B1A85DC1E004FD458 /* Base16.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -503,7 +529,10 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6C122F861A85EA52004FD458 /* StringExtensionTests.swift in Sources */,
 				6CA0A7EE1A74ECD700AC539F /* Base32Tests.swift in Sources */,
+				6C122F811A85E885004FD458 /* Base16Tests.swift in Sources */,
+				6C122F831A85EA0B004FD458 /* StringExtension.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -513,6 +542,7 @@
 			files = (
 				6CA0A80C1A75135D00AC539F /* SecEncodeTransformTests.swift in Sources */,
 				6C10E91A1A754346006EED90 /* TTTDataTransformer.m in Sources */,
+				6C122F871A85F332004FD458 /* StringExtension.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -536,7 +566,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7B81A74E88E00AC539F /* Debug.xcconfig */;
 			buildSettings = {
-				APPLICATION_EXTENSION_API_ONLY = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CURRENT_PROJECT_VERSION = 1;
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -551,7 +580,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7BA1A74E88E00AC539F /* Release.xcconfig */;
 			buildSettings = {
-				APPLICATION_EXTENSION_API_ONLY = YES;
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CURRENT_PROJECT_VERSION = 1;
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -566,6 +594,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7CB1A74E88E00AC539F /* Mac-Framework.xcconfig */;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				INFOPLIST_FILE = Base32/Info.plist;
@@ -576,6 +605,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7CB1A74E88E00AC539F /* Mac-Framework.xcconfig */;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				INFOPLIST_FILE = Base32/Info.plist;
@@ -604,6 +634,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7C51A74E88E00AC539F /* iOS-Framework.xcconfig */;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				INFOPLIST_FILE = Base32/Info.plist;
@@ -614,6 +645,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 6CA0A7C51A74E88E00AC539F /* iOS-Framework.xcconfig */;
 			buildSettings = {
+				APPLICATION_EXTENSION_API_ONLY = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				INFOPLIST_FILE = Base32/Info.plist;

+ 122 - 0
Base32/Base16.swift

@@ -0,0 +1,122 @@
+//
+//  Base16.swift
+//  Base32
+//
+//  Created by 野村 憲男 on 2/7/15.
+//  Copyright (c) 2015 Norio Nomura. All rights reserved.
+//
+
+import Foundation
+
+// MARK: - Base16 NSData <-> String
+
+public func base16Encode(data: NSData) -> String {
+    return base16encode(data.bytes, data.length)
+}
+
+public func base16DecodeToData(string: String) -> NSData? {
+    if let array = base16decode(string) {
+        return NSData(bytes: array, length: array.count)
+    } else {
+        return nil
+    }
+}
+
+// MARK: - Base16 [UInt8] <-> String
+
+public func base16Encode(array: [UInt8]) -> String {
+    return base16encode(array, array.count)
+}
+
+public func base16Decode(string: String) -> [UInt8]? {
+    return base16decode(string)
+}
+
+// MARK: extensions
+
+extension String {
+    // base16
+    public var base16DecodedData: NSData? {
+        return base16DecodeToData(self)
+    }
+    
+    public var base16EncodedString: String {
+        let length = lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
+        return nulTerminatedUTF8.withUnsafeBufferPointer {
+            (p: UnsafeBufferPointer<UInt8>) -> String in
+            return base16encode(p.baseAddress, length)
+        }
+    }
+    
+    public func base16DecodedString(encoding: NSStringEncoding = NSUTF8StringEncoding) -> String? {
+        if let data = self.base16DecodedData {
+            return NSString(data: data, encoding: NSUTF8StringEncoding) as? String
+        } else {
+            return nil
+        }
+    }
+}
+
+extension NSData {
+    // base16
+    public var base16EncodedString: String {
+        return base16Encode(self)
+    }
+    
+    public var base16EncodedData: NSData {
+        return base16EncodedString.dataUsingUTF8StringEncoding
+    }
+    
+    public var base16DecodedData: NSData? {
+        if let string = NSString(data: self, encoding: NSUTF8StringEncoding) as? String {
+            return base16DecodeToData(string)
+        } else {
+            return nil
+        }
+    }
+}
+
+// MARK: encode
+private func base16encode(data: UnsafePointer<Void>, var length: Int, uppercase: Bool = true) -> String {
+    let array = UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(data), count: length)
+    return map(array) { String(format: uppercase ? "%02X" : "%02x", $0) }.reduce("", +)
+}
+
+// MARK: decode
+extension UnicodeScalar {
+    private var hexToUInt8: UInt8? {
+        switch self {
+        case "0"..."9": return UInt8(value - UnicodeScalar("0").value)
+        case "a"..."f": return UInt8(value - UnicodeScalar("a").value + 0xa)
+        case "A"..."F": return UInt8(value - UnicodeScalar("A").value + 0xa)
+        default:
+            println("base16decode: Invalid hex character \(self)")
+            return nil
+        }
+    }
+}
+
+private func base16decode(string: String) -> [UInt8]? {
+    // validate length
+    let lenght = countElements(string)
+    if lenght % 2 != 0 {
+        println("base16decode: String must contain even number of characters")
+        return nil
+    }
+    var g = string.unicodeScalars.generate()
+    var buffer = Array<UInt8>(count: lenght / 2, repeatedValue: 0)
+    var index = 0
+    while let msn = g.next() {
+        if let msn = msn.hexToUInt8 {
+            if let lsn = g.next()?.hexToUInt8 {
+                buffer[index] = msn << 4 | lsn
+            } else {
+                return nil
+            }
+        } else {
+            return nil
+        }
+        index++
+    }
+    return buffer
+}

+ 4 - 4
Base32/Base32.swift

@@ -106,8 +106,8 @@ extension NSData {
         return base32Encode(self)
     }
     
-    public var base32EncodedData: NSData? {
-        return base32EncodedString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+    public var base32EncodedData: NSData {
+        return base32EncodedString.dataUsingUTF8StringEncoding
     }
     
     public var base32DecodedData: NSData? {
@@ -123,8 +123,8 @@ extension NSData {
         return base32HexEncode(self)
     }
     
-    public var base32HexEncodedData: NSData? {
-        return base32HexEncodedString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+    public var base32HexEncodedData: NSData {
+        return base32HexEncodedString.dataUsingUTF8StringEncoding
     }
     
     public var base32HexDecodedData: NSData? {

+ 29 - 0
Base32/StringExtension.swift

@@ -0,0 +1,29 @@
+//
+//  StringExtension.swift
+//  Base32
+//
+//  Created by 野村 憲男 on 2/7/15.
+//  Copyright (c) 2015 Norio Nomura. All rights reserved.
+//
+
+import Foundation
+
+// MARK: - private
+
+extension String {
+    /// NSData never nil
+    internal var dataUsingUTF8StringEncoding: NSData {
+        let length = nulTerminatedUTF8.count - 1
+        return nulTerminatedUTF8.withUnsafeBufferPointer {
+            return NSData(bytes: $0.baseAddress, length: length)
+        }
+    }
+    
+    /// Array<UInt8>
+    internal var arrayUsingUTF8StringEncoding: [UInt8] {
+        let length = nulTerminatedUTF8.count - 1
+        return nulTerminatedUTF8.withUnsafeBufferPointer {
+            return Array(UnsafeBufferPointer(start: $0.baseAddress, count: length))
+        }
+    }
+}

+ 109 - 0
Base32Tests/Base16Tests.swift

@@ -0,0 +1,109 @@
+//
+//  Base16Tests.swift
+//  Base32
+//
+//  Created by 野村 憲男 on 2/7/15.
+//  Copyright (c) 2015 Norio Nomura. All rights reserved.
+//
+
+import Foundation
+import XCTest
+import Base32
+
+class Base16Tests: XCTestCase {
+
+    let vectors: [(String, String)] = [
+        ("", ""),
+        ("f", "66"),
+        ("fo", "666F"),
+        ("foo", "666F6F"),
+        ("foob", "666F6F62"),
+        ("fooba", "666F6F6261"),
+        ("foobar", "666F6F626172"),
+    ]
+    
+
+    override func setUp() {
+        super.setUp()
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+    }
+    
+    override func tearDown() {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+        super.tearDown()
+    }
+
+    // MARK: https://tools.ietf.org/html/rfc4648
+
+    func test_RFC4648_base16Encode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1)}
+        self.measureBlock{
+            for _ in 0...100 {
+                for (test, expect) in convertedVectors {
+                    let result = base16Encode(test)
+                    XCTAssertEqual(result, expect, "base16Encode for \(test)")
+                }
+            }
+        }
+    }
+    
+    func test_RFC4648_base16Decode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1)}
+        self.measureBlock{
+            for _ in 0...100 {
+                for (expect, test) in convertedVectors {
+                    let result = base16DecodeToData(test)
+                    XCTAssertEqual(result!, expect, "base16Decode for \(test)")
+                }
+            }
+        }
+    }
+    
+    // MARK: -
+    
+    func test_Base16ExtensionString() {
+        self.measureBlock{
+            for _ in 0...100 {
+                for (test, expect) in self.vectors {
+                    let result = test.base16EncodedString
+                    XCTAssertEqual(result, expect, "\(test).base16EncodedString")
+                    let decoded = result.base16DecodedString()
+                    XCTAssertEqual(decoded!, test, "\(result).base16DecodedString()")
+                }
+            }
+        }
+    }
+    
+    func test_Base16ExtensionData() {
+        let dataVectors = vectors.map {
+            (
+                $0.dataUsingUTF8StringEncoding,
+                $1.dataUsingUTF8StringEncoding
+            )
+        }
+        self.measureBlock{
+            for _ in 0...100 {
+                for (test, expect) in dataVectors {
+                    let result = test.base16EncodedData
+                    XCTAssertEqual(result, expect, "\(test).base16EncodedData")
+                    let decoded = result.base16DecodedData
+                    XCTAssertEqual(decoded!, test, "\(result).base16DecodedData")
+                }
+            }
+        }
+    }
+    
+    func test_Base16ExtensionDataAndString() {
+        let dataAndStringVectors = vectors.map {($0.dataUsingUTF8StringEncoding, $1)}
+        self.measureBlock{
+            for _ in 0...100 {
+                for (test, expect) in dataAndStringVectors {
+                    let result = test.base16EncodedString
+                    XCTAssertEqual(result, expect, "\(test).base16EncodedString")
+                    let decoded = result.base16DecodedData
+                    XCTAssertEqual(decoded!, test, "\(result).base16DecodedData")
+                }
+            }
+        }
+    }
+}

+ 32 - 33
Base32Tests/Base32Tests.swift

@@ -1,6 +1,6 @@
 //
 //  Base32Tests.swift
-//  TOTP
+//  Base32
 //
 //  Created by 野村 憲男 on 1/24/15.
 //  Copyright (c) 2015 Norio Nomura. All rights reserved.
@@ -34,49 +34,49 @@ class Base32Tests: XCTestCase {
     
     // MARK: https://tools.ietf.org/html/rfc4648
     
-    func test_RFC4648_Encode() {
+    func test_RFC4648_base32Encode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
         self.measureBlock{
             for _ in 0...100 {
-                for (test, expect, expectHex) in self.vectors {
-                    let data = test.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
-                    let result = base32Encode(data)
+                for (test, expect, expectHex) in convertedVectors {
+                    let result = base32Encode(test)
                     XCTAssertEqual(result, expect, "base32Encode for \(test)")
                 }
             }
         }
     }
     
-    func test_RFC4648_Decode() {
+    func test_RFC4648_base32Decode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
         self.measureBlock{
             for _ in 0...100 {
-                for (expect, test, testHex) in self.vectors {
-                    let data = expect.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+                for (expect, test, testHex) in convertedVectors {
                     let result = base32DecodeToData(test)
-                    XCTAssertEqual(result!, data!, "base32Decode for \(test)")
+                    XCTAssertEqual(result!, expect, "base32Decode for \(test)")
                 }
             }
         }
     }
     
-    func test_RFC4648_HexEncode() {
+    func test_RFC4648_base32HexEncode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
         self.measureBlock{
             for _ in 0...100 {
-                for (test, expect, expectHex) in self.vectors {
-                    let data = test.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
-                    let resultHex = base32HexEncode(data)
+                for (test, expect, expectHex) in convertedVectors {
+                    let resultHex = base32HexEncode(test)
                     XCTAssertEqual(resultHex, expectHex, "base32HexEncode for \(test)")
                 }
             }
         }
     }
     
-    func test_RFC4648_HexDecode() {
+    func test_RFC4648_base32HexDecode() {
+        let convertedVectors = self.vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
         self.measureBlock{
             for _ in 0...100 {
-                for (expect, test, testHex) in self.vectors {
-                    let data = expect.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+                for (expect, test, testHex) in convertedVectors {
                     let resultHex = base32HexDecodeToData(testHex)
-                    XCTAssertEqual(resultHex!, data!, "base32HexDecode for \(testHex)")
+                    XCTAssertEqual(resultHex!, expect, "base32HexDecode for \(testHex)")
                 }
             }
         }
@@ -84,7 +84,7 @@ class Base32Tests: XCTestCase {
     
     // MARK: -
     
-    func test_ExtensionString() {
+    func test_base32ExtensionString() {
         self.measureBlock{
             for _ in 0...100 {
                 for (test, expect, expectHex) in self.vectors {
@@ -101,12 +101,12 @@ class Base32Tests: XCTestCase {
         }
     }
     
-    func test_ExtensionData() {
+    func test_base32ExtensionData() {
         let dataVectors = vectors.map {
             (
-                $0.dataUsingEncoding(NSUTF8StringEncoding)!,
-                $1.dataUsingEncoding(NSUTF8StringEncoding)!,
-                $2.dataUsingEncoding(NSUTF8StringEncoding)!
+                $0.dataUsingUTF8StringEncoding,
+                $1.dataUsingUTF8StringEncoding,
+                $2.dataUsingUTF8StringEncoding
             )
         }
         self.measureBlock{
@@ -114,10 +114,10 @@ class Base32Tests: XCTestCase {
                 for (test, expect, expectHex) in dataVectors {
                     let result = test.base32EncodedData
                     let resultHex = test.base32HexEncodedData
-                    XCTAssertEqual(result!, expect, "\(test).base32EncodedData")
-                    XCTAssertEqual(resultHex!, expectHex, "\(test).base32HexEncodedData")
-                    let decoded = result!.base32DecodedData
-                    let decodedHex = resultHex!.base32HexDecodedData
+                    XCTAssertEqual(result, expect, "\(test).base32EncodedData")
+                    XCTAssertEqual(resultHex, expectHex, "\(test).base32HexEncodedData")
+                    let decoded = result.base32DecodedData
+                    let decodedHex = resultHex.base32HexDecodedData
                     XCTAssertEqual(decoded!, test, "\(result).base32DecodedData")
                     XCTAssertEqual(decodedHex!, test, "\(resultHex).base32HexDecodedData")
                 }
@@ -125,8 +125,8 @@ class Base32Tests: XCTestCase {
         }
     }
     
-    func test_ExtensionDataAndString() {
-        let dataAndStringVectors = vectors.map {($0.dataUsingEncoding(NSUTF8StringEncoding)!, $1, $2)}
+    func test_base32ExtensionDataAndString() {
+        let dataAndStringVectors = vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
         self.measureBlock{
             for _ in 0...100 {
                 for (test, expect, expectHex) in dataAndStringVectors {
@@ -145,21 +145,20 @@ class Base32Tests: XCTestCase {
     
     // MARK:
     
-    func test_DecodeStringAcceptableLengthPattern() {
+    func test_base32DecodeStringAcceptableLengthPatterns() {
         // "=" stripped valid string
         let strippedVectors = vectors.map {
             (
-                $0,
+                $0.dataUsingUTF8StringEncoding,
                 $1.stringByReplacingOccurrencesOfString("=", withString:""),
                 $2.stringByReplacingOccurrencesOfString("=", withString:"")
             )
         }
         for (expect, test, testHex) in strippedVectors {
-            let data = expect.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
             let result = base32DecodeToData(test)
             let resultHex = base32HexDecodeToData(testHex)
-            XCTAssertEqual(result!, data!, "base32Decode for \(test)")
-            XCTAssertEqual(resultHex!, data!, "base32HexDecode for \(testHex)")
+            XCTAssertEqual(result!, expect, "base32Decode for \(test)")
+            XCTAssertEqual(resultHex!, expect, "base32HexDecode for \(testHex)")
         }
         
         // invalid length string with padding

+ 31 - 0
Base32Tests/StringExtensionTests.swift

@@ -0,0 +1,31 @@
+//
+//  StringExtensionTests.swift
+//  Base32
+//
+//  Created by 野村 憲男 on 2/7/15.
+//  Copyright (c) 2015 Norio Nomura. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class StringExtensionTests: XCTestCase {
+
+    override func setUp() {
+        super.setUp()
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+    }
+    
+    override func tearDown() {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+        super.tearDown()
+    }
+
+    func test_dataUsingUTF8StringEncoding() {
+        let emptyString = ""
+        XCTAssertEqual(emptyString.dataUsingUTF8StringEncoding, emptyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!)
+
+        let string = "0112233445566778899AABBCCDDEEFFaabbccddeefff"
+        XCTAssertEqual(string.dataUsingUTF8StringEncoding, string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!)
+    }
+}

+ 1 - 1
Gemfile

@@ -1,5 +1,5 @@
 source "https://rubygems.org"
 
 gem "rake"
-gem 'xcpretty'
+gem 'xcpretty', :git => 'https://github.com/norio-nomura/xcpretty.git', :branch => 'add-measuring'
 gem "xcjobs", :git => 'https://github.com/norio-nomura/xcjobs.git', :branch => 'subclass-of-rake-task'

+ 8 - 2
Gemfile.lock

@@ -5,11 +5,17 @@ GIT
   specs:
     xcjobs (0.0.4)
 
+GIT
+  remote: https://github.com/norio-nomura/xcpretty.git
+  revision: aa9c2adfefc315d5dbf06f70f8ab6926c74fb045
+  branch: add-measuring
+  specs:
+    xcpretty (0.1.7)
+
 GEM
   remote: https://rubygems.org/
   specs:
     rake (10.4.2)
-    xcpretty (0.1.7)
 
 PLATFORMS
   ruby
@@ -17,4 +23,4 @@ PLATFORMS
 DEPENDENCIES
   rake
   xcjobs!
-  xcpretty
+  xcpretty!

+ 41 - 16
SecEncodeTransformTests/SecEncodeTransformTests.swift

@@ -9,18 +9,22 @@
 import Foundation
 import XCTest
 import Security
+import Base32
+
+let vectors: [(String, String, String)] = [
+    ("", "", ""),
+    ("f", "MY======", "CO======"),
+    ("fo", "MZXQ====", "CPNG===="),
+    ("foo", "MZXW6===", "CPNMU==="),
+    ("foob", "MZXW6YQ=", "CPNMUOG="),
+    ("fooba", "MZXW6YTB", "CPNMUOJ1"),
+    ("foobar", "MZXW6YTBOI======", "CPNMUOJ1E8======"),
+]
+
+let convertedVectors = vectors.map {($0.dataUsingUTF8StringEncoding, $1, $2)}
 
 class SecEncodeTransformTests: XCTestCase {
     
-    let vectors: [(String,String,String)] = [
-        ("", "", ""),
-        ("f", "MY======", "CO======"),
-        ("fo", "MZXQ====", "CPNG===="),
-        ("foo", "MZXW6===", "CPNMU==="),
-        ("foob", "MZXW6YQ=", "CPNMUOG="),
-        ("fooba", "MZXW6YTB", "CPNMUOJ1"),
-        ("foobar", "MZXW6YTBOI======", "CPNMUOJ1E8======"),
-    ]
     
     override func setUp() {
         super.setUp()
@@ -33,14 +37,13 @@ class SecEncodeTransformTests: XCTestCase {
     }
     
     // MARK: https://tools.ietf.org/html/rfc4648
-    
+
     // MARK: Using SecEncodeTransform
     func test_RFC4648_Encode_UsingSecEncodeTransform() {
         self.measureBlock{
             for _ in 0...100 {
-                for (test, expect, expectHex) in self.vectors {
-                    let data = test.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
-                    let result = TTTBase32EncodedStringFromData(data)
+                for (test, expect, expectHex) in convertedVectors {
+                    let result = TTTBase32EncodedStringFromData(test)
                     XCTAssertEqual(result, expect, "TTTBase32EncodedStringFromData for \(test)")
                 }
             }
@@ -50,10 +53,32 @@ class SecEncodeTransformTests: XCTestCase {
     func test_RFC4648_Decode_UsingSecEncodeTransform() {
         self.measureBlock{
             for _ in 0...100 {
-                for (expect, test, testHex) in self.vectors {
-                    let data = expect.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
+                for (expect, test, testHex) in convertedVectors {
                     let result = TTTDataFromBase32EncodedString(test)
-                    XCTAssertEqual(result, data!, "TTTDataFromBase32EncodedString for \(test)")
+                    XCTAssertEqual(result, expect, "TTTDataFromBase32EncodedString for \(test)")
+                }
+            }
+        }
+    }
+    
+    // MARK: Using Base32
+    func test_RFC4648_Encode_UsingBase32() {
+        self.measureBlock{
+            for _ in 0...100 {
+                for (test, expect, expectHex) in convertedVectors {
+                    let result = base32Encode(test)
+                    XCTAssertEqual(result, expect, "base32Encode for \(test)")
+                }
+            }
+        }
+    }
+    
+    func test_RFC4648_Decode_UsingBase32() {
+        self.measureBlock{
+            for _ in 0...100 {
+                for (expect, test, testHex) in convertedVectors {
+                    let result = base32DecodeToData(test)
+                    XCTAssertEqual(result!, expect, "base32Decode for \(test)")
                 }
             }
         }