// // String+OAuthSwift.swift // OAuthSwift // // Created by Dongri Jin on 6/21/14. // Copyright (c) 2014 Dongri Jin. All rights reserved. // import Foundation extension String { var parametersFromQueryString: [String: String] { return dictionaryBySplitting("&", keyValueSeparator: "=") } /// Encodes url string making it ready to be passed as a query parameter. This encodes pretty much everything apart from /// alphanumerics and a few other characters compared to standard query encoding. var urlEncoded: String { let customAllowedSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~") return self.addingPercentEncoding(withAllowedCharacters: customAllowedSet)! } var urlQueryEncoded: String? { return self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) } /// Returns new url query string by appending query parameter encoding it first, if specified. func urlQueryByAppending(parameter name: String, value: String, encode: Bool = true, _ encodeError: ((String, String) -> Void)? = nil) -> String? { if value.isEmpty { return self } else if let value = encode ? value.urlQueryEncoded : value { return "\(self)\(self.isEmpty ? "" : "&")\(name)=\(value)" } else { encodeError?(name, value) return nil } } /// Returns new url string by appending query string at the end. func urlByAppending(query: String) -> String { return "\(self)\(self.contains("?") ? "&" : "?")\(query)" } fileprivate func dictionaryBySplitting(_ elementSeparator: String, keyValueSeparator: String) -> [String: String] { var string = self if hasPrefix(elementSeparator) { string = String(dropFirst(1)) } var parameters = [String: String]() let scanner = Scanner(string: string) var key: NSString? var value: NSString? while !scanner.isAtEnd { key = nil scanner.scanUpTo(keyValueSeparator, into: &key) scanner.scanString(keyValueSeparator, into: nil) value = nil scanner.scanUpTo(elementSeparator, into: &value) scanner.scanString(elementSeparator, into: nil) if let key = key as String? { if let value = value as String? { if key.contains(elementSeparator) { var keys = key.components(separatedBy: elementSeparator) if let key = keys.popLast() { parameters.updateValue(value, forKey: String(key)) } for flag in keys { parameters.updateValue("", forKey: flag) } } else { parameters.updateValue(value, forKey: key) } } else { parameters.updateValue("", forKey: key) } } } return parameters } public var headerDictionary: OAuthSwift.Headers { return dictionaryBySplitting(",", keyValueSeparator: "=") } var safeStringByRemovingPercentEncoding: String { return self.removingPercentEncoding ?? self } mutating func dropLast() { self.remove(at: self.index(before: self.endIndex)) } subscript (bounds: CountableClosedRange) -> String { let start = index(startIndex, offsetBy: bounds.lowerBound) let end = index(startIndex, offsetBy: bounds.upperBound) return String(self[start...end]) } subscript (bounds: CountableRange) -> String { let start = index(startIndex, offsetBy: bounds.lowerBound) let end = index(startIndex, offsetBy: bounds.upperBound) return String(self[start..