GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/environment.cpp
Date: 2026-09-07 02:37:58
Exec Total Coverage
Lines: 73 133 54.9%
Functions: 17 25 68.0%
Branches: 34 142 23.9%

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 class RootEnvironment : public Environment {
56 protected:
57 /** \copydoc GEO::Environment::get_local_value() */
58 10218 bool get_local_value(
59 const std::string& name, std::string& value
60 ) const override {
61
1/2
✓ Branch 1 taken 10218 times.
✗ Branch 2 not taken.
10218 auto it = values_.find(name);
62
2/2
✓ Branch 2 taken 8736 times.
✓ Branch 3 taken 1482 times.
10218 if(it != values_.end()) {
63
1/2
✓ Branch 2 taken 8736 times.
✗ Branch 3 not taken.
8736 value = it->second;
64 8736 return true;
65 }
66 1482 return false;
67 }
68
69 /** \copydoc GEO::Environment::set_local_value() */
70 11637 bool set_local_value(
71 const std::string& name, const std::string& value
72 ) override {
73 11637 values_[name] = value;
74 11637 return true;
75 }
76
77 /** \brief ProcessEnvironment destructor */
78 1004 ~RootEnvironment() override {
79 1004 }
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 24854 Environment* Environment::instance() {
143
2/2
✓ Branch 1 taken 251 times.
✓ Branch 2 taken 24603 times.
24854 if(instance_ == nullptr) {
144 static bool created = false;
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
251 if(created) {
146 std::cerr
147 << "CRITICAL: Environment::instance() "
148 << "called after the instance was deleted"
149 << std::endl;
150 geo_abort();
151 }
152 251 created = true;
153
2/6
✓ Branch 3 taken 251 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 251 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
251 instance_ = new RootEnvironment();
154
2/6
✓ Branch 4 taken 251 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 251 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
251 instance_->add_environment(new SystemEnvironment());
155 }
156 24854 return instance_;
157 }
158
159 251 void Environment::terminate() {
160 251 instance_.reset();
161 251 }
162
163 2510 Environment::~Environment() {
164 2510 }
165
166 1004 bool Environment::add_environment(Environment* env) {
167
1/2
✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
1004 environments_.push_back(env);
168 1004 return true;
169 }
170
171 2217 bool Environment::has_value(const std::string& name) const {
172 2217 std::string value;
173
1/2
✓ Branch 1 taken 2217 times.
✗ Branch 2 not taken.
4434 return get_value(name, value);
174 2217 }
175
176 65663 bool Environment::set_value(
177 const std::string& name, const std::string& value
178 ) {
179
2/2
✓ Branch 1 taken 51278 times.
✓ Branch 2 taken 62915 times.
114193 for(size_t i = 0; i < environments_.size(); i++) {
180
2/2
✓ Branch 3 taken 2748 times.
✓ Branch 4 taken 48530 times.
51278 if(environments_[i]->set_value(name, value)) {
181 2748 notify_local_observers(name, value);
182 2748 return true;
183 }
184 }
185
2/2
✓ Branch 1 taken 14385 times.
✓ Branch 2 taken 48530 times.
62915 if(set_local_value(name, value)) {
186 14385 notify_local_observers(name, value);
187 14385 return true;
188 }
189 48530 return false;
190 }
191
192 18197 bool Environment::get_value(
193 const std::string& name, std::string& value
194 ) const {
195
2/2
✓ Branch 1 taken 14188 times.
✓ Branch 2 taken 4009 times.
18197 if(get_local_value(name, value)) {
196 14188 return true;
197 }
198
2/2
✓ Branch 1 taken 3963 times.
✓ Branch 2 taken 2573 times.
6536 for(size_t i = 0; i < environments_.size(); i++) {
199
2/2
✓ Branch 3 taken 1436 times.
✓ Branch 4 taken 2527 times.
3963 if(environments_[i]->get_value(name, value)) {
200 1436 return true;
201 }
202 }
203 2573 return false;
204 }
205
206 12017 std::string Environment::get_value(const std::string& name) const {
207 12017 std::string value;
208
1/2
✓ Branch 1 taken 12017 times.
✗ Branch 2 not taken.
12017 bool variable_exists = get_value(name, value);
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12017 times.
12017 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
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12017 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12017 geo_assert(variable_exists);
218 12017 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 4016 bool Environment::notify_observers(
252 const std::string& name, bool recursive
253 ) {
254
1/2
✓ Branch 1 taken 4016 times.
✗ Branch 2 not taken.
4016 std::string value = get_value(name);
255
1/2
✓ Branch 1 taken 4016 times.
✗ Branch 2 not taken.
8032 return notify_observers(name, value, recursive);
256 4016 }
257
258 4016 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 4016 times.
4016 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 4016 return notify_local_observers(name, value);
270 }
271
272 21149 bool Environment::notify_local_observers(
273 const std::string& name, const std::string& value
274 ) {
275
1/2
✓ Branch 1 taken 21149 times.
✗ Branch 2 not taken.
21149 auto it = observers_.find(name);
276
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 21149 times.
21149 if(it != observers_.end()) {
277 it->second.notify_observers(value);
278 }
279 21149 return true;
280 }
281
282 /************************************************************************/
283
284 1004 SystemEnvironment::~SystemEnvironment() {
285 1004 }
286
287 14385 bool SystemEnvironment::set_local_value(
288 const std::string& name, const std::string& value
289 ) {
290 14385 geo_argused(name);
291 14385 geo_argused(value);
292 14385 return false;
293 }
294
295 1482 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 1482 char* result = ::getenv(name.c_str());
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1482 times.
1482 if(result != nullptr) {
306 value = std::string(result);
307 }
308 1482 return result != nullptr;
309 #endif
310 }
311 }
312