diff --git a/benchmark/parse.cpp b/benchmark/parse.cpp index 24c54277a..e9a6ffc56 100644 --- a/benchmark/parse.cpp +++ b/benchmark/parse.cpp @@ -224,10 +224,10 @@ int main(int argc, char *argv[]) { << " Gigabytes/second: " << (p.size()) / (min_result * 1000000000.0) << "\n"; if(jsonoutput) { - isok = isok && pj.printjson(); + isok = isok && pj.printjson(std::cout); } if(dump) { - isok = isok && pj.dump_raw_tape(); + isok = isok && pj.dump_raw_tape(std::cout); } if (!isok) { printf(" Parsing failed. \n "); diff --git a/include/simdjson/jsoncharutils.h b/include/simdjson/jsoncharutils.h index a348e495c..68da37350 100644 --- a/include/simdjson/jsoncharutils.h +++ b/include/simdjson/jsoncharutils.h @@ -4,14 +4,14 @@ #include "simdjson/parsedjson.h" // structural chars here are -// they are { 0x7b } 0x7d : 0x3a [ 0x5b ] 0x5d , 0x2c +// they are { 0x7b } 0x7d : 0x3a [ 0x5b ] 0x5d , 0x2c (and NULL) // we are also interested in the four whitespace characters // space 0x20, linefeed 0x0a, horizontal tab 0x09 and carriage return 0x0d // these are the chars that can follow a true/false/null or number atom // and nothing else const u32 structural_or_whitespace_negated[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, diff --git a/include/simdjson/numberparsing.h b/include/simdjson/numberparsing.h index e6649c24d..a38cb02cd 100644 --- a/include/simdjson/numberparsing.h +++ b/include/simdjson/numberparsing.h @@ -242,6 +242,9 @@ parse_float(const u8 *const buf, } i *= power_of_ten[308 + exponent]; } + if(is_not_structural_or_whitespace(*p)) { + return false; + } double d = negative ? -i : i; pj.write_tape_double(d); #ifdef JSON_TEST_NUMBERS // for unit testing @@ -447,6 +450,9 @@ static really_inline bool parse_number(const u8 *const buf, } exponent += (negexp ? -expnumber : expnumber); } + if(is_not_structural_or_whitespace(*p)) { + return false; + } i = negative ? -i : i; if ((exponent != 0) || (expnumber != 0)) { if (unlikely(digitcount >= 19)) { // this is uncommon!!! diff --git a/include/simdjson/parsedjson.h b/include/simdjson/parsedjson.h index a80e8f3d7..076b81109 100644 --- a/include/simdjson/parsedjson.h +++ b/include/simdjson/parsedjson.h @@ -110,7 +110,7 @@ public: // return false if the tape is likely wrong (e.g., you did not parse a valid // JSON). WARN_UNUSED - bool printjson() { + bool printjson(std::ostream &os) { if(!isvalid) return false; size_t tapeidx = 0; u64 tape_val = tape[tapeidx]; @@ -138,64 +138,64 @@ public: type = (tape_val >> 56); if (!inobject[depth]) { if ((inobjectidx[depth] > 0) && (type != ']')) - printf(", "); + os << ", "; inobjectidx[depth]++; } else { // if (inobject) { if ((inobjectidx[depth] > 0) && ((inobjectidx[depth] & 1) == 0) && (type != '}')) - printf(", "); + os << ", "; if (((inobjectidx[depth] & 1) == 1)) - printf(" : "); + os << " : "; inobjectidx[depth]++; } switch (type) { case '"': // we have a string - putchar('"'); + os << '"'; print_with_escapes((const unsigned char *)(string_buf + payload)); - putchar('"'); + os << '"'; break; case 'l': // we have a long int if (tapeidx + 1 >= howmany) return false; - printf("%" PRId64, (int64_t)tape[++tapeidx]); + os << (int64_t)tape[++tapeidx]; break; case 'd': // we have a double if (tapeidx + 1 >= howmany) return false; double answer; memcpy(&answer, &tape[++tapeidx], sizeof(answer)); - printf("%f", answer); + os << answer; break; case 'n': // we have a null - printf("null"); + os << "null"; break; case 't': // we have a true - printf("true"); + os << "true"; break; case 'f': // we have a false - printf("false"); + os << "false"; break; case '{': // we have an object - printf("\n"); - printf("%*s\n%*s", depth, "{", depth + 1, ""); + os << '\n'; + os << '{'; depth++; inobject[depth] = true; inobjectidx[depth] = 0; break; case '}': // we end an object depth--; - printf("\n%*s}\n%*s", depth - 1, "", depth, ""); + os << '}'; break; case '[': // we start an array - printf("\n"); - printf("%*s\n%*s", depth, "[", depth + 1, ""); + os << '\n'; + os << '['; depth++; inobject[depth] = false; inobjectidx[depth] = 0; break; case ']': // we end an array depth--; - printf("\n%*s]\n%*s", depth - 1, "", depth, ""); + os << ']'; break; case 'r': // we start and end with the root node printf("should we be hitting the root node?\n"); @@ -215,7 +215,7 @@ public: } WARN_UNUSED - bool dump_raw_tape() { + bool dump_raw_tape(std::ostream &os) { if(!isvalid) return false; size_t tapeidx = 0; u64 tape_val = tape[tapeidx++]; @@ -228,52 +228,49 @@ public: return false; } for (; tapeidx < howmany; tapeidx++) { - printf("%zu : ", tapeidx); + os << tapeidx << " : "; tape_val = tape[tapeidx]; u64 payload = tape_val & JSONVALUEMASK; type = (tape_val >> 56); switch (type) { case '"': // we have a string - printf("string: "); - putchar('"'); + os << "string \""; print_with_escapes((const unsigned char *)(string_buf + payload)); - putchar('"'); - printf("\n"); + os << '"'; break; case 'l': // we have a long int if (tapeidx + 1 >= howmany) return false; - printf("integer: "); - printf("%" PRId64"\n", (int64_t)tape[++tapeidx]); + os << "integer " << (int64_t)tape[++tapeidx] << "\n"; break; case 'd': // we have a double - printf("float: "); + os << "float "; if (tapeidx + 1 >= howmany) return false; double answer; memcpy(&answer, &tape[++tapeidx], sizeof(answer)); - printf("%f\n", answer); + os << answer << '\n'; break; case 'n': // we have a null - printf("null\n"); + os << "null\n"; break; case 't': // we have a true - printf("true\n"); + os << "true\n"; break; case 'f': // we have a false - printf("false\n"); + os << "false\n"; break; case '{': // we have an object - printf("{\t// pointing to next tape location %llu \n", payload); + os << "{\t// pointing to next tape location " << payload << "\n"; break; case '}': // we end an object - printf("}\t// pointing to previous tape location %llu \n", payload); + os << "}\t// pointing to previous tape location " << payload << "\n"; break; case '[': // we start an array - printf("[\t// pointing to next tape location %llu \n", payload); + os << "[\t// pointing to next tape location " << payload << "\n"; break; case ']': // we end an array - printf("]\t// pointing to previous tape location %llu \n", payload); + os << "]\t// pointing to previous tape location " << payload << "\n"; break; case 'r': // we start and end with the root node printf("end of root\n"); diff --git a/jsonchecker/fail38.json b/jsonchecker/fail38.json new file mode 100644 index 000000000..64d572796 --- /dev/null +++ b/jsonchecker/fail38.json @@ -0,0 +1 @@ +[12 a] diff --git a/tools/json2json.cpp b/tools/json2json.cpp index de2977ebf..d8ceeda01 100644 --- a/tools/json2json.cpp +++ b/tools/json2json.cpp @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) { } compute_dump(pjh); } else { - is_ok = rawdump ? pj.dump_raw_tape() : pj.printjson(); + is_ok = rawdump ? pj.dump_raw_tape(std::cout) : pj.printjson(std::cout); if (!is_ok) { std::cerr << " Could not print out parsed result. " << std::endl; return EXIT_FAILURE;