c@75: #include <string>
c@75: #include <cstdio>
c@75: #include <cstring>
c@75: #include <iostream>
c@75: #include <sstream>
c@75: #include "json11.hpp"
c@75: #include <cassert>
c@75: #include <list>
c@75: #include <set>
c@75: #include <unordered_map>
c@75: 
c@75: using namespace json11;
c@75: using std::string;
c@75: 
c@75: // Check that Json has the properties we want.
c@75: #include <type_traits>
c@75: #define CHECK_TRAIT(x) static_assert(std::x::value, #x)
c@75: CHECK_TRAIT(is_nothrow_constructible<Json>);
c@75: CHECK_TRAIT(is_nothrow_default_constructible<Json>);
c@75: CHECK_TRAIT(is_copy_constructible<Json>);
c@75: CHECK_TRAIT(is_nothrow_move_constructible<Json>);
c@75: CHECK_TRAIT(is_copy_assignable<Json>);
c@75: CHECK_TRAIT(is_nothrow_move_assignable<Json>);
c@75: CHECK_TRAIT(is_nothrow_destructible<Json>);
c@75: 
c@75: void parse_from_stdin() {
c@75:     string buf;
c@75:     string line;
c@75:     while (std::getline(std::cin, line)) {
c@75:         buf += line + "\n";
c@75:     }
c@75: 
c@75:     string err;
c@75:     auto json = Json::parse(buf, err);
c@75:     if (!err.empty()) {
c@75:         printf("Failed: %s\n", err.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json.dump().c_str());
c@75:     }
c@75: }
c@75: 
c@75: int main(int argc, char **argv) {
c@75:     if (argc == 2 && argv[1] == string("--stdin")) {
c@75:         parse_from_stdin();
c@75:         return 0;
c@75:     }
c@75: 
c@75:     const string simple_test =
c@75:         R"({"k1":"v1", "k2":42, "k3":["a",123,true,false,null]})";
c@75: 
c@75:     string err;
c@75:     auto json = Json::parse(simple_test, err);
c@75: 
c@75:     std::cout << "k1: " << json["k1"].string_value() << "\n";
c@75:     std::cout << "k3: " << json["k3"].dump() << "\n";
c@75: 
c@75:     for (auto &k : json["k3"].array_items()) {
c@75:         std::cout << "    - " << k.dump() << "\n";
c@75:     }
c@75: 
c@75:     const string comment_test = R"({
c@75:       // comment /* with nested comment */
c@75:       "a": 1,
c@75:       // comment
c@75:       // continued
c@75:       "b": "text",
c@75:       /* multi
c@75:          line
c@75:          comment */
c@75:       // and single-line comment
c@75:       "c": [1, 2, 3]
c@75:     })";
c@75: 
c@75:     string err_comment;
c@75:     auto json_comment = Json::parse(
c@75:       comment_test, err_comment, JsonParse::COMMENTS);
c@75:     if (!err_comment.empty()) {
c@75:         printf("Failed: %s\n", err_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     string failing_comment_test = R"({
c@75:       /* bad comment
c@75:       "a": 1,
c@75:     })";
c@75: 
c@75:     string err_failing_comment;
c@75:     auto json_failing_comment = Json::parse(
c@75:       failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
c@75:     if (!err_failing_comment.empty()) {
c@75:         printf("Failed: %s\n", err_failing_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_failing_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     failing_comment_test = R"({
c@75:       / / bad comment })";
c@75: 
c@75:     json_failing_comment = Json::parse(
c@75:       failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
c@75:     if (!err_failing_comment.empty()) {
c@75:         printf("Failed: %s\n", err_failing_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_failing_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     failing_comment_test = R"({// bad comment })";
c@75: 
c@75:     json_failing_comment = Json::parse(
c@75:       failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
c@75:     if (!err_failing_comment.empty()) {
c@75:         printf("Failed: %s\n", err_failing_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_failing_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     failing_comment_test = R"({
c@75:           "a": 1
c@75:         }/)";
c@75: 
c@75:     json_failing_comment = Json::parse(
c@75:       failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
c@75:     if (!err_failing_comment.empty()) {
c@75:         printf("Failed: %s\n", err_failing_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_failing_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     failing_comment_test = R"({/* bad
c@75:                                   comment *})";
c@75: 
c@75:     json_failing_comment = Json::parse(
c@75:       failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
c@75:     if (!err_failing_comment.empty()) {
c@75:         printf("Failed: %s\n", err_failing_comment.c_str());
c@75:     } else {
c@75:         printf("Result: %s\n", json_failing_comment.dump().c_str());
c@75:     }
c@75: 
c@75:     std::list<int> l1 { 1, 2, 3 };
c@75:     std::vector<int> l2 { 1, 2, 3 };
c@75:     std::set<int> l3 { 1, 2, 3 };
c@75:     assert(Json(l1) == Json(l2));
c@75:     assert(Json(l2) == Json(l3));
c@75: 
c@75:     std::map<string, string> m1 { { "k1", "v1" }, { "k2", "v2" } };
c@75:     std::unordered_map<string, string> m2 { { "k1", "v1" }, { "k2", "v2" } };
c@75:     assert(Json(m1) == Json(m2));
c@75: 
c@75:     // Json literals
c@75:     Json obj = Json::object({
c@75:         { "k1", "v1" },
c@75:         { "k2", 42.0 },
c@75:         { "k3", Json::array({ "a", 123.0, true, false, nullptr }) },
c@75:     });
c@75: 
c@75:     std::cout << "obj: " << obj.dump() << "\n";
c@75: 
c@75:     assert(Json("a").number_value() == 0);
c@75:     assert(Json("a").string_value() == "a");
c@75:     assert(Json().number_value() == 0);
c@75: 
c@75:     assert(obj == json);
c@75:     assert(Json(42) == Json(42.0));
c@75:     assert(Json(42) != Json(42.1));
c@75: 
c@75:     const string unicode_escape_test =
c@75:         R"([ "blah\ud83d\udca9blah\ud83dblah\udca9blah\u0000blah\u1234" ])";
c@75: 
c@75:     const char utf8[] = "blah" "\xf0\x9f\x92\xa9" "blah" "\xed\xa0\xbd" "blah"
c@75:                         "\xed\xb2\xa9" "blah" "\0" "blah" "\xe1\x88\xb4";
c@75: 
c@75:     Json uni = Json::parse(unicode_escape_test, err);
c@75:     assert(uni[0].string_value().size() == (sizeof utf8) - 1);
c@75:     assert(std::memcmp(uni[0].string_value().data(), utf8, sizeof utf8) == 0);
c@75: 
c@75:     // Demonstrates the behavior change in Xcode 7 / Clang 3.7 described
c@75:     // here: https://llvm.org/bugs/show_bug.cgi?id=23812
c@75:     Json nested_array = Json::array { Json::array { 1, 2, 3 } };
c@75:     assert(nested_array.is_array());
c@75:     assert(nested_array.array_items().size() == 1);
c@75:     assert(nested_array.array_items()[0].is_array());
c@75:     assert(nested_array.array_items()[0].array_items().size() == 3);
c@75: 
c@75:     Json my_json = Json::object {
c@75:         { "key1", "value1" },
c@75:         { "key2", false },
c@75:         { "key3", Json::array { 1, 2, 3 } },
c@75:     };
c@75:     std::string json_str = my_json.dump();
c@75:     printf("%s\n", json_str.c_str());
c@75: 
c@75:     class Point {
c@75:     public:
c@75:         int x;
c@75:         int y;
c@75:         Point (int x, int y) : x(x), y(y) {}
c@75:         Json to_json() const { return Json::array { x, y }; }
c@75:     };
c@75: 
c@75:     std::vector<Point> points = { { 1, 2 }, { 10, 20 }, { 100, 200 } };
c@75:     std::string points_json = Json(points).dump();
c@75:     printf("%s\n", points_json.c_str());
c@75: }