<commit_before>//
//  RegularExpressions.swift
//  PhoneNumberKit
//
//  Created by <NAME> on 04/10/2015.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

class RegularExpressions {
        
    var regularExpresions = [String : NSRegularExpression]()

    var phoneDataDetector: NSDataDetector? = {
        do {
            let dataDetector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
            return dataDetector
        }
        catch {
            return nil
        }
    }()
    
    var spaceCharacterSet: CharacterSet = {
        let characterSet = NSMutableCharacterSet(charactersIn: "\u{00a0}")
        characterSet.formUnion(with: CharacterSet.whitespacesAndNewlines)
        return characterSet as CharacterSet
    }()
    
    deinit {
        regularExpresions.removeAll()
        phoneDataDetector = nil
    }

    // MARK: Regular expression
    
    func regexWithPattern(_ pattern: String) throws -> NSRegularExpression {
        if let regex = regularExpresions[pattern] {
            return regex
        }
        else {
            do {
                let currentPattern: NSRegularExpression
                currentPattern =  try NSRegularExpression(pattern: pattern, options:NSRegularExpression.Options.caseInsensitive)
                regularExpresions[pattern] = currentPattern
                return currentPattern
            }
            catch {
                throw PhoneNumberError.generalError
            }
        }
    }
    
    func regexMatches(_ pattern: String, string: String) throws -> [NSTextCheckingResult] {
        do {
            let internalString = string
            let currentPattern =  try regexWithPattern(pattern)
            let matches = currentPattern.matches(in: internalString)
            return matches
        }
        catch {
            throw PhoneNumberError.generalError
        }
    }
    
    func phoneDataDetectorMatches(_ string: String) throws -> [NSTextCheckingResult] {
        guard let matches = phoneDataDetector?.matches(in: string) else {
            throw PhoneNumberError.generalError
        }
        if matches.isEmpty == false {
            return matches
        }
        else {
            let fallBackMatches = try regexMatches(PhoneNumberPatterns.validPhoneNumberPattern, string: string)<commit_msg>Introduce basic thread safety to regular expression pool<commit_after>//
//  RegularExpressions.swift
//  PhoneNumberKit
//
//  Created by <NAME> on 04/10/2015.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

class RegularExpressions {
        
    var _regularExpresions = [String : NSRegularExpression]()
    
    var regularExpresions: [String : NSRegularExpression] {
        var regularExpresionsCopy: [String : NSRegularExpression]!
        concurrentRegexQueue.sync {
            regularExpresionsCopy = self._regularExpresions
        }
        return regularExpresionsCopy
    }
    private let concurrentRegexQueue = DispatchQueue(label: "com.phonenumberkit.regexqueue", qos: .default, attributes: .concurrent)

    func addRegularExpression(regex: NSRegularExpression, pattern: String) {
        concurrentRegexQueue.async(flags: .barrier) {
            self._regularExpresions[pattern] = regex
        }
    }
    
    var phoneDataDetector: NSDataDetector? = {
        do {
            let dataDetector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
            return dataDetector
        }
        catch {
            return nil
        }
    }()
    
    var spaceCharacterSet: CharacterSet = {
        let characterSet = NSMutableCharacterSet(charactersIn: "\u{00a0}")
        characterSet.formUnion(with: CharacterSet.whitespacesAndNewlines)
        return characterSet as CharacterSet
    }()
    
    deinit {
        _regularExpresions.removeAll()
        phoneDataDetector = nil
    }

    // MARK: Regular expression
    
    func regexWithPattern(_ pattern: String) throws -> NSRegularExpression {
        if let regex = regularExpresions[pattern] {
            return regex
        }
        else {
            do {
                let currentPattern: NSRegularExpression
                currentPattern =  try NSRegularExpression(pattern: pattern, options:NSRegularExpression.Options.caseInsensitive)
                self.addRegularExpression(regex: currentPattern, pattern: pattern)
                return currentPattern
            }
            catch {
                throw PhoneNumberError.generalError
            }
        }
    }
    
    func regexMatches(_ pattern: String, string: String) throws -> [NSTextCheckingResult] {
        do {
            let internalString = string
            let currentPattern =  try regexWithPattern(pattern)
            let matches = currentPattern.matches(in: internalString)
            return matches
        }
        catch {
            throw PhoneNumberError.generalError
        }
    }
    
    func phoneDataDetectorMatches(_ string: String) throws -> [NSTextCheckingResult] {
        guard let matches = phoneDataDetector?.matches(in: string) else {
            throw PhoneNumberError.generalError
        }
        if matches.isEmpty == false {
            return matches
        }
        else {
            let fallBackMatches = try regexMatches(PhoneNumberPatterns.validPhoneNumberPattern, string: string)
{'fraction_non_alphanumeric': 0.07112506927766488, 'fraction_numerical': 0.005542213190467393, 'mean_word_length': 2.1385507246376814, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6598911', 'n_tokens_mistral': 1412, 'n_tokens_neox': 1350, 'n_words': 313}