1// __ _____ _____ _____ 2// __| | __| | | | JSON for Modern C++ (supporting code) 3// | | |__ | | | | | | version 3.11.2 4// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5// 6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7// SPDX-License-Identifier: MIT 8 9#include "doctest_compatibility.h" 10 11#define JSON_TESTS_PRIVATE 12#include <nlohmann/json.hpp> 13using nlohmann::json; 14 15#include <sstream> 16 17namespace 18{ 19struct alt_string_iter 20{ 21 alt_string_iter() = default; 22 alt_string_iter(const char* cstr) 23 : impl(cstr) 24 {} 25 26 void reserve(std::size_t s) 27 { 28 impl.reserve(s); 29 } 30 31 template<typename Iter> 32 void append(Iter first, Iter last) 33 { 34 impl.append(first, last); 35 } 36 37 std::string::const_iterator begin() const 38 { 39 return impl.begin(); 40 } 41 42 std::string::const_iterator end() const 43 { 44 return impl.end(); 45 } 46 47 std::size_t size() const 48 { 49 return impl.size(); 50 } 51 52 alt_string_iter& operator+=(const char c) 53 { 54 impl += c; 55 return *this; 56 } 57 58 std::string impl{}; 59}; 60 61struct alt_string_data 62{ 63 alt_string_data() = default; 64 alt_string_data(const char* cstr) 65 : impl(cstr) 66 {} 67 68 void reserve(std::size_t s) 69 { 70 impl.reserve(s); 71 } 72 73 void append(const char* p, std::size_t s) 74 { 75 impl.append(p, s); 76 } 77 78 const char* data() const 79 { 80 return impl.data(); 81 } 82 83 std::size_t size() const 84 { 85 return impl.size(); 86 } 87 88 alt_string_data& operator+=(const char c) 89 { 90 impl += c; 91 return *this; 92 } 93 94 std::string impl{}; 95}; 96 97void check_escaped(const char* original, const char* escaped = "", bool ensure_ascii = false); 98void check_escaped(const char* original, const char* escaped, const bool ensure_ascii) 99{ 100 std::stringstream ss; 101 json::serializer s(nlohmann::detail::output_adapter<char>(ss), ' '); 102 s.dump_escaped(original, ensure_ascii); 103 CHECK(ss.str() == escaped); 104} 105} // namespace 106 107TEST_CASE("convenience functions") 108{ 109 SECTION("type name as string") 110 { 111 CHECK(std::string(json(json::value_t::null).type_name()) == "null"); 112 CHECK(std::string(json(json::value_t::object).type_name()) == "object"); 113 CHECK(std::string(json(json::value_t::array).type_name()) == "array"); 114 CHECK(std::string(json(json::value_t::number_integer).type_name()) == "number"); 115 CHECK(std::string(json(json::value_t::number_unsigned).type_name()) == "number"); 116 CHECK(std::string(json(json::value_t::number_float).type_name()) == "number"); 117 CHECK(std::string(json(json::value_t::binary).type_name()) == "binary"); 118 CHECK(std::string(json(json::value_t::boolean).type_name()) == "boolean"); 119 CHECK(std::string(json(json::value_t::string).type_name()) == "string"); 120 CHECK(std::string(json(json::value_t::discarded).type_name()) == "discarded"); 121 } 122 123 SECTION("string escape") 124 { 125 check_escaped("\"", "\\\""); 126 check_escaped("\\", "\\\\"); 127 check_escaped("\b", "\\b"); 128 check_escaped("\f", "\\f"); 129 check_escaped("\n", "\\n"); 130 check_escaped("\r", "\\r"); 131 check_escaped("\t", "\\t"); 132 133 check_escaped("\x01", "\\u0001"); 134 check_escaped("\x02", "\\u0002"); 135 check_escaped("\x03", "\\u0003"); 136 check_escaped("\x04", "\\u0004"); 137 check_escaped("\x05", "\\u0005"); 138 check_escaped("\x06", "\\u0006"); 139 check_escaped("\x07", "\\u0007"); 140 check_escaped("\x08", "\\b"); 141 check_escaped("\x09", "\\t"); 142 check_escaped("\x0a", "\\n"); 143 check_escaped("\x0b", "\\u000b"); 144 check_escaped("\x0c", "\\f"); 145 check_escaped("\x0d", "\\r"); 146 check_escaped("\x0e", "\\u000e"); 147 check_escaped("\x0f", "\\u000f"); 148 check_escaped("\x10", "\\u0010"); 149 check_escaped("\x11", "\\u0011"); 150 check_escaped("\x12", "\\u0012"); 151 check_escaped("\x13", "\\u0013"); 152 check_escaped("\x14", "\\u0014"); 153 check_escaped("\x15", "\\u0015"); 154 check_escaped("\x16", "\\u0016"); 155 check_escaped("\x17", "\\u0017"); 156 check_escaped("\x18", "\\u0018"); 157 check_escaped("\x19", "\\u0019"); 158 check_escaped("\x1a", "\\u001a"); 159 check_escaped("\x1b", "\\u001b"); 160 check_escaped("\x1c", "\\u001c"); 161 check_escaped("\x1d", "\\u001d"); 162 check_escaped("\x1e", "\\u001e"); 163 check_escaped("\x1f", "\\u001f"); 164 165 // invalid UTF-8 characters 166 CHECK_THROWS_WITH_AS(check_escaped("ä\xA9ü"), "[json.exception.type_error.316] invalid UTF-8 byte at index 2: 0xA9", json::type_error&); 167 168 CHECK_THROWS_WITH_AS(check_escaped("\xC2"), "[json.exception.type_error.316] incomplete UTF-8 string; last byte: 0xC2", json::type_error&); 169 } 170 171 SECTION("string concat") 172 { 173 using nlohmann::detail::concat; 174 175 const char* expected = "Hello, world!"; 176 alt_string_iter hello_iter{"Hello, "}; 177 alt_string_data hello_data{"Hello, "}; 178 std::string world = "world"; 179 180 SECTION("std::string") 181 { 182 std::string str1 = concat(hello_iter, world, '!'); 183 std::string str2 = concat(hello_data, world, '!'); 184 std::string str3 = concat("Hello, ", world, '!'); 185 186 CHECK(str1 == expected); 187 CHECK(str2 == expected); 188 CHECK(str3 == expected); 189 } 190 191 SECTION("alt_string_iter") 192 { 193 alt_string_iter str = concat<alt_string_iter>(hello_iter, world, '!'); 194 195 CHECK(str.impl == expected); 196 } 197 198 SECTION("alt_string_data") 199 { 200 alt_string_data str = concat<alt_string_data>(hello_data, world, '!'); 201 202 CHECK(str.impl == expected); 203 } 204 } 205} 206