• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.9.1
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2018 Vitaliy Manushkin <agri@akamo.info>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 
32 #include <nlohmann/json.hpp>
33 
34 #include <string>
35 #include <utility>
36 
37 
38 /* forward declarations */
39 class alt_string;
40 bool operator<(const char* op1, const alt_string& op2);
41 void int_to_string(alt_string& target, std::size_t value);
42 
43 /*
44  * This is virtually a string class.
45  * It covers std::string under the hood.
46  */
47 class alt_string
48 {
49   public:
50     using value_type = std::string::value_type;
51 
alt_string(const char * str)52     alt_string(const char* str): str_impl(str) {}
alt_string(const char * str,std::size_t count)53     alt_string(const char* str, std::size_t count): str_impl(str, count) {}
alt_string(size_t count,char chr)54     alt_string(size_t count, char chr): str_impl(count, chr) {}
55     alt_string() = default;
56 
57     template <typename...TParams>
append(TParams &&...params)58     alt_string& append(TParams&& ...params)
59     {
60         str_impl.append(std::forward<TParams>(params)...);
61         return *this;
62     }
63 
push_back(char c)64     void push_back(char c)
65     {
66         str_impl.push_back(c);
67     }
68 
69     template <typename op_type>
operator ==(const op_type & op) const70     bool operator==(const op_type& op) const
71     {
72         return str_impl == op;
73     }
74 
operator ==(const alt_string & op) const75     bool operator==(const alt_string& op) const
76     {
77         return str_impl == op.str_impl;
78     }
79 
80     template <typename op_type>
operator !=(const op_type & op) const81     bool operator!=(const op_type& op) const
82     {
83         return str_impl != op;
84     }
85 
operator !=(const alt_string & op) const86     bool operator!=(const alt_string& op) const
87     {
88         return str_impl != op.str_impl;
89     }
90 
size() const91     std::size_t size() const noexcept
92     {
93         return str_impl.size();
94     }
95 
resize(std::size_t n)96     void resize (std::size_t n)
97     {
98         str_impl.resize(n);
99     }
100 
resize(std::size_t n,char c)101     void resize (std::size_t n, char c)
102     {
103         str_impl.resize(n, c);
104     }
105 
106     template <typename op_type>
operator <(const op_type & op) const107     bool operator<(const op_type& op) const
108     {
109         return str_impl < op;
110     }
111 
operator <(const alt_string & op) const112     bool operator<(const alt_string& op) const
113     {
114         return str_impl < op.str_impl;
115     }
116 
c_str() const117     const char* c_str() const
118     {
119         return str_impl.c_str();
120     }
121 
operator [](std::size_t index)122     char& operator[](std::size_t index)
123     {
124         return str_impl[index];
125     }
126 
operator [](std::size_t index) const127     const char& operator[](std::size_t index) const
128     {
129         return str_impl[index];
130     }
131 
back()132     char& back()
133     {
134         return str_impl.back();
135     }
136 
back() const137     const char& back() const
138     {
139         return str_impl.back();
140     }
141 
clear()142     void clear()
143     {
144         str_impl.clear();
145     }
146 
data()147     const value_type* data()
148     {
149         return str_impl.data();
150     }
151 
152   private:
153     std::string str_impl {};
154 
155     friend bool ::operator<(const char*, const alt_string&);
156 };
157 
int_to_string(alt_string & target,std::size_t value)158 void int_to_string(alt_string& target, std::size_t value)
159 {
160     target = std::to_string(value).c_str();
161 }
162 
163 using alt_json = nlohmann::basic_json <
164                  std::map,
165                  std::vector,
166                  alt_string,
167                  bool,
168                  std::int64_t,
169                  std::uint64_t,
170                  double,
171                  std::allocator,
172                  nlohmann::adl_serializer >;
173 
174 
operator <(const char * op1,const alt_string & op2)175 bool operator<(const char* op1, const alt_string& op2)
176 {
177     return op1 < op2.str_impl;
178 }
179 
180 TEST_CASE("alternative string type")
181 {
182     SECTION("dump")
183     {
184         {
185             alt_json doc;
186             doc["pi"] = 3.141;
187             alt_string dump = doc.dump();
188             CHECK(dump == R"({"pi":3.141})");
189         }
190 
191         {
192             alt_json doc;
193             doc["happy"] = true;
194             alt_string dump = doc.dump();
195             CHECK(dump == R"({"happy":true})");
196         }
197 
198         {
199             alt_json doc;
200             doc["name"] = "I'm Batman";
201             alt_string dump = doc.dump();
202             CHECK(dump == R"({"name":"I'm Batman"})");
203         }
204 
205         {
206             alt_json doc;
207             doc["nothing"] = nullptr;
208             alt_string dump = doc.dump();
209             CHECK(dump == R"({"nothing":null})");
210         }
211 
212         {
213             alt_json doc;
214             doc["answer"]["everything"] = 42;
215             alt_string dump = doc.dump();
216             CHECK(dump == R"({"answer":{"everything":42}})");
217         }
218 
219         {
220             alt_json doc;
221             doc["list"] = { 1, 0, 2 };
222             alt_string dump = doc.dump();
223             CHECK(dump == R"({"list":[1,0,2]})");
224         }
225 
226         {
227             alt_json doc;
228             doc["object"] = { {"currency", "USD"}, {"value", 42.99} };
229             alt_string dump = doc.dump();
230             CHECK(dump == R"({"object":{"currency":"USD","value":42.99}})");
231         }
232     }
233 
234     SECTION("parse")
235     {
236         auto doc = alt_json::parse("{\"foo\": \"bar\"}");
237         alt_string dump = doc.dump();
238         CHECK(dump == R"({"foo":"bar"})");
239     }
240 
241     SECTION("items")
242     {
243         auto doc = alt_json::parse("{\"foo\": \"bar\"}");
244 
245         for ( auto item : doc.items() )
246         {
247             CHECK( item.key() == "foo" );
248             CHECK( item.value() == "bar" );
249         }
250 
251         auto doc_array = alt_json::parse("[\"foo\", \"bar\"]");
252 
253         for ( auto item : doc_array.items() )
254         {
255             if (item.key() == "0" )
256             {
257                 CHECK( item.value() == "foo" );
258             }
259             else if (item.key() == "1" )
260             {
261                 CHECK( item.value() == "bar" );
262             }
263             else
264             {
265                 CHECK( false );
266             }
267         }
268     }
269 
270     SECTION("equality")
271     {
272         alt_json doc;
273         doc["Who are you?"] = "I'm Batman";
274 
275         CHECK("I'm Batman" == doc["Who are you?"]);
276         CHECK(doc["Who are you?"]  == "I'm Batman");
277         CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
278         CHECK_FALSE(doc["Who are you?"]  != "I'm Batman");
279 
280         CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
281         CHECK(doc["Who are you?"]  != "I'm Bruce Wayne");
282         CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
283         CHECK_FALSE(doc["Who are you?"]  == "I'm Bruce Wayne");
284 
285         {
286             const alt_json& const_doc = doc;
287 
288             CHECK("I'm Batman" == const_doc["Who are you?"]);
289             CHECK(const_doc["Who are you?"] == "I'm Batman");
290             CHECK_FALSE("I'm Batman" != const_doc["Who are you?"]);
291             CHECK_FALSE(const_doc["Who are you?"] != "I'm Batman");
292 
293             CHECK("I'm Bruce Wayne" != const_doc["Who are you?"]);
294             CHECK(const_doc["Who are you?"] != "I'm Bruce Wayne");
295             CHECK_FALSE("I'm Bruce Wayne" == const_doc["Who are you?"]);
296             CHECK_FALSE(const_doc["Who are you?"] == "I'm Bruce Wayne");
297         }
298     }
299 }
300