<commit_before>//
//  MMDB.swift
//  MMDB
//
//  Created by Lex on 12/16/15.
//  Copyright © 2015 <EMAIL>. All rights reserved.
//

import Foundation

public struct MMDBContinent {
    public var code: String?
    public var names: [String: String]?
}

public struct MMDBCountry: CustomStringConvertible {
    public var continent = MMDBContinent()
    public var isoCode = ""
    public var names = [String: String]()

    init(dictionary: NSDictionary) {
        if let dict = dictionary["continent"] as? NSDictionary,
            let code = dict["code"] as? String,
            let continentNames = dict["names"] as? [String: String]
        {
            continent.code = code
            continent.names = continentNames
        }
        if let dict = dictionary["country"] as? NSDictionary,
            let iso = dict["iso_code"] as? String,
            let countryNames = dict["names"] as? [String: String]
        {
            self.isoCode = iso
            self.names = countryNames
        }
    }
    
    public var description: String {
        var s = "{\n"
        s += "  \"continent\": {\n"
        s += "    \"code\": \"" + (self.continent.code ?? "") + "\",\n"
        s += "    \"names\": {\n"
        var i = continent.names?.count ?? 0
        continent.names?.forEach {
            s += "      \""
            s += $0.0 + ": \""
            s += $0.1 + "\""
            s += (i > 1 ? "," : "")
            s += "\n"
            i -= 1
        }
        s += "    }\n"
        s += "  },\n"
        s += "  \"isoCode\": \"" + self.isoCode + "\",\n"
        s += "  \"names\": {\n"
        i = names.count
        names.forEach {
            s += "    \""
            s += $0.0 + ": \""
            s += $0.1 + "\""
            s += (i > 1 ? "," : "")
            s += "\n"
            i -= 1
        }
        s += "  }\n}"
        return s
    }
}

final public class MMDB {

    fileprivate var db = MMDB_s()

    fileprivate typealias ListPtr = UnsafeMutablePointer<MMDB_entry_data_list_s>
    fileprivate typealias StringPtr = UnsafeMutablePointer<String>

    public init?(_ filename: String = "") {
        var cfilename = (filename as NSString).utf8String
        var cfilenamePtr = UnsafePointer<Int8>(cfilename)

        var status = MMDB_open(cfilenamePtr, UInt32(MMDB_MODE_MASK), &db)
        if status != MMDB_SUCCESS {
            print(String(cString: MMDB_strerror(errno)))
            // Failover to db in bundle
            let bundle = Bundle(for: MMDB.self)
            guard let path =
                bundle.path(forResource: "GeoLite2-Country", ofType: "mmdb") else {
                    return nil
            }
            cfilename = (path as NSString).utf8String
            cfilenamePtr = UnsafePointer<Int8>(cfilename)
            status = MMDB_open(cfilenamePtr, UInt32(MMDB_MODE_MASK), &db)
            if status != MMDB_SUCCESS {
                print(String(cString: MMDB_strerror(errno)))
                return nil
            }
        }
    }

    fileprivate func lookupString(_ s: String) -> MMDB_lookup_result_s? {
        let string = (s as NSString).utf8String
        let stringPtr = UnsafePointer<Int8>(string)

        var gaiError: Int32 = 0
        var error: Int32 = 0

        let result = MMDB_lookup_string(&db, stringPtr, &gaiError, &error)
        if gaiError == noErr && error == noErr {
            return result
        }
        return nil
    }


    fileprivate func getString(_ list: ListPtr) -> String {
        var data = list.pointee.entry_data
        let type = (Int32)(data.type)

        // Ignore other useless keys<commit_msg>refactoring failable initializer of MMDB. won't print error when create MMDB without filename parameter.<commit_after>//
//  MMDB.swift
//  MMDB
//
//  Created by Lex on 12/16/15.
//  Copyright © 2015 <EMAIL>. All rights reserved.
//

import Foundation

public struct MMDBContinent {
    public var code: String?
    public var names: [String: String]?
}

public struct MMDBCountry: CustomStringConvertible {
    public var continent = MMDBContinent()
    public var isoCode = ""
    public var names = [String: String]()

    init(dictionary: NSDictionary) {
        if let dict = dictionary["continent"] as? NSDictionary,
            let code = dict["code"] as? String,
            let continentNames = dict["names"] as? [String: String]
        {
            continent.code = code
            continent.names = continentNames
        }
        if let dict = dictionary["country"] as? NSDictionary,
            let iso = dict["iso_code"] as? String,
            let countryNames = dict["names"] as? [String: String]
        {
            self.isoCode = iso
            self.names = countryNames
        }
    }
    
    public var description: String {
        var s = "{\n"
        s += "  \"continent\": {\n"
        s += "    \"code\": \"" + (self.continent.code ?? "") + "\",\n"
        s += "    \"names\": {\n"
        var i = continent.names?.count ?? 0
        continent.names?.forEach {
            s += "      \""
            s += $0.0 + ": \""
            s += $0.1 + "\""
            s += (i > 1 ? "," : "")
            s += "\n"
            i -= 1
        }
        s += "    }\n"
        s += "  },\n"
        s += "  \"isoCode\": \"" + self.isoCode + "\",\n"
        s += "  \"names\": {\n"
        i = names.count
        names.forEach {
            s += "    \""
            s += $0.0 + ": \""
            s += $0.1 + "\""
            s += (i > 1 ? "," : "")
            s += "\n"
            i -= 1
        }
        s += "  }\n}"
        return s
    }
}

final public class MMDB {

    fileprivate var db = MMDB_s()

    fileprivate typealias ListPtr = UnsafeMutablePointer<MMDB_entry_data_list_s>
    fileprivate typealias StringPtr = UnsafeMutablePointer<String>

    public init?(_ filename: String? = nil) {
        if let filename = filename, openDB(atPath: filename) { return }

        let path = Bundle(for: MMDB.self).path(forResource: "GeoLite2-Country", ofType: "mmdb")
        if let path = path, openDB(atPath: path) { return }

        return nil
    }
    private func openDB(atPath: String) -> Bool {
        let cfilename = (atPath as NSString).utf8String
        let cfilenamePtr = UnsafePointer<Int8>(cfilename)
        let status = MMDB_open(cfilenamePtr, UInt32(MMDB_MODE_MASK), &db)
        if status != MMDB_SUCCESS {
            print(String(cString: MMDB_strerror(errno)))
            return false
        } else {
            return true
        }
    }

    fileprivate func lookupString(_ s: String) -> MMDB_lookup_result_s? {
        let string = (s as NSString).utf8String
        let stringPtr = UnsafePointer<Int8>(string)

        var gaiError: Int32 = 0
        var error: Int32 = 0

        let result = MMDB_lookup_string(&db, stringPtr, &gaiError, &error)
        if gaiError == noErr && error == noErr {
            return result
        }
        return nil
    }


    fileprivate func getString(_ list: ListPtr) -> String {
        var data = list.pointee.entry_data
        let type = (Int32)(data.type)

        // Ignore other useless keys
{'fraction_non_alphanumeric': 0.13252842903271095, 'fraction_numerical': 0.011231222799382283, 'mean_word_length': 1.6995073891625616, 'pattern_counts': {'":': 14, '<': 14, '<?xml version=': 0, '>': 23, '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': '7441883', 'n_tokens_mistral': 2238, 'n_tokens_neox': 2158, 'n_words': 570}