GCC Code Coverage Report


Directory: ./
File: commands/Condition.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 1 1 100.0%
Functions: 1 1 100.0%
Branches: 0 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-2026 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 #include "fpp-json-fwd.h"
15 #include <memory>
16 #include <string>
17 #include <vector>
18
19 // Shared condition tree backing the "If" command's Check field (a
20 // conditionlist widget - one or more conditions, AND'd or OR'd together).
21 // Every leaf is a direct, synchronous call into an existing subsystem
22 // accessor - no I/O, no blocking, safe to call from any thread including
23 // (eventually, Phase 3) the player loop.
24 class ConditionNode {
25 public:
26 2072 virtual ~ConditionNode() = default;
27 virtual bool evaluate() const = 0;
28
29 // Compound tree: {"op":"AND"|"OR","not":bool,"conditions":[...]} for a
30 // group, or {"source":...,"name":...,"comparator":...,"value":...,"not":bool}
31 // for a leaf. Returns nullptr (never throws) on malformed JSON - callers
32 // should treat that as "condition false".
33 static std::unique_ptr<ConditionNode> FromJSON(const Json::Value& j);
34
35 // Reads one leaf's current raw value (before any comparator/Value is
36 // applied) - the exact same lookup a leaf's evaluate() uses internally,
37 // exposed for the If editor's "Show Current Value" preview button so
38 // picking the right Value to compare against isn't guesswork. found is
39 // set false if source/name doesn't currently resolve to anything (e.g.
40 // an MQTT topic never seen, or an unset Variable).
41 static std::string PreviewSourceValue(const std::string& source, const std::string& name, bool& found);
42
43 // Full ad-hoc-leaf evaluation for the Check editor's consolidated
44 // eye-preview modal: given the same Source/Name/Comparator/Value/Not a
45 // saved leaf would have, returns the LHS/RHS values it currently
46 // resolves to and the comparator's result - reuses the exact same
47 // evaluation path a real saved leaf's evaluate() does, so this preview
48 // can never drift from what actually happens at runtime.
49 static void PreviewLeafResult(const std::string& source, const std::string& name, const std::string& comparatorStr,
50 const std::string& value, bool negate, bool& lhsFound, std::string& lhsValue,
51 std::string& rhsValue, bool& result);
52
53 // How a Name/Value field's raw text will actually be treated at
54 // evaluate() time - same priority order as the private
55 // EvaluateNameOrExpression() in Condition.cpp: an exact match against a
56 // real variable name always wins first, before any '='/%%/formula
57 // detection ever runs. Exposed for GET /api/variables?validateExpression
58 // (Variables.cpp) so the Check editor's valid/invalid icon can tell "this
59 // matches a real variable" and "this compiles as a formula" apart from
60 // "this is just inert literal text" (Condition.cpp's own documented,
61 // non-error passthrough for unmatched plain text) - the raw
62 // ExpressionProcessor::compile() the icon used before always reported
63 // "valid" for the literal case too, so a typo'd variable name (e.g.
64 // missing/extra characters) looked identical to a real match.
65 enum class ExpressionKind { Variable,
66 Formula,
67 Literal };
68 static ExpressionKind ClassifyNameOrExpression(const std::string& text, bool& compileOk);
69 };
70