<commit_before>//
//  JSON2.swift
//  THGModel
//
//  Created by <NAME> on 9/12/15.
//  Copyright © 2015 theholygrail. All rights reserved.
//

import Foundation

public enum JSONError: ErrorType {
    case InvalidJSON
}

public enum JSONType: Int {
    case Number
    case String
    case Bool
    case Array
    case Dictionary
    case Null
    case Unknown
}


public struct JSON {
    
    public var object: AnyObject?
    
    public init() {
        self.object = nil
    }
    
    public init(_ object: AnyObject?) {
        self.object = object
    }
    
    public init(json: JSON) {
        self.object = json.object
    }
    
    public init?(data: NSData?) {
        if let data = data {
            do {
                let object: AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
                self.object = object
            } catch let error as NSError {
                debugPrint(error)
            }
        }
        else {
            return nil
        }
    }
    
    public init?(path: String) {
        let exists = NSFileManager.defaultManager().fileExistsAtPath(path)
        if exists {
            let data = NSData(contentsOfFile: path)
            self.init(data: data)
        } else {
            return nil
        }
    }
    
    /**
    Initialize an instance given a JSON file contained within the bundle.
    
    - parameter bundle: The bundle to attempt to load from.
    - parameter string: A string containing the name of the file to load from resources.
    */
    public init?(bundleClass: AnyClass, filename: String) {
        let bundle = NSBundle(forClass: bundleClass)
        self.init(bundle: bundle, filename: filename)
    }

    public init?(bundle: NSBundle, filename: String) {
        let filepath: String? = bundle.pathForResource(filename, ofType: nil)
        if let filepath = filepath {
            self.init(path: filepath)
        } else {
            return nil
        }
    }

    public subscript(key: String) -> JSON? {
        set {
            if var tempObject = object as? [String : AnyObject] {
                tempObject[key] = newValue?.object
                self.object = tempObject
            }
            else {
                var tempObject: [String : AnyObject] = [:]
                tempObject[key] = newValue?.object
                self.object = tempObject
            }
        }
        get {
            /**
            NSDictionary is used because it currently performs better than a native Swift dictionary.
            The reason for this is that [String : AnyObject] is bridged to NSDictionary deep down the
            call stack, and this bridging operation is relatively expensive. Until Swift is ABI stable
            and/or doesn't require a bridge to Objective-C, NSDictionary will be used here
            */
            if let dictionary = object as? NSDictionary {
                let value = dictionary[key]
                if let value = value {
                    return JSON(value)
                }
            }
            
            return nil
        }
    }
}

extension JSON {
    func data() -> NSData? {
        if let object = object {
            return try? NSJSONSerialization.dataWithJSONObject(object, options: .PrettyPrinted)
        }
        return nil
    }
}

// MARK: - Types (Debugging)
extension JSON {
    public var type: JSONType {
        if let object = object {
            switch object {
            case is NSString:
                return .String
            case is NSArray:
                return .Array
            case is NSDictionary:
                return .Dictionary
            case is NSNumber:
                let number = object as! NSNumber
                let type = String.fromCString(number.objCType)!<commit_msg>Make data() public.<commit_after>//
//  JSON2.swift
//  THGModel
//
//  Created by <NAME> on 9/12/15.
//  Copyright © 2015 theholygrail. All rights reserved.
//

import Foundation

public enum JSONError: ErrorType {
    case InvalidJSON
}

public enum JSONType: Int {
    case Number
    case String
    case Bool
    case Array
    case Dictionary
    case Null
    case Unknown
}


public struct JSON {
    
    public var object: AnyObject?
    
    public init() {
        self.object = nil
    }
    
    public init(_ object: AnyObject?) {
        self.object = object
    }
    
    public init(json: JSON) {
        self.object = json.object
    }
    
    public init?(data: NSData?) {
        if let data = data {
            do {
                let object: AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
                self.object = object
            } catch let error as NSError {
                debugPrint(error)
            }
        }
        else {
            return nil
        }
    }
    
    public init?(path: String) {
        let exists = NSFileManager.defaultManager().fileExistsAtPath(path)
        if exists {
            let data = NSData(contentsOfFile: path)
            self.init(data: data)
        } else {
            return nil
        }
    }
    
    /**
    Initialize an instance given a JSON file contained within the bundle.
    
    - parameter bundle: The bundle to attempt to load from.
    - parameter string: A string containing the name of the file to load from resources.
    */
    public init?(bundleClass: AnyClass, filename: String) {
        let bundle = NSBundle(forClass: bundleClass)
        self.init(bundle: bundle, filename: filename)
    }

    public init?(bundle: NSBundle, filename: String) {
        let filepath: String? = bundle.pathForResource(filename, ofType: nil)
        if let filepath = filepath {
            self.init(path: filepath)
        } else {
            return nil
        }
    }

    public subscript(key: String) -> JSON? {
        set {
            if var tempObject = object as? [String : AnyObject] {
                tempObject[key] = newValue?.object
                self.object = tempObject
            }
            else {
                var tempObject: [String : AnyObject] = [:]
                tempObject[key] = newValue?.object
                self.object = tempObject
            }
        }
        get {
            /**
            NSDictionary is used because it currently performs better than a native Swift dictionary.
            The reason for this is that [String : AnyObject] is bridged to NSDictionary deep down the
            call stack, and this bridging operation is relatively expensive. Until Swift is ABI stable
            and/or doesn't require a bridge to Objective-C, NSDictionary will be used here
            */
            if let dictionary = object as? NSDictionary {
                let value = dictionary[key]
                if let value = value {
                    return JSON(value)
                }
            }
            
            return nil
        }
    }
}

extension JSON {
    public func data() -> NSData? {
        if let object = object {
            return try? NSJSONSerialization.dataWithJSONObject(object, options: .PrettyPrinted)
        }
        return nil
    }
}

// MARK: - Types (Debugging)
extension JSON {
    public var type: JSONType {
        if let object = object {
            switch object {
            case is NSString:
                return .String
            case is NSArray:
                return .Array
            case is NSDictionary:
                return .Dictionary
            case is NSNumber:
                let number = object as! NSNumber
                let type = String.fromCString(number.objCType)!
{'fraction_non_alphanumeric': 0.07404988899046624, 'fraction_numerical': 0.0026119890296460754, 'mean_word_length': 1.5450315719508143, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, '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': '5175296', 'n_tokens_mistral': 2025, 'n_tokens_neox': 1950, 'n_words': 656}