GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/environment.cpp
Date: 2026-09-07 02:25:23
Exec Total Coverage
Lines: 59 104 56.7%
Functions: 17 25 68.0%
Branches: 33 122 27.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #include <geogram/basic/environment.h>
41 #include <geogram/basic/assert.h>
42 #include <geogram/basic/logger.h>
43 #include <geogram/basic/argused.h>
44 #include <algorithm>
45 #include <stdlib.h>
46
47 namespace {
48 using namespace GEO;
49
50 /**
51 * \brief Root environment
52 * \details The root environment stores properties as name-value pairs in
53 * a dictionary.
54 */
55 249 class RootEnvironment : public Environment {
56 protected:
57 /** \copydoc GEO::Environment::get_local_value() */
58
2/2
✓ Branch 0 taken 8688 times.
✓ Branch 1 taken 1473 times.
10161 bool get_local_value(
59 const std::string& name, std::string& value
60 ) const override {
61 auto it = values_.find(name);
62
2/2
✓ Branch 0 taken 8688 times.
✓ Branch 1 taken 1473 times.
10161 if(it != values_.end()) {
63 8688 value = it->second;
64 8688 return true;
65 }
66 return false;
67 }
68
69 /** \copydoc GEO::Environment::set_local_value() */
70 11522 bool set_local_value(
71 const std::string& name, const std::string& value
72 ) override {
73 11522 values_[name] = value;
74 11522 return true;
75 }
76
77 /** \brief ProcessEnvironment destructor */
78 498 ~RootEnvironment() override {
79 498 }
80
81 private:
82 /** \brief Stores the variable values by name */
83 typedef std::map<std::string, std::string> ValueMap;
84 ValueMap values_;
85 };
86 }
87
88 namespace GEO {
89
90 /************************************************************************/
91
92 VariableObserver::VariableObserver(
93 const std::string& var_name
94 ) :
95 observed_variable_(var_name),
96 environment_(nullptr)
97 {
98 environment_ = Environment::instance()->find_environment(var_name);
99 geo_assert(environment_ != nullptr);
100 environment_->add_observer(var_name, this);
101 }
102
103 VariableObserver::~VariableObserver() {
104 environment_->remove_observer(observed_variable_, this);
105 }
106
107 /************************************************************************/
108
109 void VariableObserverList::notify_observers(
110 const std::string& value
111 ) {
112 if(block_notify_) {
113 return;
114 }
115 block_notify_ = true;
116 for(size_t i = 0; i < observers_.size(); i++) {
117 observers_[i]->value_changed(value);
118 }
119 block_notify_ = false;
120 }
121
122 void VariableObserverList::add_observer(
123 VariableObserver* observer
124 ) {
125 auto it = std::find(observers_.begin(), observers_.end(), observer);
126 geo_assert(it == observers_.end());
127 observers_.push_back(observer);
128 }
129
130 void VariableObserverList::remove_observer(
131 VariableObserver* observer
132 ) {
133 auto it = std::find(observers_.begin(), observers_.end(), observer);
134 geo_assert(it != observers_.end());
135 observers_.erase(it);
136 }
137
138 /************************************************************************/
139
140 Environment::Environment_var Environment::instance_;
141
142
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 24409 times.
24658 Environment* Environment::instance() {
143
2/2
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 24409 times.
24658 if(instance_ == nullptr) {
144 static bool created = false;
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if(created) {
146 std::cerr
147 << "CRITICAL: Environment::instance() "
148 << "called after the instance was deleted"
149 << std::endl;
150 geo_abort();
151 }
152 249 created = true;
153 249 instance_ = new RootEnvironment();
154 249 instance_->add_environment(new SystemEnvironment());
155 }
156 24658 return instance_;
157 }
158
159
1/2
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
249 void Environment::terminate() {
160 instance_.reset();
161 249 }
162
163 2490 Environment::~Environment() {
164 2490 }
165
166 996 bool Environment::add_environment(Environment* env) {
167
1/2
✓ Branch 0 taken 996 times.
✗ Branch 1 not taken.
996 environments_.push_back(env);
168 996 return true;
169 }
170
171
1/2
✓ Branch 1 taken 2192 times.
✗ Branch 2 not taken.
2192 bool Environment::has_value(const std::string& name) const {
172 std::string value;
173
1/2
✓ Branch 1 taken 2192 times.
✗ Branch 2 not taken.
4384 return get_value(name, value);
174 }
175
176 65028 bool Environment::set_value(
177 const std::string& name, const std::string& value
178 ) {
179
2/2
✓ Branch 0 taken 50780 times.
✓ Branch 1 taken 62302 times.
226164 for(size_t i = 0; i < environments_.size(); i++) {
180
2/2
✓ Branch 2 taken 2726 times.
✓ Branch 3 taken 48054 times.
50780 if(environments_[i]->set_value(name, value)) {
181 2726 notify_local_observers(name, value);
182 2726 return true;
183 }
184 }
185
2/2
✓ Branch 1 taken 14248 times.
✓ Branch 2 taken 48054 times.
62302 if(set_local_value(name, value)) {
186 14248 notify_local_observers(name, value);
187 14248 return true;
188 }
189 return false;
190 }
191
192 18080 bool Environment::get_value(
193 const std::string& name, std::string& value
194 ) const {
195
2/2
✓ Branch 1 taken 14100 times.
✓ Branch 2 taken 3980 times.
18080 if(get_local_value(name, value)) {
196 return true;
197 }
198
2/2
✓ Branch 0 taken 3935 times.
✓ Branch 1 taken 2552 times.
8994 for(size_t i = 0; i < environments_.size(); i++) {
199
2/2
✓ Branch 2 taken 1428 times.
✓ Branch 3 taken 2507 times.
3935 if(environments_[i]->get_value(name, value)) {
200 return true;
201 }
202 }
203 return false;
204 }
205
206
1/2
✓ Branch 1 taken 11953 times.
✗ Branch 2 not taken.
11953 std::string Environment::get_value(const std::string& name) const {
207 std::string value;
208
1/2
✓ Branch 1 taken 11953 times.
✗ Branch 2 not taken.
11953 bool variable_exists = get_value(name, value);
209
1/2
✓ Branch 0 taken 11953 times.
✗ Branch 1 not taken.
11953 if(!variable_exists) {
210 Logger::err("Environment")
211 << "No such variable: " << name
212 << std::endl;
213 Logger::err("Environment")
214 << "Probably missing CmdLine::import_arg_group(\"...\");"
215 << std::endl;
216 }
217 geo_assert(variable_exists);
218 11953 return value;
219 }
220
221 Environment* Environment::find_environment(const std::string& name) {
222 std::string value;
223 if(get_local_value(name, value)) {
224 return this;
225 }
226 for(index_t i=0; i<environments_.size(); ++i) {
227 Environment* result = environments_[i]->find_environment(name);
228 if(result != nullptr) {
229 return result;
230 }
231 }
232 return nullptr;
233 }
234
235 bool Environment::add_observer(
236 const std::string& name, VariableObserver* observer
237 ) {
238 observers_[name].add_observer(observer);
239 return true;
240 }
241
242 bool Environment::remove_observer(
243 const std::string& name, VariableObserver* observer
244 ) {
245 auto obs = observers_.find(name);
246 geo_assert(obs != observers_.end());
247 obs->second.remove_observer(observer);
248 return true;
249 }
250
251 3984 bool Environment::notify_observers(
252 const std::string& name, bool recursive
253 ) {
254 3984 std::string value = get_value(name);
255
1/2
✓ Branch 1 taken 3984 times.
✗ Branch 2 not taken.
7968 return notify_observers(name, value, recursive);
256 }
257
258 3984 bool Environment::notify_observers(
259 const std::string& name, const std::string& value,
260 bool recursive
261 ) {
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3984 times.
3984 if(recursive) {
263 for(size_t i = 0; i < environments_.size(); i++) {
264 environments_[i]->notify_observers(
265 name, value, true
266 );
267 }
268 }
269 3984 return notify_local_observers(name, value);
270 }
271
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20958 times.
20958 bool Environment::notify_local_observers(
273 const std::string& name, const std::string& value
274 ) {
275 auto it = observers_.find(name);
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20958 times.
20958 if(it != observers_.end()) {
277 it->second.notify_observers(value);
278 }
279 20958 return true;
280 }
281
282 /************************************************************************/
283
284 498 SystemEnvironment::~SystemEnvironment() {
285 498 }
286
287 14248 bool SystemEnvironment::set_local_value(
288 const std::string& name, const std::string& value
289 ) {
290 geo_argused(name);
291 geo_argused(value);
292 14248 return false;
293 }
294
295 1473 bool SystemEnvironment::get_local_value(
296 const std::string& name, std::string& value
297 ) const {
298 // For the moment, deactivated under Windows
299 #ifdef GEO_OS_WINDOWS
300 geo_argused(name);
301 geo_argused(value);
302 return false;
303 #else
304 1473 char* result = ::getenv(name.c_str());
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1473 times.
1473 if(result != nullptr) {
306 value = std::string(result);
307 }
308 1473 return result != nullptr;
309 #endif
310 }
311 }
312