<commit_before>//
//  OperatorAndFunctions.swift
//  xcconfig-extractor
//
//  Created by <NAME> on 2017/04/27.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import Foundation
import PathKit

func compare(_ l: Any, _ r: Any) -> Bool {
    switch l {
    case let ls as String:
        if let rs = r as? String {
            return ls == rs
        } else {
            return false
        }
    case let ls as [String: Any]:
        if let rs = r as? [String: Any] {
            return ls == rs
        } else {
            return false
        }
    case let ls as [Any]:
        if let rs = r as? [Any] {
            guard ls.count == rs.count else { return false }
            for i in (0..<ls.count).map({ $0 }) {
                if compare(ls[i], rs[i]) == false {
                    return false
                }
            }
            return true
        } else {
            return false
        }
    default:
        return false
    }
}

func convertToLines(_ dictionary: [String: Any]) -> [String] {
    let result = dictionary.map { (k, v) -> String in
        switch v {
        case let s as String:
            return "\(k) = \(s)"
        case let s as [String]:
            return "\(k) = \(s.map{$0}.joined(separator: " "))"
        case is [String: Any]:
            fatalError("Unexpected Object. Please file an issue if you believe this as a bug.")
        default:
            fatalError("Unexpected Object. Please file an issue if you believe this as a bug.")
        }
    }
    return result
}

func format(_ result: [String], with includes: [String] = []) -> [String] {
    return header + includes.map {"#include \"\($0)\""} + result + ["\n"]
}

func write(to path: Path, settings: [String], includes: [String] = []) throws {
    let formatted = format(settings, with: includes)
    let data = (formatted.joined(separator: "\n") as NSString).data(using: String.Encoding.utf8.rawValue)!
    try path.write(data)
}

extension Array where Element == [String] {
    func filterCommon() -> [String] {
        func _filterCommon(acc: [String]?, values: [String]) -> [String]? {
            if acc == nil {
                return values
            } else {
                var r = acc!
                for i in (0..<r.count).reversed() {
                    let v = r[i]
                    if values.contains(v) {
                        continue
                    } else {
                        r.remove(at: i)
                    }
                }
                return r
            }
        }
        return reduce(Optional<[String]>.none, _filterCommon)!
    }
}

// MARK: Operators
infix operator +|
func +|<T: Equatable>(l: [T], r: [T]) -> [T] {
    var o = l
    o.append(contentsOf: r)
    return o
}
func -<T: Equatable>(l: [T], r: [T]) -> [T] {
    return l.filter { t in r.contains(t) == false }
}<commit_msg>Fix crash bug<commit_after>//
//  OperatorAndFunctions.swift
//  xcconfig-extractor
//
//  Created by <NAME> on 2017/04/27.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import Foundation
import PathKit

func compare(_ l: Any, _ r: Any) -> Bool {
    switch l {
    case let ls as String:
        if let rs = r as? String {
            return ls == rs
        } else {
            return false
        }
    case let ls as [String: Any]:
        if let rs = r as? [String: Any] {
            return ls == rs
        } else {
            return false
        }
    case let ls as [Any]:
        if let rs = r as? [Any] {
            guard ls.count == rs.count else { return false }
            for i in (0..<ls.count).map({ $0 }) {
                if compare(ls[i], rs[i]) == false {
                    return false
                }
            }
            return true
        } else {
            return false
        }
    default:
        return false
    }
}

func convertToLines(_ dictionary: [String: Any]) -> [String] {
    let result = dictionary.map { (k, v) -> String in
        switch v {
        case let s as String:
            return "\(k) = \(s)"
        case let s as [String]:
            return "\(k) = \(s.map{$0}.joined(separator: " "))"
        case is [String: Any]:
            fatalError("Unexpected Object. Please file an issue if you believe this as a bug.")
        default:
            fatalError("Unexpected Object. Please file an issue if you believe this as a bug.")
        }
    }
    return result
}

func format(_ result: [String], with includes: [String] = []) -> [String] {
    return header + includes.map {"#include \"\($0)\""} + result + ["\n"]
}

func write(to path: Path, settings: [String], includes: [String] = []) throws {
    let formatted = format(settings, with: includes)
    let data = (formatted.joined(separator: "\n") as NSString).data(using: String.Encoding.utf8.rawValue)!
    try path.write(data)
}

extension Array where Element == [String] {
    func filterCommon() -> [String] {
        func _filterCommon(acc: [String]?, values: [String]) -> [String]? {
            if acc == nil {
                return values
            } else {
                var r = acc!
                for i in (0..<r.count).reversed() {
                    let v = r[i]
                    if values.contains(v) {
                        continue
                    } else {
                        r.remove(at: i)
                    }
                }
                return r
            }
        }
        if self.isEmpty {
            return []
        }
        return reduce(Optional<[String]>.none, _filterCommon)!
    }
}

// MARK: Operators
infix operator +|
func +|<T: Equatable>(l: [T], r: [T]) -> [T] {
    var o = l
    o.append(contentsOf: r)
    return o
}
func -<T: Equatable>(l: [T], r: [T]) -> [T] {
    return l.filter { t in r.contains(t) == false }
}
{'fraction_non_alphanumeric': 0.13592400690846287, 'fraction_numerical': 0.0062176165803108805, 'mean_word_length': 1.5112749349522983, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, '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': '107672', 'n_tokens_mistral': 1775, 'n_tokens_neox': 1691, 'n_words': 553}