GCC Code Coverage Report


Directory: ./
File: fpp-json.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 12 12 100.0%
Functions: 3 3 100.0%
Branches: 12 12 100.0%

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