Last active
August 29, 2015 14:21
-
-
Save robtimp/2544790985bb7ec12623 to your computer and use it in GitHub Desktop.
String Parsing (objc.io #9) Swift version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// objc.io Issue #9 | |
// February, 2014 | |
// String Parsing by Chris Eidhof | |
// | |
// Swift version by Rob Hudson | |
import UIKit | |
// NSTextCheckingResult using NSRange, rather than Range<String.Index>, so we need an NSString, rather than a String | |
let string: NSString = "backgroundColor = #ff0000" | |
var error: NSError? | |
let pattern = "(\\w+) = #(\\p{Hex_Digit}{6})" | |
let expression = NSRegularExpression(pattern: pattern, options: nil, error: &error) | |
let result = expression?.firstMatchInString(string as String, options: nil, range: NSMakeRange(0, string.length)) | |
if let result = result { | |
let key = string.substringWithRange(result.rangeAtIndex(1)) | |
let value = string.substringWithRange(result.rangeAtIndex(2)) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// objc.io Issue #9 | |
// February, 2014 | |
// String Parsing by Chris Eidhof | |
// | |
// Example 4 | |
// Swift version by Rob Hudson | |
import UIKit | |
extension UIColor { | |
class func colorWithHexString(colorCode: String, alpha: Float = 1.0) -> UIColor { | |
var scanner = NSScanner(string:colorCode) | |
var color:UInt32 = 0; | |
scanner.scanHexInt(&color) | |
let mask = 0x000000FF | |
let r = CGFloat(Float(Int(color >> 16) & mask)/255.0) | |
let g = CGFloat(Float(Int(color >> 8) & mask)/255.0) | |
let b = CGFloat(Float(Int(color) & mask)/255.0) | |
return UIColor(red: r, green: g, blue: b, alpha: CGFloat(alpha)) | |
} | |
} | |
let FormatError = 100 | |
let MyErrorDomain = "io.objc.parsing" | |
let string = "backgroundColor = (189, 23, 95)\ntextColor = #179ac0" | |
var scanner: NSScanner! | |
func parse(string: String, inout error: NSError?) -> [String : UIColor]? { | |
scanner = NSScanner(string: string) | |
scanner.charactersToBeSkipped = NSCharacterSet.whitespaceCharacterSet() | |
var result = [String : UIColor]() | |
let letters = NSCharacterSet.letterCharacterSet() | |
while !scanner.atEnd { | |
var key: NSString? | |
var value: UIColor? | |
let didScan = scanner.scanCharactersFromSet(letters, intoString: &key) | |
scanner.scanString("=", intoString: nil) | |
scanColor(&value) | |
if let key = key as? String { | |
result[key] = value | |
} | |
scanner.scanCharactersFromSet(NSCharacterSet.newlineCharacterSet(), intoString: nil) // scan an optional newline | |
} | |
return result | |
} | |
func scanColor(inout color: UIColor?) -> Bool { | |
return scanHexColorIntoColor(&color) || scanTupleColorIntoColor(&color) | |
} | |
func scanHexColorIntoColor(inout color: UIColor?) -> Bool { | |
let hexCharacterSet = NSCharacterSet(charactersInString: "0123456789abcdefABCDEF") | |
var colorString: NSString? | |
if scanner.scanString("#", intoString: nil) && | |
scanner.scanCharactersFromSet(hexCharacterSet, intoString: &colorString) && | |
colorString?.length == 6 { | |
color = UIColor.colorWithHexString(colorString as! String) | |
return true | |
} | |
return false | |
} | |
func scanTupleColorIntoColor(inout color: UIColor?) -> Bool { | |
var red = 0, green = 0, blue = 0 | |
let didScan = scanner.scanString("(", intoString: nil) && | |
scanner.scanInteger(&red) && | |
scanner.scanString(",", intoString: nil) && | |
scanner.scanInteger(&green) && | |
scanner.scanString(",", intoString: nil) && | |
scanner.scanInteger(&blue) && | |
scanner.scanString(")", intoString: nil) | |
if didScan { | |
color = UIColor(red: CGFloat(Double(red) / 255.0), green: CGFloat(Double(green) / 255.0), blue: CGFloat(Double(blue) / 255.0), alpha: 1.0) | |
return true | |
} | |
return false | |
} | |
var error: NSError? | |
parse(string, &error) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// objc.io Issue #9 | |
// February, 2014 | |
// String Parsing by Chris Eidhof | |
// | |
// Example 5 | |
// Swift version by Rob Hudson | |
import UIKit | |
let string = "myView.left = otherView.right * 2 + 10\n" + | |
"viewController.view.centerX + myConstant <= self.view.centerX" | |
func tokenize(contents: String) -> [AnyObject] { | |
let scanner = NSScanner(string: contents) | |
var tokens = [AnyObject]() | |
while !scanner.atEnd { | |
for token in ["=", "+", "*", ">=", "<=", "."] { | |
if scanner.scanString(token, intoString: nil) { | |
tokens.append(token) | |
} | |
} | |
var result: NSString? | |
if scanner.scanCharactersFromSet(NSCharacterSet.letterCharacterSet(), intoString: &result) { | |
if let result = result as? String { | |
tokens.append(result) | |
} | |
} | |
var doubleResult = 0.0 | |
if scanner.scanDouble(&doubleResult) { | |
tokens.append(doubleResult) | |
} | |
} | |
return tokens | |
} | |
let example = "myConstant = 100\n" + | |
"myView.left = otherView.right * 2 + 10\n" + | |
"viewController.view.centerX + myConstant <= self.view.centerX" | |
let result = tokenize(example) | |
let expected: [AnyObject] = ["myConstant", "=", 100, "myView", ".", "left", "=", "otherView", ".", "right", "*", 2, "+", 10, "viewController", ".", "view", ".", "centerX", "+", "myConstant", "<=", "self", ".", "view", ".", "centerX"] | |
// We can't compare AnyObject arrays with == or !=, so we'll use this function | |
func arraysAreEqual(array1: Array<AnyObject>, array2: Array<AnyObject>) -> Bool { | |
if array1.count != array2.count { | |
return false | |
} | |
for i in 0..<array1.count { | |
if let string1 = array1[i] as? String, string2 = array2[i] as? String { | |
if string1 != string2 { | |
return false | |
} | |
} else if let number1 = array1[i] as? NSNumber, number2 = array2[i] as? NSNumber { | |
if number1 != number2 { | |
return false | |
} | |
} | |
} | |
return true | |
} | |
arraysAreEqual(result, expected) // true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment