diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 04438854c..e07360ac9 100755 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -215,6 +215,10 @@ ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp testHarness_SRCS += ipAddrToAsciiTest.cpp TESTS += ipAddrToAsciiTest +TESTPROD_HOST += yajl_test +yajl_test_SRCS += yajl_test.c +TESTS += yajlTest + # The testHarness runs all the test programs in a known working order. testHarness_SRCS += epicsRunLibComTests.c diff --git a/src/libCom/test/yajlTest.plt b/src/libCom/test/yajlTest.plt new file mode 100644 index 000000000..5c9052032 --- /dev/null +++ b/src/libCom/test/yajlTest.plt @@ -0,0 +1,51 @@ +#!/usr/bin/perl +# +# This is a test director for running yajl JSON parser tests. +# The tests are actually defined in the yajlTestCases.pm module, +# which is generated from the yajl cases by yajlTestConverter.pl + +use strict; +use Test::More; +use IO::Handle; +use IPC::Open3; + +# Load test cases +use lib ".."; +use yajlTestCases; + +my @cases = cases(); +plan tests => scalar @cases; + +# The yajl_test program reads JSON from stdin and sends a description +# of what it got to stdout, with errors going to stderr. We merge the +# two output streams for the purpose of checking the test results. +my $prog = './yajl_test'; +$prog .= '.exe' if ($^O eq 'MSWin32') || ($^O eq 'cygwin'); + +foreach my $case (@cases) { + my $name = $case->{name}; + my @opts = @{$case->{opts}}; + my @input = @{$case->{input}}; + my @gives = @{$case->{gives}}; + + my ($rx, $tx); + my $pid = open3($tx, $rx, 0, $prog, @opts); + + # Send the test case, then EOF + print $tx join "\n", @input; + close $tx; + + # Receive the result + my @result; + while (!$rx->eof) { + chomp(my $line = <$rx>); + push @result, $line; + } + close $rx; + + # Clean up the child process + waitpid $pid, 0; + + # Report the result of this test case + is_deeply(\@result, \@gives, $name); +} diff --git a/src/libCom/test/yajlTestCases.pm b/src/libCom/test/yajlTestCases.pm new file mode 100644 index 000000000..9064df043 --- /dev/null +++ b/src/libCom/test/yajlTestCases.pm @@ -0,0 +1,3046 @@ +# Parser test cases from https://github.com/lloyd/yajl +# +# This file is generated, DO NOT EDIT! +# +# See comments in yajlTestConverter.pl for instructions on +# how to regenerate this file from the original yajl sources. + +sub cases { + my $VAR1 = [ + { + name => "difficult_json_c_test_case_with_comments", + opts => [ + "-c" + ], + input => [ + "{ \"glossary\": { /* you */ \"title\": /**/ \"example glossary\", /*should*/\"GlossDiv\": { \"title\": /*never*/\"S\", /*ever*/\"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", /*see*/\"GlossSeeAlso\"/*this*/:/*coming*/[/*out*/\"GML\"/*of*/,/*the*/\"XML\"/*parser!*/, \"markup\"] /*hey*/}/*ho*/]/*hey*/}/*ho*/} } // and the parser won't even get this far, so chill. /* hah!", + "" + ], + gives => [ + "map open '{'", + "key: 'glossary'", + "map open '{'", + "key: 'title'", + "string: 'example glossary'", + "key: 'GlossDiv'", + "map open '{'", + "key: 'title'", + "string: 'S'", + "key: 'GlossList'", + "array open '['", + "map open '{'", + "key: 'ID'", + "string: 'SGML'", + "key: 'SortAs'", + "string: 'SGML'", + "key: 'GlossTerm'", + "string: 'Standard Generalized Markup Language'", + "key: 'Acronym'", + "string: 'SGML'", + "key: 'Abbrev'", + "string: 'ISO 8879:1986'", + "key: 'GlossDef'", + "string: 'A meta-markup language, used to create markup languages such as DocBook.'", + "key: 'GlossSeeAlso'", + "array open '['", + "string: 'GML'", + "string: 'XML'", + "string: 'markup'", + "array close ']'", + "map close '}'", + "array close ']'", + "map close '}'", + "map close '}'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "simple_with_comments", + opts => [ + "-c" + ], + input => [ + "{", + " \"this\": \"is\", // ignore this", + " \"really\": \"simple\",", + " /* ignore", + "this", + "too * / ", + "** //", + "(/", + "******/", + " \"json\": \"right?\"", + "}", + "" + ], + gives => [ + "map open '{'", + "key: 'this'", + "string: 'is'", + "key: 'really'", + "string: 'simple'", + "key: 'json'", + "string: 'right?'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "false_then_garbage", + opts => [ + "-g" + ], + input => [ + "falsex" + ], + gives => [ + "bool: false", + "memory leaks:\t0" + ] + }, + { + name => "null_then_garbage", + opts => [ + "-g" + ], + input => [ + "nullx", + "" + ], + gives => [ + "null", + "memory leaks:\t0" + ] + }, + { + name => "true_then_garbage", + opts => [ + "-g" + ], + input => [ + "truex" + ], + gives => [ + "bool: true", + "memory leaks:\t0" + ] + }, + { + name => "eof", + opts => [ + "-m" + ], + input => [ + "{ \"123\":", + "" + ], + gives => [ + "map open '{'", + "key: '123'", + "parse error: premature EOF", + "memory leaks:\t0" + ] + }, + { + name => "integers", + opts => [ + "-m" + ], + input => [ + "1221 21", + "" + ], + gives => [ + "integer: 1221", + "integer: 21", + "memory leaks:\t0" + ] + }, + { + name => "multiple", + opts => [ + "-m" + ], + input => [ + "", + "{}", + "{}", + "" + ], + gives => [ + "map open '{'", + "map close '}'", + "map open '{'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "stuff", + opts => [ + "-m" + ], + input => [ + "{}", + "[]", + "[]", + "\"sdfasd\"", + 123, + "{ \"123\" : 123 }", + "3.1e124", + "" + ], + gives => [ + "map open '{'", + "map close '}'", + "array open '['", + "array close ']'", + "array open '['", + "array close ']'", + "string: 'sdfasd'", + "integer: 123", + "map open '{'", + "key: '123'", + "integer: 123", + "map close '}'", + "double: 3.1e+124", + "memory leaks:\t0" + ] + }, + { + name => "array_open", + opts => [ + "-p" + ], + input => [ + "[", + "" + ], + gives => [ + "array open '['", + "memory leaks:\t0" + ] + }, + { + name => "eof_str", + opts => [ + "-p" + ], + input => [ + "\"abc" + ], + gives => [ + "memory leaks:\t0" + ] + }, + { + name => "map_open", + opts => [ + "-p" + ], + input => [ + "{", + "" + ], + gives => [ + "map open '{'", + "memory leaks:\t0" + ] + }, + { + name => "partial_ok", + opts => [ + "-p" + ], + input => [ + "[ \"foo\", \"bar\"", + "" + ], + gives => [ + "array open '['", + "string: 'foo'", + "string: 'bar'", + "memory leaks:\t0" + ] + }, + { + name => "array", + opts => [], + input => [ + "[\"foo\",", + " \"bar\", \"baz\",", + " true,false,null,{\"key\":\"value\"},", + " [null,null,null,[]],", + " \"\\n\\r\\\\\"", + "]", + "" + ], + gives => [ + "array open '['", + "string: 'foo'", + "string: 'bar'", + "string: 'baz'", + "bool: true", + "bool: false", + "null", + "map open '{'", + "key: 'key'", + "string: 'value'", + "map close '}'", + "array open '['", + "null", + "null", + "null", + "array open '['", + "array close ']'", + "array close ']'", + "string: '", + "\r\\'", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "array_close", + opts => [], + input => [ + "]", + "" + ], + gives => [ + "parse error: unallowed token at this point in JSON text", + "memory leaks:\t0" + ] + }, + { + name => "bignums", + opts => [], + input => [ + "[ 9223372036854775807, -9223372036854775807 ]", + "" + ], + gives => [ + "array open '['", + "integer: 9223372036854775807", + "integer: -9223372036854775807", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "bogus_char", + opts => [], + input => [ + "[\"this\",\"is\",\"what\",\"should\",\"be\",", + " \"a happy bit of json\",", + " \"but someone, misspelled \\\"true\\\"\", ture,", + " \"who says JSON is easy for humans to generate?\"]", + "" + ], + gives => [ + "array open '['", + "string: 'this'", + "string: 'is'", + "string: 'what'", + "string: 'should'", + "string: 'be'", + "string: 'a happy bit of json'", + "string: 'but someone, misspelled \"true\"'", + "lexical error: invalid string in json text.", + "memory leaks:\t0" + ] + }, + { + name => "codepoints_from_unicode_org", + opts => [], + input => [ + "\"\\u004d\\u0430\\u4e8c\\ud800\\udf02\"", + "" + ], + gives => [ + "string: 'M\320\260\344\272\214\360\220\214\202'", + "memory leaks:\t0" + ] + }, + { + name => "deep_arrays", + opts => [], + input => [ + "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" + ], + gives => [ + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array open '['", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "difficult_json_c_test_case", + opts => [], + input => [ + "{ \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }", + "" + ], + gives => [ + "map open '{'", + "key: 'glossary'", + "map open '{'", + "key: 'title'", + "string: 'example glossary'", + "key: 'GlossDiv'", + "map open '{'", + "key: 'title'", + "string: 'S'", + "key: 'GlossList'", + "array open '['", + "map open '{'", + "key: 'ID'", + "string: 'SGML'", + "key: 'SortAs'", + "string: 'SGML'", + "key: 'GlossTerm'", + "string: 'Standard Generalized Markup Language'", + "key: 'Acronym'", + "string: 'SGML'", + "key: 'Abbrev'", + "string: 'ISO 8879:1986'", + "key: 'GlossDef'", + "string: 'A meta-markup language, used to create markup languages such as DocBook.'", + "key: 'GlossSeeAlso'", + "array open '['", + "string: 'GML'", + "string: 'XML'", + "string: 'markup'", + "array close ']'", + "map close '}'", + "array close ']'", + "map close '}'", + "map close '}'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "doubles", + opts => [], + input => [ + "[ 0.1e2, 1e1, 3.141569, 10000000000000e-10]", + "" + ], + gives => [ + "array open '['", + "double: 10", + "double: 10", + "double: 3.14157", + "double: 1000", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "doubles_in_array", + opts => [], + input => [ + "[0.00011999999999999999, 6E-06, 6E-06, 1E-06, 1E-06]", + "" + ], + gives => [ + "array open '['", + "double: 0.00012", + "double: 6e-06", + "double: 6e-06", + "double: 1e-06", + "double: 1e-06", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "empty_array", + opts => [], + input => [ + "[]" + ], + gives => [ + "array open '['", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "empty_string", + opts => [], + input => [ + "\"\"", + "" + ], + gives => [ + "string: ''", + "memory leaks:\t0" + ] + }, + { + name => "escaped_bulgarian", + opts => [], + input => [ + "[\"\\u0414\\u0430\",", + " \"\\u041c\\u0443\",", + " \"\\u0415\\u0431\\u0430\",", + " \"\\u041c\\u0430\\u0439\\u043a\\u0430\\u0442\\u0430\"]", + "" + ], + gives => [ + "array open '['", + "string: '\320\224\320\260'", + "string: '\320\234\321\203'", + "string: '\320\225\320\261\320\260'", + "string: '\320\234\320\260\320\271\320\272\320\260\321\202\320\260'", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "escaped_foobar", + opts => [], + input => [ + "\"\\u0066\\u006f\\u006f\\u0062\\u0061\\u0072\"", + "" + ], + gives => [ + "string: 'foobar'", + "memory leaks:\t0" + ] + }, + { + name => "false", + opts => [], + input => [ + "false", + "" + ], + gives => [ + "bool: false", + "memory leaks:\t0" + ] + }, + { + name => "false_then_garbage", + opts => [], + input => [ + "falsex" + ], + gives => [ + "bool: false", + "parse error: trailing garbage", + "memory leaks:\t0" + ] + }, + { + name => "issue_7", + opts => [], + input => [ + "2009-10-20\@20:38:21.539575", + "" + ], + gives => [ + "integer: 2009", + "parse error: trailing garbage", + "memory leaks:\t0" + ] + }, + { + name => "null_then_garbage", + opts => [], + input => [ + "nullx", + "" + ], + gives => [ + "null", + "parse error: trailing garbage", + "memory leaks:\t0" + ] + }, + { + name => "true_then_garbage", + opts => [], + input => [ + "truex", + "" + ], + gives => [ + "bool: true", + "parse error: trailing garbage", + "memory leaks:\t0" + ] + }, + { + name => "four_byte_utf8", + opts => [], + input => [ + "{ \"U+10ABCD\": \"\364\212\257\215\" }", + "" + ], + gives => [ + "map open '{'", + "key: 'U+10ABCD'", + "string: '\364\212\257\215'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "high_overflow", + opts => [], + input => [ + "9223372036854775808" + ], + gives => [ + "parse error: integer overflow", + "memory leaks:\t0" + ] + }, + { + name => "integers", + opts => [], + input => [ + "[ 1,2,3,4,5,6,7,", + " 123456789 , -123456789,", + " 2147483647, -2147483647 ]", + "" + ], + gives => [ + "array open '['", + "integer: 1", + "integer: 2", + "integer: 3", + "integer: 4", + "integer: 5", + "integer: 6", + "integer: 7", + "integer: 123456789", + "integer: -123456789", + "integer: 2147483647", + "integer: -2147483647", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "invalid_utf8", + opts => [], + input => [ + "[\"\320\224\320\260 \320\234\321 \320\225\320\261\320\260 \320\234\320\260\320\271\320\272\320\260\321\202\320\260\"]", + "" + ], + gives => [ + "array open '['", + "lexical error: invalid bytes in UTF8 string.", + "memory leaks:\t0" + ] + }, + { + name => "isolated_surrogate_marker", + opts => [], + input => [ + "\"\\ud800\"", + "" + ], + gives => [ + "string: '?'", + "memory leaks:\t0" + ] + }, + { + name => "leading_zero_in_number", + opts => [], + input => [ + "{ \"bad thing\": 01 }", + "" + ], + gives => [ + "map open '{'", + "key: 'bad thing'", + "integer: 0", + "parse error: after key and value, inside map, I expect ',' or '}'", + "memory leaks:\t0" + ] + }, + { + name => "lonely_minus_sign", + opts => [], + input => [ + "[", + "\t\t\"foo\", true,", + "\t\ttrue, \"blue\",", + "\t\t\"baby where are you?\", \"oh boo hoo!\",", + " - ", + "]", + "" + ], + gives => [ + "array open '['", + "string: 'foo'", + "bool: true", + "bool: true", + "string: 'blue'", + "string: 'baby where are you?'", + "string: 'oh boo hoo!'", + "lexical error: malformed number, a digit is required after the minus sign.", + "memory leaks:\t0" + ] + }, + { + name => "lonely_number", + opts => [], + input => [ + 123456789 + ], + gives => [ + "integer: 123456789", + "memory leaks:\t0" + ] + }, + { + name => "low_overflow", + opts => [], + input => [ + "-9223372036854775808" + ], + gives => [ + "parse error: integer overflow", + "memory leaks:\t0" + ] + }, + { + name => "map_close", + opts => [], + input => [ + "}", + "" + ], + gives => [ + "parse error: unallowed token at this point in JSON text", + "memory leaks:\t0" + ] + }, + { + name => "missing_integer_after_decimal_point", + opts => [], + input => [ + "10.e2", + "" + ], + gives => [ + "lexical error: malformed number, a digit is required after the decimal point.", + "memory leaks:\t0" + ] + }, + { + name => "missing_integer_after_exponent", + opts => [], + input => [ + "10e", + "" + ], + gives => [ + "lexical error: malformed number, a digit is required after the exponent.", + "memory leaks:\t0" + ] + }, + { + name => "multiple", + opts => [], + input => [ + "", + "{}", + "{}", + "" + ], + gives => [ + "map open '{'", + "map close '}'", + "parse error: trailing garbage", + "memory leaks:\t0" + ] + }, + { + name => "non_utf8_char_in_string", + opts => [], + input => [ + "{\"CoreletAPIVersion\":2,\"CoreletType\":\"standalone\",\"documentation\":\"A corelet that provides the capability to upload a folder\222s contents into a user\222s locker.\",\"functions\":[{\"documentation\":\"Displays a dialog box that allows user to select a folder on the local system.\",\"name\":\"ShowBrowseDialog\",\"parameters\":[{\"documentation\":\"The callback function for results.\",\"name\":\"callback\",\"required\":true,\"type\":\"callback\"}]},{\"documentation\":\"Uploads all mp3 files in the folder provided.\",\"name\":\"UploadFolder\",\"parameters\":[{\"documentation\":\"The path to upload mp3 files from.\",\"name\":\"path\",\"required\":true,\"type\":\"string\"},{\"documentation\":\"The callback function for progress.\",\"name\":\"callback\",\"required\":true,\"type\":\"callback\"}]},{\"documentation\":\"Returns the server name to the current locker service.\",\"name\":\"GetLockerService\",\"parameters\":[]},{\"documentation\":\"Changes the name of the locker service.\",\"name\":\"SetLockerService\",\"parameters\":[{\"documentation\":\"The value of the locker service to set active.\",\"name\":\"LockerService\",\"required\":true,\"type\":\"string\"}]},{\"documentation\":\"Downloads locker files to the suggested folder.\",\"name\":\"DownloadFile\",\"parameters\":[{\"documentation\":\"The origin path of the locker file.\",\"name\":\"path\",\"required\":true,\"type\":\"string\"},{\"documentation\":\"The Window destination path of the locker file.\",\"name\":\"destination\",\"required\":true,\"type\":\"integer\"},{\"documentation\":\"The callback function for progress.\",\"name\":\"callback\",\"required\":true,\"type\":\"callback\"}]}],\"name\":\"LockerUploader\",\"version\":{\"major\":0,\"micro\":1,\"minor\":0},\"versionString\":\"0.0.1\"}" + ], + gives => [ + "map open '{'", + "key: 'CoreletAPIVersion'", + "integer: 2", + "key: 'CoreletType'", + "string: 'standalone'", + "key: 'documentation'", + "lexical error: invalid bytes in UTF8 string.", + "memory leaks:\t0" + ] + }, + { + name => "partial_bad", + opts => [], + input => [ + "[ \"foo\", \"bar\"", + "" + ], + gives => [ + "array open '['", + "string: 'foo'", + "string: 'bar'", + "parse error: premature EOF", + "memory leaks:\t0" + ] + }, + { + name => "null", + opts => [], + input => [ + "null", + "" + ], + gives => [ + "null", + "memory leaks:\t0" + ] + }, + { + name => "nulls_and_bools", + opts => [], + input => [ + "{", + "\t\"boolean, true\": true,", + "\t\"boolean, false\": false,", + "\t\"null\": null", + "}", + "" + ], + gives => [ + "map open '{'", + "key: 'boolean, true'", + "bool: true", + "key: 'boolean, false'", + "bool: false", + "key: 'null'", + "null", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "simple", + opts => [], + input => [ + "{", + " \"this\": \"is\",", + " \"really\": \"simple\",", + " \"json\": \"right?\"", + "}", + "" + ], + gives => [ + "map open '{'", + "key: 'this'", + "string: 'is'", + "key: 'really'", + "string: 'simple'", + "key: 'json'", + "string: 'right?'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "simple_with_comments", + opts => [], + input => [ + "{", + " \"this\": \"is\", // ignore this", + " \"really\": \"simple\",", + " /* ignore", + "this", + "too * / ", + "** //", + "(/", + "******/", + " \"json\": \"right?\"", + "}", + "" + ], + gives => [ + "map open '{'", + "key: 'this'", + "string: 'is'", + "lexical error: probable comment found in input text, comments are not enabled.", + "memory leaks:\t0" + ] + }, + { + name => "string_invalid_escape", + opts => [], + input => [ + "[\"\\n foo \\/ bar \\r\\f\\\\\\uffff\\t\\b\\\"\\\\ and you can't escape thi\\s\"]", + "" + ], + gives => [ + "array open '['", + "lexical error: inside a string, '\\' occurs before a character which it may not.", + "memory leaks:\t0" + ] + }, + { + name => "string_invalid_hex_char", + opts => [], + input => [ + "\"foo foo, blah blah \\u0123 \\u4567 \\u89ab \\uc/ef \\uABCD \\uEFFE bar baz bing\"", + "" + ], + gives => [ + "lexical error: invalid (non-hex) character occurs after '\\u' inside string.", + "memory leaks:\t0" + ] + }, + { + name => "string_with_escapes", + opts => [], + input => [ + "[\"\\n foo \\/ bar \\r\\f\\\\\\uffff\\t\\b\\\"\\\\\",", + " \"\\\"and this string has an escape at the beginning\",", + " \"and this string has no escapes\" ]", + "" + ], + gives => [ + "array open '['", + "string: '", + " foo / bar \r\f\\\357\277\277\t\b\"\\'", + "string: '\"and this string has an escape at the beginning'", + "string: 'and this string has no escapes'", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "string_with_invalid_newline", + opts => [], + input => [ + "\"la di dah. this is a string, and I can do this, \\n, but not this", + "\"", + "" + ], + gives => [ + "lexical error: invalid character inside string.", + "memory leaks:\t0" + ] + }, + { + name => "three_byte_utf8", + opts => [], + input => [ + "{\"matzue\": \"\346\235\276\346\261\237\", \"asakusa\": \"\346\265\205\350\215\211\"}", + "" + ], + gives => [ + "map open '{'", + "key: 'matzue'", + "string: '\346\235\276\346\261\237'", + "key: 'asakusa'", + "string: '\346\265\205\350\215\211'", + "map close '}'", + "memory leaks:\t0" + ] + }, + { + name => "true", + opts => [], + input => [ + "true", + "" + ], + gives => [ + "bool: true", + "memory leaks:\t0" + ] + }, + { + name => "unescaped_bulgarian", + opts => [], + input => [ + "[\"\320\224\320\260 \320\234\321\203 \320\225\320\261\320\260 \320\234\320\260\320\271\320\272\320\260\321\202\320\260\"]", + "" + ], + gives => [ + "array open '['", + "string: '\320\224\320\260 \320\234\321\203 \320\225\320\261\320\260 \320\234\320\260\320\271\320\272\320\260\321\202\320\260'", + "array close ']'", + "memory leaks:\t0" + ] + }, + { + name => "zerobyte", + opts => [], + input => [ + "\"\\u0000\"", + "" + ], + gives => [ + "string: '\0'", + "memory leaks:\t0" + ] + } + ]; + + return @{$VAR1}; +} + +1; diff --git a/src/libCom/test/yajlTestConverter.pl b/src/libCom/test/yajlTestConverter.pl new file mode 100755 index 000000000..c3d2b54b6 --- /dev/null +++ b/src/libCom/test/yajlTestConverter.pl @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# This script converts the parsing test cases from the yajl release tree +# into the yajlTestCases module as used by libCom/test/yajlTest.plt +# +# Re-do this conversion and commit after checking out a new version of yajl +# from https://github.com/lloyd/yajl as follows: +# $ cd /src/libCom/test +# $ perl yajlTestConverter.pl /path/to/yajl +# The tests are saved into the file yajlTestCases.pm in the src/libCom/test +# directory which will be read by the yajlTest.t test script. + +use Data::Dumper; + +my $yajl = shift @ARGV + or die "Usage: $0 /path/to/yajl\n"; + +my @files = glob "$yajl/test/parsing/cases/*.json"; + +my $caseFile = 'yajlTestCases.pm'; + +my @cases; + +for my $file (@files) { + $file =~ m|/([afn][cgmp]_)?([^/]*)\.json$|; + my $allow = $1; + my $name = $2; + next if $name eq ''; + + my $case = { name => $name }; + + if ($allow eq 'ac_') { + $case->{opts} = ['-c']; + } + elsif ($allow eq 'ag_') { + $case->{opts} = ['-g']; + } + elsif ($allow eq 'am_') { + $case->{opts} = ['-m']; + } + elsif ($allow eq 'ap_') { + $case->{opts} = ['-p']; + } + else { + $case->{opts} = []; + } + + my $input = slurp($file); + my @input = split "\n", $input; + push @input, '' if $input =~ m/\n$/; + $case->{input} = \@input; + + my @gives = split "\n", slurp("$file.gold"); + $case->{gives} = \@gives; + + push @cases, $case; +} + +# Configure Dumper() output +$Data::Dumper::Pad = ' '; +$Data::Dumper::Indent = 1; +$Data::Dumper::Useqq = 1; +$Data::Dumper::Quotekeys = 0; +$Data::Dumper::Sortkeys = sub { return ['name', 'opts', 'input', 'gives'] }; + +my $data = Dumper(\@cases); + +open my $out, '>', $caseFile + or die "Can't open/create $caseFile: $@\n"; +print $out <<"EOF"; +# Parser test cases from https://github.com/lloyd/yajl +# +# This file is generated, DO NOT EDIT! +# +# See comments in yajlTestConverter.pl for instructions on +# how to regenerate this file from the original yajl sources. + +sub cases { + my$data + return \@{\$VAR1}; +} + +1; +EOF + +close $out + or die "Problem writing $caseFile: $@\n"; + +exit 0; + + +sub slurp { + my ($file) = @_; + open my $in, '<', $file + or die "Can't open file $file: $!\n"; + my $contents = do { local $/; <$in> }; + return $contents; +} diff --git a/src/libCom/test/yajl_test.c b/src/libCom/test/yajl_test.c new file mode 100644 index 000000000..c07210ac2 --- /dev/null +++ b/src/libCom/test/yajl_test.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2007-2014, Lloyd Hilaiel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include + +/* memory debugging routines */ +typedef struct +{ + unsigned int numFrees; + unsigned int numMallocs; + /* XXX: we really need a hash table here with per-allocation + * information */ +} yajlTestMemoryContext; + +/* cast void * into context */ +#define TEST_CTX(vptr) ((yajlTestMemoryContext *) (vptr)) + +static void yajlTestFree(void * ctx, void * ptr) +{ + assert(ptr != NULL); + TEST_CTX(ctx)->numFrees++; + free(ptr); +} + +static void * yajlTestMalloc(void * ctx, size_t sz) +{ + assert(sz != 0); + TEST_CTX(ctx)->numMallocs++; + return malloc(sz); +} + +static void * yajlTestRealloc(void * ctx, void * ptr, size_t sz) +{ + if (ptr == NULL) { + assert(sz != 0); + TEST_CTX(ctx)->numMallocs++; + } else if (sz == 0) { + TEST_CTX(ctx)->numFrees++; + } + + return realloc(ptr, sz); +} + + +/* begin parsing callback routines */ +#define BUF_SIZE 2048 + +static int test_yajl_null(void *ctx) +{ + printf("null\n"); + return 1; +} + +static int test_yajl_boolean(void * ctx, int boolVal) +{ + printf("bool: %s\n", boolVal ? "true" : "false"); + return 1; +} + +static int test_yajl_integer(void *ctx, long long integerVal) +{ + printf("integer: %lld\n", integerVal); + return 1; +} + +static int test_yajl_double(void *ctx, double doubleVal) +{ + printf("double: %g\n", doubleVal); + return 1; +} + +static int test_yajl_string(void *ctx, const unsigned char * stringVal, + size_t stringLen) +{ + printf("string: '"); + fwrite(stringVal, 1, stringLen, stdout); + printf("'\n"); + return 1; +} + +static int test_yajl_map_key(void *ctx, const unsigned char * stringVal, + size_t stringLen) +{ + char * str = (char *) malloc(stringLen + 1); + str[stringLen] = 0; + memcpy(str, stringVal, stringLen); + printf("key: '%s'\n", str); + free(str); + return 1; +} + +static int test_yajl_start_map(void *ctx) +{ + printf("map open '{'\n"); + return 1; +} + + +static int test_yajl_end_map(void *ctx) +{ + printf("map close '}'\n"); + return 1; +} + +static int test_yajl_start_array(void *ctx) +{ + printf("array open '['\n"); + return 1; +} + +static int test_yajl_end_array(void *ctx) +{ + printf("array close ']'\n"); + return 1; +} + +static yajl_callbacks callbacks = { + test_yajl_null, + test_yajl_boolean, + test_yajl_integer, + test_yajl_double, + NULL, + test_yajl_string, + test_yajl_start_map, + test_yajl_map_key, + test_yajl_end_map, + test_yajl_start_array, + test_yajl_end_array +}; + +static void usage(const char * progname) +{ + fprintf(stderr, + "usage: %s [options]\n" + "Parse input from stdin as JSON and ouput parsing details " + "to stdout\n" + " -b set the read buffer size\n" + " -c allow comments\n" + " -g allow *g*arbage after valid JSON text\n" + " -h print this help message\n" + " -m allows the parser to consume multiple JSON values\n" + " from a single string separated by whitespace\n" + " -p partial JSON documents should not cause errors\n", + progname); + exit(1); +} + +int +main(int argc, char ** argv) +{ + yajl_handle hand; + const char * fileName = NULL; + static unsigned char * fileData = NULL; + FILE *file; + size_t bufSize = BUF_SIZE; + yajl_status stat; + size_t rd; + int i, j; + + /* memory allocation debugging: allocate a structure which collects + * statistics */ + yajlTestMemoryContext memCtx = { 0,0 }; + + /* memory allocation debugging: allocate a structure which holds + * allocation routines */ + yajl_alloc_funcs allocFuncs = { + yajlTestMalloc, + yajlTestRealloc, + yajlTestFree, + (void *) NULL + }; + + allocFuncs.ctx = (void *) &memCtx; + + /* allocate the parser */ + hand = yajl_alloc(&callbacks, &allocFuncs, NULL); + + /* check arguments. We expect exactly one! */ + for (i=1;i= argc) usage(argv[0]); + + /* validate integer */ + for (j=0;j<(int)strlen(argv[i]);j++) { + if (argv[i][j] <= '9' && argv[i][j] >= '0') continue; + fprintf(stderr, "-b requires an integer argument. '%s' " + "is invalid\n", argv[i]); + usage(argv[0]); + } + + bufSize = atoi(argv[i]); + if (!bufSize) { + fprintf(stderr, "%zu is an invalid buffer size\n", + bufSize); + } + } else if (!strcmp("-g", argv[i])) { + yajl_config(hand, yajl_allow_trailing_garbage, 1); + } else if (!strcmp("-h", argv[i])) { + usage(argv[0]); + } else if (!strcmp("-m", argv[i])) { + yajl_config(hand, yajl_allow_multiple_values, 1); + } else if (!strcmp("-p", argv[i])) { + yajl_config(hand, yajl_allow_partial_values, 1); + } else { + fileName = argv[i]; + break; + } + } + + fileData = (unsigned char *) malloc(bufSize); + + if (fileData == NULL) { + fprintf(stderr, + "failed to allocate read buffer of %zu bytes, exiting.", + bufSize); + yajl_free(hand); + exit(2); + } + + if (fileName) + { + file = fopen(fileName, "r"); + } + else + { + file = stdin; + } + for (;;) { + rd = fread((void *) fileData, 1, bufSize, file); + + if (rd == 0) { + if (!feof(stdin)) { + fprintf(stderr, "error reading from '%s'\n", fileName); + } + break; + } + /* read file data, now pass to parser */ + stat = yajl_parse(hand, fileData, rd); + + if (stat != yajl_status_ok) break; + } + + stat = yajl_complete_parse(hand); + if (stat != yajl_status_ok) + { + unsigned char * str = yajl_get_error(hand, 0, fileData, rd); + fflush(stdout); + fprintf(stderr, "%s", (char *) str); + yajl_free_error(hand, str); + } + + yajl_free(hand); + free(fileData); + + if (fileName) + { + fclose(file); + } + /* finally, print out some memory statistics */ + +/* (lth) only print leaks here, as allocations and frees may vary depending + * on read buffer size, causing false failures. + * + * printf("allocations:\t%u\n", memCtx.numMallocs); + * printf("frees:\t\t%u\n", memCtx.numFrees); +*/ + fflush(stderr); + fflush(stdout); + printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees); + + return 0; +}