| 259 | } |
| 260 | |
| 261 | int |
| 262 | compare (const value& x, const value& y, bool null_equal_empty) |
| 263 | { |
| 264 | bool xn (x.null); |
| 265 | bool yn (y.null); |
| 266 | |
| 267 | assert (x.type == y.type || |
| 268 | (xn && x.type == nullptr) || |
| 269 | (yn && y.type == nullptr)); |
| 270 | |
| 271 | |
| 272 | if (xn || yn) |
| 273 | { |
| 274 | if (null_equal_empty) |
| 275 | { |
| 276 | if (!xn && (x.type == nullptr |
| 277 | ? x.as<names> ().empty () |
| 278 | : x.type->empty != nullptr && x.type->empty (x))) |
| 279 | xn = true; |
| 280 | |
| 281 | if (!yn && (y.type == nullptr |
| 282 | ? y.as<names> ().empty () |
| 283 | : y.type->empty != nullptr && y.type->empty (y))) |
| 284 | yn = true; |
| 285 | } |
| 286 | |
| 287 | // NULL value is always less than non-NULL. |
| 288 | // |
| 289 | return (xn > yn ? -1 : // !xn < !yn |
| 290 | xn < yn ? 1 : // !xn > !yn |
| 291 | 0); |
| 292 | } |
| 293 | |
| 294 | if (x.type == nullptr) |
| 295 | { |
| 296 | const names& xns (x.as<names> ()); |
| 297 | const names& yns (y.as<names> ()); |
| 298 | |
| 299 | // std::lexicographical_compare_three_way() is only available in C++20. |
| 300 | // |
| 301 | auto xi (xns.begin ()), xe (xns.end ()); |
| 302 | auto yi (yns.begin ()), ye (yns.end ()); |
| 303 | |
| 304 | for (;; ++xi, ++yi) |
| 305 | { |
| 306 | bool xd (xi == xe); |
| 307 | bool yd (yi == ye); |
| 308 | |
| 309 | if (xd) |
| 310 | { |
| 311 | if (yd) |
| 312 | break; // Equal. |
| 313 | else |
| 314 | return -1; // x shorter. |
| 315 | } |
| 316 | else if (yd) |
| 317 | return 1; // y shorter. |
| 318 |
no test coverage detected