Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
environment.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef JAU_ENV_HPP_
27#define JAU_ENV_HPP_
28
29#include <cstdint>
30#include <cinttypes>
31#include <cstring>
32#include <string>
33#include <cstdio>
34
35extern "C" {
36 #include <errno.h>
37}
38
39#include <jau/basic_types.hpp>
40
41namespace jau {
42
43 /** @defgroup SysUtils System and OS Utilities
44 * System and OS related types and functionality.
45 *
46 * @{
47 */
48
49 /**
50 * Base jau environment class,
51 * merely to tag all environment settings by inheritance and hence documentation.
52 * <p>
53 * See main environment {@link environment} and
54 * {@link environment::getExplodingProperties(const std::string & prefix_domain)}.
55 * </p>
56 */
58 public:
59 /**
60 * Optional path to signal early termination, i.e. JVM shutdown.
61 */
62 static void set_terminating() noexcept;
63 /**
64 * Returns true if program is terminating as detected via atexit() callback
65 * or set_terminating() has been called.
66 */
67 static bool is_terminating() noexcept;
68 };
69
70 /**
71 * Main jau environment class,
72 * supporting environment variable access and fetching elapsed time using its stored startup-time.
73 */
75 private:
76 const std::string root_prefix_domain;
77
78 environment(const std::string & root_prefix_domain) noexcept;
79
80 static bool local_debug;
81
82 static void envSet(const std::string& prefix_domain, std::string basepair) noexcept;
83 static void envExplodeProperties(const std::string& prefix_domain, const std::string& list) noexcept;
84
85 static bool getExplodingPropertiesImpl(const std::string& root_prefix_domain, const std::string & prefix_domain) noexcept;
86
87 public:
88 /**
89 * Module startup time t0 in monotonic time using high precision and range of fraction_timespec.
90 */
92
93 /**
94 * Module startup time t0 in monotonic time in milliseconds.
95 */
96 static const uint64_t startupTimeMilliseconds;
97
98 /**
99 * Returns elapsed monotonic time using fraction_timespec since module startup,
100 * see {@link #startupTimeMonotonic} and getMonotonicTime().
101 * <pre>
102 * return getMonotonicTime() - startupTimeMonotonic;
103 * </pre>
104 */
107 }
108
109 /**
110 * Returns elapsed monotonic time using fraction_timespec since module startup up to the given current_ts, see {@link #startupTimeMonotonic}.
111 * <pre>
112 * return current_ts - startupTimeMonotonic;
113 * </pre>
114 */
116 return current_ts - startupTimeMonotonic;
117 }
118
119 /**
120 * Returns current elapsed monotonic time in milliseconds since module startup, see {@link #startupTimeMilliseconds}.
121 */
122 static uint64_t getElapsedMillisecond() noexcept {
124 }
125
126 /**
127 * Returns elapsed monotonic time in milliseconds since module startup comparing against the given timestamp, see {@link #startupTimeMilliseconds}.
128 */
129 static uint64_t getElapsedMillisecond(const uint64_t& current_ts) noexcept {
130 return current_ts - startupTimeMilliseconds;
131 }
132
133 /**
134 * Returns the value of the environment's variable 'name'.
135 * <p>
136 * Note that only '[org.]tinyb.*' and 'direct_bt.*' Java JVM properties are passed via 'org.tinyb.BluetoothFactory'
137 * </p>
138 * <p>
139 * Implementation attempts to also find a Unix conform environment name,
140 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.</br>
141 *
142 * Dots are not allowed as valid Unix envrionment variable identifier.
143 * If the property 'name' isn't found and if the 'name' contains a dot ('.'),
144 * all dots ('.') will be replaced y underscore ('_') and looked up again.</br>
145 * This allows Unix shell user to set the property 'direct_bt_debug' instead of 'direct_bt.debug'.
146 * </p>
147 */
148 static std::string getProperty(const std::string & name) noexcept;
149
150 /**
151 * Returns the value of the environment's variable 'name',
152 * or the 'default_value' if the environment variable's value is null.
153 * <p>
154 * Implementation uses {@link #getProperty(const std::string & name)}
155 * and hence attempts to also find a Unix conform name,
156 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
157 * </p>
158 */
159 static std::string getProperty(const std::string & name, const std::string & default_value) noexcept;
160
161 /**
162 * Returns the boolean value of the environment's variable 'name',
163 * or the 'default_value' if the environment variable's value is null.
164 * <p>
165 * If the environment variable is set (value != null),
166 * true is determined if the value equals 'true'.
167 * </p>
168 * <p>
169 * Implementation uses {@link #getProperty(const std::string & name)}
170 * and hence attempts to also find a Unix conform name,
171 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
172 * </p>
173 */
174 static bool getBooleanProperty(const std::string & name, const bool default_value) noexcept;
175
176 /**
177 * Returns the int32_t value of the environment's variable 'name',
178 * or the 'default_value' if the environment variable's value is null
179 * or not within int32_t value range or within the given value range.
180 * <p>
181 * Implementation uses {@link #getProperty(const std::string & name)}
182 * and hence attempts to also find a Unix conform name,
183 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
184 * </p>
185 */
186 static int32_t getInt32Property(const std::string & name, const int32_t default_value,
187 const int32_t min_allowed=INT32_MIN, const int32_t max_allowed=INT32_MAX) noexcept;
188
189 /**
190 * Returns the uint32_t value of the environment's variable 'name',
191 * or the 'default_value' if the environment variable's value is null
192 * or not within uint32_t value range or within the given value range.
193 * <p>
194 * Implementation uses {@link #getProperty(const std::string & name)}
195 * and hence attempts to also find a Unix conform name,
196 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
197 * </p>
198 */
199 static uint32_t getUint32Property(const std::string & name, const uint32_t default_value,
200 const uint32_t min_allowed=0, const uint32_t max_allowed=UINT32_MAX) noexcept;
201
202 /**
203 * Returns the fraction_i64 value of the environment's variable 'name' in format `<num>/<denom>`,
204 * with white space allowed, if within given fraction_i64 value range.
205 *
206 * Otherwise returns the 'default_value' if the environment variable's value is null
207 * or of invalid format or not within given fraction_i64 value range.
208 * <p>
209 * Implementation uses {@link #getProperty(const std::string & name)}
210 * and hence attempts to also find a Unix conform name,
211 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
212 * </p>
213 */
214 static fraction_i64 getFractionProperty(const std::string & name, const fraction_i64& default_value,
215 const fraction_i64& min_allowed, const fraction_i64& max_allowed) noexcept;
216
217 /**
218 * Fetches exploding variable-name (prefix_domain) values.
219 * <p>
220 * Implementation uses {@link #getProperty(const std::string & name)}
221 * and hence attempts to also find a Unix conform name,
222 * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
223 * </p>
224 * <p>
225 * If the value of a prefix_domain is neither 'true' or 'false',
226 * it is treated as a list of sub-variable names including their optional value separated by comma ','.
227 * <p>
228 * If the value is not given for the sub-variable name, a boolean "true" will be used per default.
229 * </p>
230 * <p>
231 * Example 1
232 * <pre>
233 * Input Environment:
234 * "direct_bt.debug" := "jni,adapter.event,gatt.data=false,hci.event,mgmt.event=true"
235 *
236 * Result Environment:
237 * "direct_bt.debug.jni" := "true"
238 * "direct_bt.debug.adapter.event" := "true"
239 * "direct_bt.debug.gatt.data" := "false"
240 * "direct_bt.debug.hci.event" := "true"
241 * "direct_bt.debug.mgmt.event" := "true"
242 * "direct_bt.debug" := "true" (will be overwritten)
243 * </pre>
244 * Example 2
245 * <pre>
246 * Input Environment:
247 * "direct_bt.gatt" := "cmd.read.timeout=20000,cmd.write.timeout=20001,ringsize=256"
248 *
249 * Result Environment:
250 * "direct_bt.gatt.cmd.read.timeout" := "20000"
251 * "direct_bt.gatt.cmd.write.timeout" := "20001"
252 * "direct_bt.gatt.ringsize" := "256"
253 * "direct_bt.gatt" := "true" (will be overwritten)
254 * </pre>
255 * </p>
256 * <p>
257 * Each sub-variable name/value pair will be trimmed and if not zero-length
258 * appended to the prefix_domain with a dot '.'.</br>
259 *
260 * Each new variable name will be set in the environment with value 'true'.</br>
261 *
262 * The prefix_domain will also be set to the new value 'true', hence gets overwritten.
263 * </p>
264 * <p>
265 * This is automatically performed for environment::debug root_prefix_domain+".debug",
266 * and environment::verbose root_prefix_domain+'.verbose',
267 * e.g: 'direct_bt.debug' and verbose 'direct_bt.verbose'.
268 * </p>
269 *
270 * @param prefix_domain the queried prefix domain, e.g. "direct_bt.debug" or "direct_bt.verbose" etc.
271 * @return
272 */
273 static bool getExplodingProperties(const std::string & prefix_domain) noexcept {
274 return getExplodingPropertiesImpl("", prefix_domain);
275 }
276
277 /**
278 * Static singleton initialization of this project's environment
279 * with the given global root prefix_domain.
280 * <p>
281 * The root prefix_domain defines the value for environment::debug, environment::debug_jni and environment::verbose.
282 * </p>
283 * <p>
284 * The resulting singleton instance will be constructed only once.
285 * </p>
286 * @param root_prefix_domain the project's global singleton root prefix_domain, e.g. "direct_bt".
287 * Default value to "jau", only intended for subsequent queries.
288 * Initial call shall utilize the actual project's root_prefix_domain!
289 * @return the static singleton instance.
290 */
291 static environment& get(const std::string& root_prefix_domain="jau") noexcept {
292 /**
293 * Thread safe starting with C++11 6.7:
294 *
295 * If control enters the declaration concurrently while the variable is being initialized,
296 * the concurrent execution shall wait for completion of the initialization.
297 *
298 * (Magic Statics)
299 *
300 * Avoiding non-working double checked locking.
301 */
302 static environment e(root_prefix_domain);
303 return e;
304 }
305
306 /**
307 * Returns the project's global singleton root prefix_domain, used at first call of
308 * environment::get(const std::string root_prefix_domain).
309 */
310 const std::string & getRootPrefixDomain() const noexcept { return root_prefix_domain; }
311
312 /**
313 * Debug logging enabled or disabled.
314 * <p>
315 * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.debug', boolean, default 'false',
316 * see get(const std::string & root_prefix_domain).
317 * </p>
318 * <p>
319 * Implementation uses {@link #getProperty(const std::string & name)}
320 * </p>
321 * <p>
322 * Exploding variable-name values are implemented here,
323 * see {@link #getExplodingProperties(const std::string & prefix_domain)}.
324 * </p>
325 */
326 const bool debug;
327
328 /**
329 * JNI Debug logging enabled or disabled.
330 * <p>
331 * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.debug.jni', boolean, default 'false',
332 * see get(const std::string & root_prefix_domain).
333 * </p>
334 * <p>
335 * Implementation uses getBooleanProperty().
336 * </p>
337 */
338 const bool debug_jni;
339
340 /**
341 * Verbose info logging enabled or disabled.
342 * <p>
343 * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.verbose', boolean, default 'false',
344 * see get(const std::string & root_prefix_domain).
345 * </p>
346 * <p>
347 * Implementation uses {@link #getProperty(const std::string & name)}
348 * </p>
349 * <p>
350 * VERBOSE is also enabled if DEBUG is enabled!
351 * </p>
352 * <p>
353 * Exploding variable-name values are implemented here,
354 * see {@link #getExplodingProperties(const std::string & prefix_domain)}.
355 * </p>
356 */
357 const bool verbose;
358 };
359
360 /**@}*/
361
362} // namespace jau
363
364#endif /* JAU_ENV_HPP_ */
365
Main jau environment class, supporting environment variable access and fetching elapsed time using it...
Definition: environment.hpp:74
static std::string getProperty(const std::string &name) noexcept
Returns the value of the environment's variable 'name'.
Definition: environment.cpp:60
const std::string & getRootPrefixDomain() const noexcept
Returns the project's global singleton root prefix_domain, used at first call of environment::get(con...
const bool verbose
Verbose info logging enabled or disabled.
const bool debug
Debug logging enabled or disabled.
static int32_t getInt32Property(const std::string &name, const int32_t default_value, const int32_t min_allowed=INT32_MIN, const int32_t max_allowed=INT32_MAX) noexcept
Returns the int32_t value of the environment's variable 'name', or the 'default_value' if the environ...
static fraction_i64 getFractionProperty(const std::string &name, const fraction_i64 &default_value, const fraction_i64 &min_allowed, const fraction_i64 &max_allowed) noexcept
Returns the fraction_i64 value of the environment's variable 'name' in format <num>/<denom>,...
static bool getBooleanProperty(const std::string &name, const bool default_value) noexcept
Returns the boolean value of the environment's variable 'name', or the 'default_value' if the environ...
Definition: environment.cpp:94
const bool debug_jni
JNI Debug logging enabled or disabled.
static const fraction_timespec startupTimeMonotonic
Module startup time t0 in monotonic time using high precision and range of fraction_timespec.
Definition: environment.hpp:91
static environment & get(const std::string &root_prefix_domain="jau") noexcept
Static singleton initialization of this project's environment with the given global root prefix_domai...
static fraction_timespec getElapsedMonotonicTime() noexcept
Returns elapsed monotonic time using fraction_timespec since module startup, see startupTimeMonotonic...
static uint64_t getElapsedMillisecond(const uint64_t &current_ts) noexcept
Returns elapsed monotonic time in milliseconds since module startup comparing against the given times...
static const uint64_t startupTimeMilliseconds
Module startup time t0 in monotonic time in milliseconds.
Definition: environment.hpp:96
static fraction_timespec getElapsedMonotonicTime(const fraction_timespec &current_ts) noexcept
Returns elapsed monotonic time using fraction_timespec since module startup up to the given current_t...
static bool getExplodingProperties(const std::string &prefix_domain) noexcept
Fetches exploding variable-name (prefix_domain) values.
static uint64_t getElapsedMillisecond() noexcept
Returns current elapsed monotonic time in milliseconds since module startup, see startupTimeMilliseco...
static uint32_t getUint32Property(const std::string &name, const uint32_t default_value, const uint32_t min_allowed=0, const uint32_t max_allowed=UINT32_MAX) noexcept
Returns the uint32_t value of the environment's variable 'name', or the 'default_value' if the enviro...
Base jau environment class, merely to tag all environment settings by inheritance and hence documenta...
Definition: environment.hpp:57
static void set_terminating() noexcept
Optional path to signal early termination, i.e.
Definition: environment.cpp:50
static bool is_terminating() noexcept
Returns true if program is terminating as detected via atexit() callback or set_terminating() has bee...
Definition: environment.cpp:49
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
Definition: basic_types.cpp:52
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:64
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...