diff --git a/Sources/FoundationEssentials/JSON/JSONScanner.swift b/Sources/FoundationEssentials/JSON/JSONScanner.swift index f78c3637b..9f368cb97 100644 --- a/Sources/FoundationEssentials/JSON/JSONScanner.swift +++ b/Sources/FoundationEssentials/JSON/JSONScanner.swift @@ -265,6 +265,7 @@ internal struct JSONScanner { var reader: DocumentReader var depth: Int = 0 var partialMap = JSONPartialMapData() + private static let maximumRecursionDepth = 512 internal struct Options { var assumesTopLevelDictionary = false @@ -412,7 +413,7 @@ internal struct JSONScanner { mutating func scanArray() throws { let firstChar = reader.read() precondition(firstChar == ._openbracket) - guard self.depth < 512 else { + guard self.depth < Self.maximumRecursionDepth else { throw JSONError.tooManyNestedArraysOrDictionaries(location: reader.sourceLocation(atOffset: 1)) } self.depth &+= 1 @@ -470,7 +471,7 @@ internal struct JSONScanner { mutating func scanObject() throws { let firstChar = self.reader.read() precondition(firstChar == ._openbrace) - guard self.depth < 512 else { + guard self.depth < Self.maximumRecursionDepth else { throw JSONError.tooManyNestedArraysOrDictionaries(location: reader.sourceLocation(atOffset: -1)) } try scanObject(withoutBraces: false) diff --git a/Sources/FoundationEssentials/JSON/JSONWriter.swift b/Sources/FoundationEssentials/JSON/JSONWriter.swift index 2ecf8b7b5..b8ff000a7 100644 --- a/Sources/FoundationEssentials/JSON/JSONWriter.swift +++ b/Sources/FoundationEssentials/JSON/JSONWriter.swift @@ -29,6 +29,9 @@ internal struct JSONWriter { } mutating func serializeJSON(_ value: JSONEncoderValue, depth: Int = 0) throws { + guard depth < Self.maximumRecursionDepth else { + throw JSONError.tooManyNestedArraysOrDictionaries() + } switch value { case .string(let str): serializeString(str) @@ -172,10 +175,6 @@ internal struct JSONWriter { } mutating func serializeArray(_ array: [JSONEncoderValue], depth: Int) throws { - guard depth < Self.maximumRecursionDepth else { - throw JSONError.tooManyNestedArraysOrDictionaries() - } - writer(ascii: ._openbracket) if pretty { writer(ascii: ._newline) @@ -204,10 +203,6 @@ internal struct JSONWriter { } mutating func serializePreformattedByteArray(_ bytes: [UInt8], _ lengths: [Int], depth: Int) throws { - guard depth < Self.maximumRecursionDepth else { - throw JSONError.tooManyNestedArraysOrDictionaries() - } - writer(ascii: ._openbracket) if pretty { writer(ascii: ._newline) @@ -242,10 +237,6 @@ internal struct JSONWriter { } mutating func serializeObject(_ dict: [String:JSONEncoderValue], depth: Int) throws { - guard depth < Self.maximumRecursionDepth else { - throw JSONError.tooManyNestedArraysOrDictionaries() - } - writer(ascii: ._openbrace) if pretty { writer(ascii: ._newline) diff --git a/Tests/FoundationEssentialsTests/JSONEncoderTests.swift b/Tests/FoundationEssentialsTests/JSONEncoderTests.swift index 6697df493..3b18e0baa 100644 --- a/Tests/FoundationEssentialsTests/JSONEncoderTests.swift +++ b/Tests/FoundationEssentialsTests/JSONEncoderTests.swift @@ -2492,13 +2492,19 @@ extension JSONEncoderTests { prettyPrintEncoder.outputFormatting = .prettyPrinted for encoder in [JSONEncoder(), prettyPrintEncoder] { - let reencodedData = try! encoder.encode(decoded) - let redecodedObjects = try! decoder.decode(T.self, from: reencodedData) - XCTAssertEqual(decoded, redecodedObjects) - - if let plistData { - let decodedPlistObjects = try! PropertyListDecoder().decode(T.self, from: plistData) - XCTAssertEqual(decoded, decodedPlistObjects) + do { + let reencodedData = try encoder.encode(decoded) + let redecodedObjects = try decoder.decode(T.self, from: reencodedData) + XCTAssertEqual(decoded, redecodedObjects) + + if let plistData { + let decodedPlistObjects = try PropertyListDecoder().decode(T.self, from: plistData) + XCTAssertEqual(decoded, decodedPlistObjects) + + } + } + catch { + XCTFail("Pass test \"\(name) failed with error: \(error)") } } } @@ -2523,6 +2529,10 @@ extension JSONEncoderTests { _run_passTest(name: "pass13", type: JSONPass.Test13.self) _run_passTest(name: "pass14", type: JSONPass.Test14.self) _run_passTest(name: "pass15", type: JSONPass.Test15.self) + // FIXME: Fix platform-specific crash on Windows, skipping test case for now +#if !os(Windows) + _run_passTest(name: "pass16", type: JSONPass.Test16.self) +#endif } func test_json5PassJSONFiles() { @@ -2587,6 +2597,7 @@ extension JSONEncoderTests { _run_failTest(name: "fail39", type: JSONFail.Test39.self) _run_failTest(name: "fail40", type: JSONFail.Test40.self) _run_failTest(name: "fail41", type: JSONFail.Test41.self) + _run_failTest(name: "fail42", type: JSONFail.Test42.self) } @@ -4368,6 +4379,12 @@ extension JSONPass { } } +extension JSONPass { + struct Test16: Codable, Equatable { + var nestedArray: [Test16]? + } +} + enum JSONFail { typealias Test1 = String typealias Test2 = [String] @@ -4409,6 +4426,7 @@ enum JSONFail { typealias Test39 = [String:String] typealias Test40 = [String:String] typealias Test41 = [String:String] + typealias Test42 = JSONPass.Test16 } enum JSON5Pass { } diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail42.json b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail42.json new file mode 100644 index 000000000..4263f00ee --- /dev/null +++ b/Tests/FoundationEssentialsTests/Resources/JSON/fail/fail42.json @@ -0,0 +1,1027 @@ +{"nestedArray": [{ + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + +]} diff --git a/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass16.json b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass16.json new file mode 100644 index 000000000..1d0f0c9b5 --- /dev/null +++ b/Tests/FoundationEssentialsTests/Resources/JSON/pass/pass16.json @@ -0,0 +1,1025 @@ +{ + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + { + "nestedArray":[ + + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +}