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#include <nlohmann/json.hpp> 12using nlohmann::json; 13 14TEST_CASE("algorithms") 15{ 16 json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"}; 17 json j_object = {{"one", 1}, {"two", 2}}; 18 19 SECTION("non-modifying sequence operations") 20 { 21 SECTION("std::all_of") 22 { 23 CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value) 24 { 25 return !value.empty(); 26 })); 27 CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value) 28 { 29 return value.type() == json::value_t::number_integer; 30 })); 31 } 32 33 SECTION("std::any_of") 34 { 35 CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value) 36 { 37 return value.is_string() && value.get<std::string>() == "foo"; 38 })); 39 CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value) 40 { 41 return value.get<int>() > 1; 42 })); 43 } 44 45 SECTION("std::none_of") 46 { 47 CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value) 48 { 49 return value.empty(); 50 })); 51 CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value) 52 { 53 return value.get<int>() <= 0; 54 })); 55 } 56 57 SECTION("std::for_each") 58 { 59 SECTION("reading") 60 { 61 int sum = 0; 62 63 std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value) 64 { 65 if (value.is_number()) 66 { 67 sum += static_cast<int>(value); 68 } 69 }); 70 71 CHECK(sum == 45); 72 } 73 74 SECTION("writing") 75 { 76 auto add17 = [](json & value) 77 { 78 if (value.is_array()) 79 { 80 value.push_back(17); 81 } 82 }; 83 84 std::for_each(j_array.begin(), j_array.end(), add17); 85 86 CHECK(j_array[6] == json({1, 2, 3, 17})); 87 } 88 } 89 90 SECTION("std::count") 91 { 92 CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1); 93 } 94 95 SECTION("std::count_if") 96 { 97 CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value) 98 { 99 return (value.is_number()); 100 }) == 3); 101 CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&) 102 { 103 return true; 104 }) == 9); 105 } 106 107 SECTION("std::mismatch") 108 { 109 json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"}; 110 auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin()); 111 CHECK(*res.first == json({{"one", 1}, {"two", 2}})); 112 CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}})); 113 } 114 115 SECTION("std::equal") 116 { 117 SECTION("using operator==") 118 { 119 CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin())); 120 CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin())); 121 CHECK(!std::equal(j_array.begin(), j_array.end(), j_object.begin())); 122 } 123 124 SECTION("using user-defined comparison") 125 { 126 // compare objects only by size of its elements 127 json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"}; 128 CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin())); 129 CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(), 130 [](const json & a, const json & b) 131 { 132 return (a.size() == b.size()); 133 })); 134 } 135 } 136 137 SECTION("std::find") 138 { 139 auto it = std::find(j_array.begin(), j_array.end(), json(false)); 140 CHECK(std::distance(j_array.begin(), it) == 5); 141 } 142 143 SECTION("std::find_if") 144 { 145 auto it = std::find_if(j_array.begin(), j_array.end(), 146 [](const json & value) 147 { 148 return value.is_boolean(); 149 }); 150 CHECK(std::distance(j_array.begin(), it) == 4); 151 } 152 153 SECTION("std::find_if_not") 154 { 155 auto it = std::find_if_not(j_array.begin(), j_array.end(), 156 [](const json & value) 157 { 158 return value.is_number(); 159 }); 160 CHECK(std::distance(j_array.begin(), it) == 3); 161 } 162 163 SECTION("std::adjacent_find") 164 { 165 CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end()); 166 CHECK(std::adjacent_find(j_array.begin(), j_array.end(), 167 [](const json & v1, const json & v2) 168 { 169 return v1.type() == v2.type(); 170 }) == j_array.begin()); 171 } 172 } 173 174 SECTION("modifying sequence operations") 175 { 176 SECTION("std::reverse") 177 { 178 std::reverse(j_array.begin(), j_array.end()); 179 CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13})); 180 } 181 182 SECTION("std::rotate") 183 { 184 std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end()); 185 CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13})); 186 } 187 188 SECTION("std::partition") 189 { 190 auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v) 191 { 192 return v.is_string(); 193 }); 194 CHECK(std::distance(j_array.begin(), it) == 2); 195 CHECK(!it[2].is_string()); 196 } 197 } 198 199 SECTION("sorting operations") 200 { 201 SECTION("std::sort") 202 { 203 SECTION("with standard comparison") 204 { 205 json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr}; 206 std::sort(j.begin(), j.end()); 207 CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"})); 208 } 209 210 SECTION("with user-defined comparison") 211 { 212 json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr}; 213 std::sort(j.begin(), j.end(), [](const json & a, const json & b) 214 { 215 return a.size() < b.size(); 216 }); 217 CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}})); 218 } 219 220 SECTION("sorting an object") 221 { 222 json j({{"one", 1}, {"two", 2}}); 223 CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 224 } 225 } 226 227 SECTION("std::partial_sort") 228 { 229 json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr}; 230 std::partial_sort(j.begin(), j.begin() + 4, j.end()); 231 CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13})); 232 } 233 } 234 235 SECTION("set operations") 236 { 237 SECTION("std::merge") 238 { 239 { 240 json j1 = {2, 4, 6, 8}; 241 json j2 = {1, 2, 3, 5, 7}; 242 json j3; 243 244 std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); 245 CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8})); 246 } 247 } 248 249 SECTION("std::set_difference") 250 { 251 json j1 = {1, 2, 3, 4, 5, 6, 7, 8}; 252 json j2 = {1, 2, 3, 5, 7}; 253 json j3; 254 255 std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); 256 CHECK(j3 == json({4, 6, 8})); 257 } 258 259 SECTION("std::set_intersection") 260 { 261 json j1 = {1, 2, 3, 4, 5, 6, 7, 8}; 262 json j2 = {1, 2, 3, 5, 7}; 263 json j3; 264 265 std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); 266 CHECK(j3 == json({1, 2, 3, 5, 7})); 267 } 268 269 SECTION("std::set_union") 270 { 271 json j1 = {2, 4, 6, 8}; 272 json j2 = {1, 2, 3, 5, 7}; 273 json j3; 274 275 std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); 276 CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8})); 277 } 278 279 SECTION("std::set_symmetric_difference") 280 { 281 json j1 = {2, 4, 6, 8}; 282 json j2 = {1, 2, 3, 5, 7}; 283 json j3; 284 285 std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); 286 CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8})); 287 } 288 } 289 290 SECTION("heap operations") 291 { 292 std::make_heap(j_array.begin(), j_array.end()); 293 CHECK(std::is_heap(j_array.begin(), j_array.end())); 294 std::sort_heap(j_array.begin(), j_array.end()); 295 CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"})); 296 } 297} 298