0001    // Regex.swift
0002    //
0003    // The MIT License (MIT)
0004    //
0005    // Copyright (c) 2015 Zewo
0006    //
0007    // Permission is hereby granted, free of charge, to any person obtaining a copy
0008    // of this software and associated documentation files (the "Software"), to deal
0009    // in the Software without restriction, including without limitation the rights
0010    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0011    // copies of the Software, and to permit persons to whom the Software is
0012    // furnished to do so, subject to the following conditions:
0013    //
0014    // The above copyright notice and this permission notice shall be included in all
0015    // copies or substantial portions of the Software.
0016    //
0017    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0020    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0022    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0023    // SOFTWARE.
0024    
0025    #if os(Linux)
0026        import Glibc
0027    #else
0028        import Darwin.C
0029    #endif
0030    
0031    struct RegexError
Regex.swift:34
    static func errorFromResult(result: Int32, preg: regex_t) -> RegexError {
Regex.swift:39
        return RegexError(description: description)
Regex.swift:75
            throw RegexError.errorFromResult(result, preg: preg)
: ErrorType { 0032 let description: String 0033 0034 static func errorFromResult
Regex.swift:75
            throw RegexError.errorFromResult(result, preg: preg)
(result: Int32, preg: regex_t) -> RegexError { 0035 var preg = preg 0036 var buffer = [Int8](count: Int(BUFSIZ), repeatedValue: 0) 0037 regerror(result, &preg, &buffer, buffer.count) 0038 let description = String.fromCString(buffer)! 0039 return RegexError(description: description) 0040 } 0041 } 0042 0043 public final class Regex { 0044 public struct RegexOptions
Regex.swift:51
        public static let Basic =            RegexOptions(rawValue: 0)
Regex.swift:52
        public static let Extended =         RegexOptions(rawValue: 1)
Regex.swift:53
        public static let CaseInsensitive =  RegexOptions(rawValue: 2)
Regex.swift:54
        public static let ResultOnly =       RegexOptions(rawValue: 8)
Regex.swift:55
        public static let NewLineSensitive = RegexOptions(rawValue: 4)
Regex.swift:71
    public init(pattern: String, options: RegexOptions = [.Extended]) throws {
: OptionSetType { 0045 public let rawValue
Regex.swift:48
            self.rawValue = rawValue
Regex.swift:72
        let result = regcomp(&preg, pattern, options.rawValue)
: Int32 0046 0047 public init
Regex.swift:51
        public static let Basic =            RegexOptions(rawValue: 0)
Regex.swift:52
        public static let Extended =         RegexOptions(rawValue: 1)
Regex.swift:53
        public static let CaseInsensitive =  RegexOptions(rawValue: 2)
Regex.swift:54
        public static let ResultOnly =       RegexOptions(rawValue: 8)
Regex.swift:55
        public static let NewLineSensitive = RegexOptions(rawValue: 4)
(rawValue: Int32) { 0048 self.rawValue = rawValue 0049 } 0050 0051 public static let Basic = RegexOptions(rawValue: 0) 0052 public static let Extended
Regex.swift:71
    public init(pattern: String, options: RegexOptions = [.Extended]) throws {
= RegexOptions(rawValue: 1) 0053 public static let CaseInsensitive = RegexOptions(rawValue: 2) 0054 public static let ResultOnly = RegexOptions(rawValue: 8) 0055 public static let NewLineSensitive = RegexOptions(rawValue: 4) 0056 } 0057 0058 public struct MatchOptions
Regex.swift:65
        public static let FirstCharacterNotAtBeginningOfLine = MatchOptions(rawValue: REG_NOTBOL)
Regex.swift:66
        public static let LastCharacterNotAtEndOfLine =        MatchOptions(rawValue: REG_NOTEOL)
Regex.swift:83
    public func matches(string: String, options: MatchOptions = []) -> Bool {
Regex.swift:94
    public func groups(string: String, options: MatchOptions = []) -> [String] {
Regex.swift:128
    public func replace(string: String, withTemplate template: String, options: MatchOptions = []) -> String {
: OptionSetType { 0059 public let rawValue
Regex.swift:62
            self.rawValue = rawValue
Regex.swift:85
        let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
Regex.swift:101
            let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
Regex.swift:135
            let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
: Int32 0060 0061 public init
Regex.swift:65
        public static let FirstCharacterNotAtBeginningOfLine = MatchOptions(rawValue: REG_NOTBOL)
Regex.swift:66
        public static let LastCharacterNotAtEndOfLine =        MatchOptions(rawValue: REG_NOTEOL)
(rawValue: Int32) { 0062 self.rawValue = rawValue 0063 } 0064 0065 public static let FirstCharacterNotAtBeginningOfLine = MatchOptions(rawValue: REG_NOTBOL) 0066 public static let LastCharacterNotAtEndOfLine = MatchOptions(rawValue: REG_NOTEOL) 0067 } 0068 0069 var preg
Regex.swift:72
        let result = regcomp(&preg, pattern, options.rawValue)
Regex.swift:75
            throw RegexError.errorFromResult(result, preg: preg)
Regex.swift:80
        regfree(&preg)
Regex.swift:85
        let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
Regex.swift:101
            let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
Regex.swift:135
            let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue)
= regex_t() 0070 0071 public init(pattern: String, options: RegexOptions = [.Extended]) throws { 0072 let result = regcomp(&preg, pattern, options.rawValue) 0073 0074 if result != 0 { 0075 throw RegexError.errorFromResult(result, preg: preg) 0076 } 0077 } 0078 0079 deinit { 0080 regfree(&preg) 0081 } 0082 0083 public func matches(string: String, options: MatchOptions = []) -> Bool { 0084 var regexMatches = [regmatch_t](count: 1, repeatedValue: regmatch_t()) 0085 let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue) 0086 0087 if result == 1 { 0088 return false 0089 } 0090 0091 return true 0092 } 0093 0094 public func groups(string: String, options: MatchOptions = []) -> [String] { 0095 var string = string 0096 let maxMatches = 10 0097 var groups = [String]() 0098 0099 while true { 0100 var regexMatches = [regmatch_t](count: maxMatches, repeatedValue: regmatch_t()) 0101 let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue) 0102 0103 if result == 1 { 0104 break 0105 } 0106 0107 var j = 1 0108 0109 while regexMatches[j].rm_so != -1 { 0110 let start = Int(regexMatches[j].rm_so) 0111 let end = Int(regexMatches[j].rm_eo) 0112 let match = string[string.startIndex.advancedBy(start) ..< string.startIndex.advancedBy(end)] 0113 groups.append(match) 0114 j += 1 0115 } 0116 0117 let offset = Int(regexMatches[0].rm_eo) 0118 if let offsetString = String(string.utf8[string.utf8.startIndex.advancedBy(offset) ..< string.utf8.endIndex]) { 0119 string = offsetString 0120 } else { 0121 break 0122 } 0123 } 0124 0125 return groups 0126 } 0127 0128 public func replace(string: String, withTemplate template: String, options: MatchOptions = []) -> String { 0129 var string = string 0130 let maxMatches = 10 0131 var totalReplacedString: String = "" 0132 0133 while true { 0134 var regexMatches = [regmatch_t](count: maxMatches, repeatedValue: regmatch_t()) 0135 let result = regexec(&preg, string, regexMatches.count, &regexMatches, options.rawValue) 0136 0137 if result == 1 { 0138 break 0139 } 0140 0141 let start = Int(regexMatches[0].rm_so) 0142 let end = Int(regexMatches[0].rm_eo) 0143 0144 var replacedStringArray = Array<UInt8>(string.utf8) 0145 let templateArray = Array<UInt8>(template.utf8) 0146 replacedStringArray.replaceRange(start ..< end, with: templateArray) 0147 0148 guard let _replacedString = String(data: replacedStringArray) else { 0149 break 0150 } 0151 0152 var replacedString = _replacedString 0153 0154 let templateDelta = template.utf8.count - (end - start) 0155 let templateDeltaIndex = replacedString.utf8.startIndex.advancedBy(Int(end + templateDelta)) 0156 0157 replacedString = String(replacedString.utf8[replacedString.utf8.startIndex ..< templateDeltaIndex]) 0158 0159 totalReplacedString += replacedString 0160 string = String(string.utf8[string.utf8.startIndex.advancedBy(end) ..< string.utf8.endIndex]) 0161 } 0162 0163 return totalReplacedString + string 0164 } 0165 }