Skip to content

Commit

Permalink
Fix JSON bug and add JSON schema
Browse files Browse the repository at this point in the history
* Fix long string values in json parser

This fixes a core issue in the JSON parser, it uses a shared buffer of 8kb to avoid excessive allocations while it null-terminates strings coming from YAJL.

Unfortunately I never actually implemented it properly for values over 8kb as the code never memcpy'd or did anything to actually represent the string.

* add JSONSchema
  • Loading branch information
robertjpayne authored and paulofaria committed Jun 9, 2017
1 parent a63a245 commit ecbc083
Show file tree
Hide file tree
Showing 5 changed files with 894 additions and 640 deletions.
62 changes: 62 additions & 0 deletions Sources/Content/JSON/JSON.swift
Expand Up @@ -97,6 +97,68 @@ extension JSON {
}
}

extension JSON {
public var isNull: Bool {
if case .null = self {
return true
}

return false
}

public var isBool: Bool {
if case .bool = self {
return true
}

return false
}

public var isNumber: Bool {
return isDouble || isInt
}

public var isDouble: Bool {
if case .double = self {
return true
}

return false
}

public var isInt: Bool {
if case .int = self {
return true
}

return false
}

public var isString: Bool {
if case .string = self {
return true
}

return false
}

public var isArray: Bool {
if case .array = self {
return true
}

return false
}

public var isObject: Bool {
if case .object = self {
return true
}

return false
}
}

extension JSON {
public func get<T : JSONInitializable>(_ indexPath: IndexPathComponent...) throws -> T {
let content = try _get(indexPath as [IndexPathComponent])
Expand Down
36 changes: 36 additions & 0 deletions Sources/Content/JSON/JSONConvertible.swift
Expand Up @@ -154,3 +154,39 @@ extension Array : JSONInitializable {
self = this
}
}

protocol MapDictionaryKeyInitializable {
init(mapDictionaryKey: String)
}

extension String : MapDictionaryKeyInitializable {
init(mapDictionaryKey: String) {
self = mapDictionaryKey
}
}

extension Dictionary : JSONInitializable {
public init(json: JSON) throws {
guard case .object(let object) = json else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
}

guard let keyInitializable = Key.self as? MapDictionaryKeyInitializable.Type else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
}

guard let valueInitializable = Value.self as? JSONInitializable.Type else {
throw JSONError.cannotInitialize(type: type(of: self), json: json)
}

var this = Dictionary(minimumCapacity: object.count)

for (key, value) in object {
if let key = keyInitializable.init(mapDictionaryKey: key) as? Key {
this[key] = try valueInitializable.init(json: value) as? Value
}
}

self = this
}
}
18 changes: 10 additions & 8 deletions Sources/Content/JSON/JSONParser.swift
Expand Up @@ -339,10 +339,11 @@ fileprivate func yajl_string(
parser.buffer[bufferLength] = 0
string = String(cString: UnsafePointer(parser.buffer))
} else {
var buffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength + 1)
defer { buffer.deallocate(capacity: bufferLength + 1) }
buffer[bufferLength] = 0
string = String(cString: UnsafePointer(buffer))
var newBuffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength + 1)
defer { newBuffer.deallocate(capacity: bufferLength + 1) }
memcpy(UnsafeMutableRawPointer(newBuffer), buffer, bufferLength)
newBuffer[bufferLength] = 0
string = String(cString: UnsafePointer(newBuffer))
}
} else {
string = ""
Expand Down Expand Up @@ -374,10 +375,11 @@ fileprivate func yajl_map_key(
parser.buffer[bufferLength] = 0
string = String(cString: UnsafePointer(parser.buffer))
} else {
var buffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength + 1)
defer { buffer.deallocate(capacity: bufferLength + 1) }
buffer[bufferLength] = 0
string = String(cString: UnsafePointer(buffer))
var newBuffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength + 1)
defer { newBuffer.deallocate(capacity: bufferLength + 1) }
memcpy(UnsafeMutableRawPointer(newBuffer), buffer, bufferLength)
newBuffer[bufferLength] = 0
string = String(cString: UnsafePointer(newBuffer))
}
} else {
string = ""
Expand Down

0 comments on commit ecbc083

Please sign in to comment.