<commit_before>//
//  main.swift
//  gir2swift
//
//  Created by <NAME> on 22/03/2016.
//  Copyright © 2016, 2017 <NAME>. All rights reserved.
//
#if os(Linux)
    import Glibc
#else
    import Darwin
#endif
import Dispatch

/// verbose output
var verbose = false

func usage() -> Never  {
    fputs("Usage: \(CommandLine.arguments[0]) [-v][-s][-m module_boilerplate.swift]{-p file.gir}[file.gir ...]\n", stderr)
    exit(EXIT_FAILURE)
}

/// load a GIR file, then invoke the processing closure
func load_gir(_ file: String, quiet q: Bool = false, process: (GIR) -> Void =  { _ in }) {
    with_mmap(file) { (content: UnsafeBufferPointer<CChar>) in
        guard let gir = GIR(buffer: content, quiet: q) else {
            perror("Cannot parse GIR file '\(file)'")
            return
        }
        if gir.prefix.isEmpty {
            fputs("Warning: no namespace in GIR file '\(file)'\n", stderr)
        }
        process(gir);
    }
}


/// pre-load a GIR without processing, but adding to known types / records
func preload_gir(file: String) {
    load_gir(file, quiet: true)
}


/// process a GIR file
func process_gir(file: String, boilerPlate modulePrefix: String, to outputDirectory: String? = nil, split singleFilePerClass: Bool = false) {
    let base = file.baseName
    let node = base.stringByRemoving(suffix: ".gir") ?? base
    let wlfile = node + ".whitelist"
    if let whitelist = String(contentsOfFile: wlfile, quiet: true)?.lines.asSet {
        for name in whitelist {
            GIR.KnownTypes.removeValue(forKey: name)
            GIR.KnownRecords.removeValue(forKey: name)
            GIR.KnownFunctions.removeValue(forKey: name)
        }
    }

    load_gir(file) { gir in
        processSpecialCases(gir, forFile: node)
        let blacklist = GIR.Blacklist
        let boilerplate = gir.boilerPlate
        let preamble = gir.preamble
        let prefix = modulePrefix + boilerplate
        let queues = DispatchGroup()
        let background = DispatchQueue.global()
        let outq = DispatchQueue(label: "com.github.rhx.gir2swift.outputqueue")
        if outputDirectory == nil { print(prefix + preamble) }

        func write(_ string: String, to fileName: String) {
            do {
                try string.writeTo(file: fileName)
            } catch {
                outq.async(group: queues) { fputs("\(error)\n", stderr) }
            }
        }
        func writebg(_ string: String, to fileName: String) {
            background.async(group: queues) { write(string, to: fileName) }
        }
        func write<T: GIR.Record>(_ types: [T], using convert: (GIR.Record) -> String) {
            if let dir = outputDirectory {
                writebg(prefix, to: "\(dir)/\(node).swift")
                var output = preamble
                var first: Character? = nil
                var firstName = ""
                for type in types {
                    let name = type.className
                    let code = convert(type)
                    output += code + "\n\n"
                    guard let firstChar = name.characters.first else { continue }
                    guard singleFilePerClass || ( first != nil && first != firstChar ) else {
                        if first == nil {
                            first = firstChar
                            firstName = name + "-"
                        }
                        continue
                    }
                    let f = "\(dir)/\(node)-\(firstName)\(name).swift"
                    writebg(output, to: f)
                    output = preamble<commit_msg>Avoid repeating global prefix<commit_after>//
//  main.swift
//  gir2swift
//
//  Created by <NAME> on 22/03/2016.
//  Copyright © 2016, 2017 <NAME>. All rights reserved.
//
#if os(Linux)
    import Glibc
#else
    import Darwin
#endif
import Dispatch

/// verbose output
var verbose = false

func usage() -> Never  {
    fputs("Usage: \(CommandLine.arguments[0]) [-v][-s][-m module_boilerplate.swift]{-p file.gir}[file.gir ...]\n", stderr)
    exit(EXIT_FAILURE)
}

/// load a GIR file, then invoke the processing closure
func load_gir(_ file: String, quiet q: Bool = false, process: (GIR) -> Void =  { _ in }) {
    with_mmap(file) { (content: UnsafeBufferPointer<CChar>) in
        guard let gir = GIR(buffer: content, quiet: q) else {
            perror("Cannot parse GIR file '\(file)'")
            return
        }
        if gir.prefix.isEmpty {
            fputs("Warning: no namespace in GIR file '\(file)'\n", stderr)
        }
        process(gir);
    }
}


/// pre-load a GIR without processing, but adding to known types / records
func preload_gir(file: String) {
    load_gir(file, quiet: true)
}


/// process a GIR file
func process_gir(file: String, boilerPlate modulePrefix: String, to outputDirectory: String? = nil, split singleFilePerClass: Bool = false) {
    let base = file.baseName
    let node = base.stringByRemoving(suffix: ".gir") ?? base
    let wlfile = node + ".whitelist"
    if let whitelist = String(contentsOfFile: wlfile, quiet: true)?.lines.asSet {
        for name in whitelist {
            GIR.KnownTypes.removeValue(forKey: name)
            GIR.KnownRecords.removeValue(forKey: name)
            GIR.KnownFunctions.removeValue(forKey: name)
        }
    }

    load_gir(file) { gir in
        processSpecialCases(gir, forFile: node)
        let blacklist = GIR.Blacklist
        let boilerplate = gir.boilerPlate
        let prefix = gir.preamble
        let modulePrefix = modulePrefix + boilerplate
        let queues = DispatchGroup()
        let background = DispatchQueue.global()
        let outq = DispatchQueue(label: "com.github.rhx.gir2swift.outputqueue")
        if outputDirectory == nil { print(modulePrefix + prefix) }

        func write(_ string: String, to fileName: String) {
            do {
                try string.writeTo(file: fileName)
            } catch {
                outq.async(group: queues) { fputs("\(error)\n", stderr) }
            }
        }
        func writebg(_ string: String, to fileName: String) {
            background.async(group: queues) { write(string, to: fileName) }
        }
        func write<T: GIR.Record>(_ types: [T], using convert: (GIR.Record) -> String) {
            if let dir = outputDirectory {
                writebg(modulePrefix, to: "\(dir)/\(node).swift")
                var output = prefix
                var first: Character? = nil
                var firstName = ""
                for type in types {
                    let name = type.className
                    let code = convert(type)
                    output += code + "\n\n"
                    guard let firstChar = name.characters.first else { continue }
                    guard singleFilePerClass || ( first != nil && first != firstChar ) else {
                        if first == nil {
                            first = firstChar
                            firstName = name + "-"
                        }
                        continue
                    }
                    let f = "\(dir)/\(node)-\(firstName)\(name).swift"
                    writebg(output, to: f)
                    output = prefix
{'fraction_non_alphanumeric': 0.11414253897550111, 'fraction_numerical': 0.005289532293986637, 'mean_word_length': 1.8176470588235294, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, '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': '4467164', 'n_tokens_mistral': 2159, 'n_tokens_neox': 2041, 'n_words': 572}