Direct-BT  2.3.1
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 
35 extern "C" {
36  #include <errno.h>
37 }
38 
39 #include <jau/basic_types.hpp>
40 
41 namespace jau {
42 
43  /**
44  * Base jau environment class,
45  * merely to tag all environment settings by inheritance and hence documentation.
46  * <p>
47  * See main environment {@link environment} and
48  * {@link environment::getExplodingProperties(const std::string & prefix_domain)}.
49  * </p>
50  */
52  };
53 
54  /**
55  * Main jau environment class,
56  * supporting environment variable access and fetching elapsed time using its stored startup-time.
57  */
58  class environment : public root_environment {
59  private:
60  const std::string root_prefix_domain;
61 
62  environment(const std::string & root_prefix_domain) noexcept;
63 
64  static bool local_debug;
65 
66  static void envSet(std::string prefix_domain, std::string basepair) noexcept;
67  static void envExplodeProperties(std::string prefix_domain, std::string list) noexcept;
68 
69  static bool getExplodingPropertiesImpl(const std::string & root_prefix_domain, const std::string & prefix_domain) noexcept;
70 
71  public:
72  /**
73  * Module startup time t0 in monotonic time in milliseconds.
74  */
75  static const uint64_t startupTimeMilliseconds;
76 
77  /**
78  * Returns current elapsed monotonic time in milliseconds since module startup, see {@link #startupTimeMilliseconds}.
79  */
80  static uint64_t getElapsedMillisecond() noexcept {
82  }
83 
84  /**
85  * Returns elapsed monotonic time in milliseconds since module startup comparing against the given timestamp, see {@link #startupTimeMilliseconds}.
86  */
87  static uint64_t getElapsedMillisecond(const uint64_t& current_ts) noexcept {
88  return current_ts - startupTimeMilliseconds;
89  }
90 
91  /**
92  * Returns the value of the environment's variable 'name'.
93  * <p>
94  * Note that only '[org.]tinyb.*' and 'direct_bt.*' Java JVM properties are passed via 'org.tinyb.BluetoothFactory'
95  * </p>
96  * <p>
97  * Implementation attempts to also find a Unix conform environment name,
98  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.</br>
99  *
100  * Dots are not allowed as valid Unix envrionment variable identifier.
101  * If the property 'name' isn't found and if the 'name' contains a dot ('.'),
102  * all dots ('.') will be replaced y underscore ('_') and looked up again.</br>
103  * This allows Unix shell user to set the property 'direct_bt_debug' instead of 'direct_bt.debug'.
104  * </p>
105  */
106  static std::string getProperty(const std::string & name) noexcept;
107 
108  /**
109  * Returns the value of the environment's variable 'name',
110  * or the 'default_value' if the environment variable's value is null.
111  * <p>
112  * Implementation uses {@link #getProperty(const std::string & name)}
113  * and hence attempts to also find a Unix conform name,
114  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
115  * </p>
116  */
117  static std::string getProperty(const std::string & name, const std::string & default_value) noexcept;
118 
119  /**
120  * Returns the boolean value of the environment's variable 'name',
121  * or the 'default_value' if the environment variable's value is null.
122  * <p>
123  * If the environment variable is set (value != null),
124  * true is determined if the value equals 'true'.
125  * </p>
126  * <p>
127  * Implementation uses {@link #getProperty(const std::string & name)}
128  * and hence attempts to also find a Unix conform name,
129  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
130  * </p>
131  */
132  static bool getBooleanProperty(const std::string & name, const bool default_value) noexcept;
133 
134  /**
135  * Returns the int32_t value of the environment's variable 'name',
136  * or the 'default_value' if the environment variable's value is null
137  * or not within int32_t value range or within the given value range.
138  * <p>
139  * Implementation uses {@link #getProperty(const std::string & name)}
140  * and hence attempts to also find a Unix conform name,
141  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
142  * </p>
143  */
144  static int32_t getInt32Property(const std::string & name, const int32_t default_value,
145  const int32_t min_allowed=INT32_MIN, const int32_t max_allowed=INT32_MAX) noexcept;
146 
147  /**
148  * Returns the uint32_t value of the environment's variable 'name',
149  * or the 'default_value' if the environment variable's value is null
150  * or not within uint32_t value range or within the given value range.
151  * <p>
152  * Implementation uses {@link #getProperty(const std::string & name)}
153  * and hence attempts to also find a Unix conform name,
154  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
155  * </p>
156  */
157  static uint32_t getUint32Property(const std::string & name, const uint32_t default_value,
158  const uint32_t min_allowed=0, const uint32_t max_allowed=UINT32_MAX) noexcept;
159 
160  /**
161  * Fetches exploding variable-name (prefix_domain) values.
162  * <p>
163  * Implementation uses {@link #getProperty(const std::string & name)}
164  * and hence attempts to also find a Unix conform name,
165  * e.g. 'direct_bt_debug' if ''direct_bt.debug' wasn't found.
166  * </p>
167  * <p>
168  * If the value of a prefix_domain is neither 'true' or 'false',
169  * it is treated as a list of sub-variable names including their optional value separated by comma ','.
170  * <p>
171  * If the value is not given for the sub-variable name, a boolean "true" will be used per default.
172  * </p>
173  * <p>
174  * Example 1
175  * <pre>
176  * Input Environment:
177  * "direct_bt.debug" := "jni,adapter.event,gatt.data=false,hci.event,mgmt.event=true"
178  *
179  * Result Environment:
180  * "direct_bt.debug.jni" := "true"
181  * "direct_bt.debug.adapter.event" := "true"
182  * "direct_bt.debug.gatt.data" := "false"
183  * "direct_bt.debug.hci.event" := "true"
184  * "direct_bt.debug.mgmt.event" := "true"
185  * "direct_bt.debug" := "true" (will be overwritten)
186  * </pre>
187  * Example 2
188  * <pre>
189  * Input Environment:
190  * "direct_bt.gatt" := "cmd.read.timeout=20000,cmd.write.timeout=20001,ringsize=256"
191  *
192  * Result Environment:
193  * "direct_bt.gatt.cmd.read.timeout" := "20000"
194  * "direct_bt.gatt.cmd.write.timeout" := "20001"
195  * "direct_bt.gatt.ringsize" := "256"
196  * "direct_bt.gatt" := "true" (will be overwritten)
197  * </pre>
198  * </p>
199  * <p>
200  * Each sub-variable name/value pair will be trimmed and if not zero-length
201  * appended to the prefix_domain with a dot '.'.</br>
202  *
203  * Each new variable name will be set in the environment with value 'true'.</br>
204  *
205  * The prefix_domain will also be set to the new value 'true', hence gets overwritten.
206  * </p>
207  * <p>
208  * This is automatically performed for environment::debug root_prefix_domain+".debug",
209  * and environment::verbose root_prefix_domain+'.verbose',
210  * e.g: 'direct_bt.debug' and verbose 'direct_bt.verbose'.
211  * </p>
212  *
213  * @param prefix_domain the queried prefix domain, e.g. "direct_bt.debug" or "direct_bt.verbose" etc.
214  * @return
215  */
216  static bool getExplodingProperties(const std::string & prefix_domain) noexcept {
217  return getExplodingPropertiesImpl("", prefix_domain);
218  }
219 
220  /**
221  * Static singleton initialization of this project's environment
222  * with the given global root prefix_domain.
223  * <p>
224  * The root prefix_domain defines the value for environment::debug, environment::debug_jni and environment::verbose.
225  * </p>
226  * <p>
227  * The resulting singleton instance will be constructed only once.
228  * </p>
229  * @param root_prefix_domain the project's global singleton root prefix_domain, e.g. "direct_bt".
230  * Default value to "jau", only intended for subsequent queries.
231  * Initial call shall utilize the actual project's root_prefix_domain!
232  * @return the static singleton instance.
233  */
234  static environment& get(const std::string root_prefix_domain="jau") noexcept {
235  /**
236  * Thread safe starting with C++11 6.7:
237  *
238  * If control enters the declaration concurrently while the variable is being initialized,
239  * the concurrent execution shall wait for completion of the initialization.
240  *
241  * (Magic Statics)
242  *
243  * Avoiding non-working double checked locking.
244  */
245  static environment e(root_prefix_domain);
246  return e;
247  }
248 
249  /**
250  * Returns the project's global singleton root prefix_domain, used at first call of
251  * environment::get(const std::string root_prefix_domain).
252  */
253  const std::string & getRootPrefixDomain() const noexcept { return root_prefix_domain; }
254 
255  /**
256  * Debug logging enabled or disabled.
257  * <p>
258  * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.debug', boolean, default 'false',
259  * see get(const std::string & root_prefix_domain).
260  * </p>
261  * <p>
262  * Implementation uses {@link #getProperty(const std::string & name)}
263  * </p>
264  * <p>
265  * Exploding variable-name values are implemented here,
266  * see {@link #getExplodingProperties(const std::string & prefix_domain)}.
267  * </p>
268  */
269  const bool debug;
270 
271  /**
272  * JNI Debug logging enabled or disabled.
273  * <p>
274  * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.debug.jni', boolean, default 'false',
275  * see get(const std::string & root_prefix_domain).
276  * </p>
277  * <p>
278  * Implementation uses getBooleanProperty().
279  * </p>
280  */
281  const bool debug_jni;
282 
283  /**
284  * Verbose info logging enabled or disabled.
285  * <p>
286  * Environment variable depending on the root prefix_domain, e.g. for "direct_bt" this is 'direct_bt.verbose', boolean, default 'false',
287  * see get(const std::string & root_prefix_domain).
288  * </p>
289  * <p>
290  * Implementation uses {@link #getProperty(const std::string & name)}
291  * </p>
292  * <p>
293  * VERBOSE is also enabled if DEBUG is enabled!
294  * </p>
295  * <p>
296  * Exploding variable-name values are implemented here,
297  * see {@link #getExplodingProperties(const std::string & prefix_domain)}.
298  * </p>
299  */
300  const bool verbose;
301  };
302 
303 } // namespace jau
304 
305 #endif /* JAU_ENV_HPP_ */
306 
jau::environment::getElapsedMillisecond
static uint64_t getElapsedMillisecond(const uint64_t &current_ts) noexcept
Returns elapsed monotonic time in milliseconds since module startup comparing against the given times...
Definition: environment.hpp:87
jau::environment::get
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...
Definition: environment.hpp:234
jau::root_environment
Base jau environment class, merely to tag all environment settings by inheritance and hence documenta...
Definition: environment.hpp:51
jau::environment
Main jau environment class, supporting environment variable access and fetching elapsed time using it...
Definition: environment.hpp:58
jau::environment::getElapsedMillisecond
static uint64_t getElapsedMillisecond() noexcept
Returns current elapsed monotonic time in milliseconds since module startup, see startupTimeMilliseco...
Definition: environment.hpp:80
jau
Definition: basic_algos.hpp:34
jau::environment::getRootPrefixDomain
const std::string & getRootPrefixDomain() const noexcept
Returns the project's global singleton root prefix_domain, used at first call of environment::get(con...
Definition: environment.hpp:253
jau::environment::debug
const bool debug
Debug logging enabled or disabled.
Definition: environment.hpp:269
jau::environment::getUint32Property
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...
Definition: environment.cpp:134
jau::environment::getBooleanProperty
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:80
jau::environment::startupTimeMilliseconds
static const uint64_t startupTimeMilliseconds
Module startup time t0 in monotonic time in milliseconds.
Definition: environment.hpp:75
jau::environment::getInt32Property
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...
Definition: environment.cpp:94
jau::getCurrentMilliseconds
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:47
basic_types.hpp
jau::environment::getProperty
static std::string getProperty(const std::string &name) noexcept
Returns the value of the environment's variable 'name'.
Definition: environment.cpp:46
jau::environment::debug_jni
const bool debug_jni
JNI Debug logging enabled or disabled.
Definition: environment.hpp:281
jau::environment::getExplodingProperties
static bool getExplodingProperties(const std::string &prefix_domain) noexcept
Fetches exploding variable-name (prefix_domain) values.
Definition: environment.hpp:216
jau::environment::verbose
const bool verbose
Verbose info logging enabled or disabled.
Definition: environment.hpp:300