| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | /* | ||
| 3 | * This file is part of the Falcon Player (FPP) and is Copyright (C) | ||
| 4 | * 2013-2022 by the Falcon Player Developers. | ||
| 5 | * | ||
| 6 | * The Falcon Player (FPP) is free software, and is covered under | ||
| 7 | * multiple Open Source licenses. Please see the included 'LICENSES' | ||
| 8 | * file for descriptions of what files are covered by each license. | ||
| 9 | * | ||
| 10 | * This source file is covered under the LGPL v2.1 as described in the | ||
| 11 | * included LICENSE.LGPL file. | ||
| 12 | */ | ||
| 13 | |||
| 14 | // Single include for jsoncpp that hides the platform path difference: | ||
| 15 | // Debian/Pi/BBB install the header as <jsoncpp/json/json.h>, while Homebrew on | ||
| 16 | // macOS installs it as <json/json.h>. Any file that uses Json:: should | ||
| 17 | // | ||
| 18 | // #include "fpp-json.h" | ||
| 19 | // | ||
| 20 | // instead of repeating the __has_include dance (or relying on it being pulled | ||
| 21 | // in transitively via fpp-pch.h). jsoncpp drags in a large chunk of the C++ | ||
| 22 | // standard library, so keeping it out of the universal include path (it is no | ||
| 23 | // longer force-included by fpp-pch.h under NOPCH/distcc builds) is what lets | ||
| 24 | // individual translation units stay lean. | ||
| 25 | |||
| 26 | #if __has_include(<jsoncpp/json/json.h>) | ||
| 27 | #include <jsoncpp/json/json.h> | ||
| 28 | #elif __has_include(<json/json.h>) | ||
| 29 | #include <json/json.h> | ||
| 30 | #endif | ||
| 31 | |||
| 32 | // isMember() throws Json::LogicError on anything that isn't objectValue/ | ||
| 33 | // nullValue, same restriction as operator[] and get(). The LoadJsonFromFile/ | ||
| 34 | // LoadJsonFromString(..., JsonRoot) overloads in common.cpp guarantee the | ||
| 35 | // *root* is the expected shape, but a nested field within a well-shaped root | ||
| 36 | // can still hold the wrong type (e.g. "ota" present but a string, not an | ||
| 37 | // object) - JsonHas() guards that case at the point of use. | ||
| 38 | 1596 | inline bool JsonHas(const Json::Value& v, const std::string& key) { | |
| 39 |
4/4✓ Branch 0 taken 1588 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1495 times.
✓ Branch 3 taken 93 times.
|
1596 | return v.isObject() && v.isMember(key); |
| 40 | } | ||
| 41 | |||
| 42 | // asInt()/asString() throw Json::LogicError when the value is present but holds | ||
| 43 | // a type that cannot convert (a string where a number was expected, an object, | ||
| 44 | // an out-of-range number). Config that reaches FPP from the API, a command | ||
| 45 | // argument, or a hand-edited file is not shape-checked, so reading it with a | ||
| 46 | // bare .asInt() turns a malformed field into an uncaught exception that aborts | ||
| 47 | // fppd. These return the default in every case a bare accessor would throw. | ||
| 48 | // | ||
| 49 | // A missing or null member yields the default, matching what the bare accessor | ||
| 50 | // already did for that case (Json::nullValue converts to 0 / ""). | ||
| 51 | 955 | inline int JsonInt(const Json::Value& v, const std::string& key, int def = 0) { | |
| 52 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 884 times.
|
955 | if (!JsonHas(v, key)) { |
| 53 | 71 | return def; | |
| 54 | } | ||
| 55 | 884 | const Json::Value& e = v[key]; | |
| 56 |
2/2✓ Branch 0 taken 881 times.
✓ Branch 1 taken 3 times.
|
884 | return e.isConvertibleTo(Json::intValue) ? e.asInt() : def; |
| 57 | } | ||
| 58 | |||
| 59 | 517 | inline std::string JsonString(const Json::Value& v, const std::string& key, const std::string& def = "") { | |
| 60 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 510 times.
|
517 | if (!JsonHas(v, key)) { |
| 61 | 7 | return def; | |
| 62 | } | ||
| 63 | 510 | const Json::Value& e = v[key]; | |
| 64 |
2/2✓ Branch 0 taken 508 times.
✓ Branch 1 taken 2 times.
|
510 | return e.isConvertibleTo(Json::stringValue) ? e.asString() : def; |
| 65 | } | ||
| 66 |