jaulib v1.3.0
Jau Support Library (C++, Java, ..)
basic_types.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <cstdint>
26#include <cinttypes>
27#include <cstring>
28
29#include <ctime>
30
31#include <algorithm>
32
33#include <jau/debug.hpp>
34#include <jau/basic_types.hpp>
35#include <jau/functional.hpp>
37
38using namespace jau;
39
40static constexpr const uint64_t NanoPerMilli = 1000'000UL;
41static constexpr const uint64_t MilliPerOne = 1'000UL;
42inline constexpr const uint64_t NanoPerOne = NanoPerMilli*MilliPerOne;
43
44/**
45 * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html>
46 * <p>
47 * Regarding avoiding kernel via VDSO,
48 * see <http://man7.org/linux/man-pages/man7/vdso.7.html>,
49 * clock_gettime seems to be well supported at least on kernel >= 4.4.
50 * Only bfin and sh are missing, while ia64 seems to be complicated.
51 */
53 struct timespec t;
54 ::clock_gettime(CLOCK_MONOTONIC, &t);
55 return fraction_timespec( (int64_t)t.tv_sec, (int64_t)t.tv_nsec );
56}
57
59 struct timespec t { 0, 0 };
60 ::clock_gettime(CLOCK_REALTIME, &t);
61 return fraction_timespec( (int64_t)t.tv_sec, (int64_t)t.tv_nsec );
62}
63
64uint64_t jau::getCurrentMilliseconds() noexcept {
65 struct timespec t { 0, 0 };
66 ::clock_gettime(CLOCK_MONOTONIC, &t);
67 return static_cast<uint64_t>( t.tv_sec ) * MilliPerOne +
68 static_cast<uint64_t>( t.tv_nsec ) / NanoPerMilli;
69}
70
71uint64_t jau::getWallClockSeconds() noexcept {
72 struct timespec t { 0, 0 };
73 ::clock_gettime(CLOCK_REALTIME, &t);
74 return static_cast<uint64_t>( t.tv_sec );
75}
76
77std::string fraction_timespec::to_string() const noexcept {
78 return std::to_string(tv_sec) + "s + " + std::to_string(tv_nsec) + "ns";
79}
80
81std::string fraction_timespec::to_iso8601_string() const noexcept {
82 std::time_t t0 = static_cast<std::time_t>(tv_sec);
83 struct std::tm tm_0;
84 if( nullptr == ::gmtime_r( &t0, &tm_0 ) ) {
85 return "1970-01-01T00:00:00.0Z"; // 22 + 1
86 } else {
87 // 2022-05-28T23:23:50Z 20+1
88 //
89 // 1655994850s + 228978909ns
90 // 2022-06-23T14:34:10.228978909Z 30+1
91 char b[30+1];
92 size_t p = ::strftime(b, sizeof(b), "%Y-%m-%dT%H:%M:%S", &tm_0);
93 if( 0 < p && p < sizeof(b)-1 ) {
94 const size_t remaining = sizeof(b) - p;
95 if( 0 < tv_nsec ) {
96 ::snprintf(b+p, remaining, ".%09" PRIi64 "Z", tv_nsec);
97 } else {
98 ::snprintf(b+p, remaining, "Z");
99 }
100 }
101 return std::string(b);
102 }
103}
104
105bool jau::milli_sleep(uint64_t td_ms, const bool ignore_irq) noexcept {
106 const int64_t td_ns_0 = static_cast<int64_t>( (td_ms * NanoPerMilli) % NanoPerOne );
107 struct timespec ts;
108 ts.tv_sec = static_cast<decltype(ts.tv_sec)>(td_ms/MilliPerOne); // signed 32- or 64-bit integer
109 ts.tv_nsec = td_ns_0;
110 int res;
111 do {
112 res = ::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
113 } while( ignore_irq && EINTR == res );
114 return 0 == res;
115}
116bool jau::sleep(const fraction_timespec& relative_time, const bool ignore_irq) noexcept {
117 struct timespec ts = relative_time.to_timespec();
118 int res;
119 do {
120 res = ::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
121 } while( ignore_irq && EINTR == res );
122 return 0 == res;
123}
124
125bool jau::sleep_until(const fraction_timespec& absolute_time, const bool monotonic, const bool ignore_irq) noexcept {
126 if( absolute_time <= fraction_tv::zero ) {
127 return false;
128 }
129 // typedef struct timespec __gthread_time_t;
130 struct timespec ts = absolute_time.to_timespec();
131 int res;
132 do {
133 res = ::clock_nanosleep(monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME,
134 TIMER_ABSTIME, &ts, &ts);
135 } while( ignore_irq && EINTR == res );
136 return 0 == res;
137}
138
139bool jau::sleep_for(const fraction_timespec& relative_time, const bool monotonic, const bool ignore_irq) noexcept {
140 if( relative_time <= fraction_tv::zero ) {
141 return false;
142 }
143 const fraction_timespec now = monotonic ? getMonotonicTime() : getWallClockTime();
144 return sleep_until( now + relative_time, monotonic, ignore_irq );
145}
146
147bool jau::sleep_for(const fraction_i64& relative_time, const bool monotonic, const bool ignore_irq) noexcept {
148 if( relative_time <= fractions_i64::zero ) {
149 return false;
150 }
151 bool overflow = false;
152 const fraction_timespec atime = ( monotonic ? getMonotonicTime() : getWallClockTime() ) + fraction_timespec(relative_time, &overflow);
153 if( overflow ) {
154 return false;
155 } else {
156 return sleep_until( atime, monotonic, ignore_irq );
157 }
158}
159
160#if defined(__linux__) && defined(__GLIBC__)
161 // Hack for glibc/pthread library w/o pthread_cond_clockwait,
162 // i.e. on g++8, arm32, Debian 10.
163 // Here we have to use pthread_cond_timedwait(), ignoring the clock type.
164 //
165 // __attribute__((weak)) tested w/ g++8.3, g++10 and clang-11
166 //
167 typedef __clockid_t os_clockid_t;
168 extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
169 pthread_mutex_t *__restrict __mutex,
170 os_clockid_t __clock_id,
171 const struct timespec *__restrict __abstime)
172 __nonnull ((1, 2, 4)) __attribute__((weak));
173
174 static bool __jau__has_pthread_cond_clockwait() noexcept {
175 const bool r = nullptr != pthread_cond_clockwait;
176 ::fprintf(stderr, "INFO: jau::has_pthread_cond_clockwait: %d\n", r);
177 return r;
178 }
179 static bool jau_has_pthread_cond_clockwait() noexcept {
180 static bool r = __jau__has_pthread_cond_clockwait();
181 return r;
182 }
183#else
184 typedef int32_t os_clockid_t;
185 static int pthread_cond_clockwait (pthread_cond_t * __cond,
186 pthread_mutex_t * __mutex,
187 os_clockid_t __clock_id,
188 const struct timespec * __abstime) {
189 (void)__cond;
190 (void)__mutex;
191 (void)__clock_id;
192 (void)__abstime;
193 return -1;
194 }
195
196 static bool jau_has_pthread_cond_clockwait() noexcept {
197 return false;
198 }
199#endif
200
201std::cv_status jau::wait_until(std::condition_variable& cv, std::unique_lock<std::mutex>& lock, const fraction_timespec& absolute_time, const bool monotonic) noexcept {
202 if( absolute_time <= fraction_tv::zero ) {
203 return std::cv_status::no_timeout;
204 }
205 // typedef struct timespec __gthread_time_t;
206 struct timespec ts = absolute_time.to_timespec();
207
209 pthread_cond_clockwait(cv.native_handle(), lock.mutex()->native_handle(),
210 monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME, &ts);
211 } else {
212 ::pthread_cond_timedwait(cv.native_handle(), lock.mutex()->native_handle(), &ts);
213 }
214
215 const fraction_timespec now = monotonic ? getMonotonicTime() : getWallClockTime();
216 return now < absolute_time ? std::cv_status::no_timeout : std::cv_status::timeout;
217}
218
219std::cv_status jau::wait_for(std::condition_variable& cv, std::unique_lock<std::mutex>& lock, const fraction_timespec& relative_time, const bool monotonic) noexcept {
220 if( relative_time <= fraction_tv::zero ) {
221 return std::cv_status::no_timeout;
222 }
223 const fraction_timespec now = monotonic ? getMonotonicTime() : getWallClockTime();
224 return wait_until(cv, lock, now + relative_time, monotonic);
225}
226
227std::cv_status jau::wait_for(std::condition_variable& cv, std::unique_lock<std::mutex>& lock, const fraction_i64& relative_time, const bool monotonic) noexcept {
228 if( relative_time <= fractions_i64::zero ) {
229 return std::cv_status::no_timeout;
230 }
231 bool overflow = false;
232 const fraction_timespec atime = ( monotonic ? getMonotonicTime() : getWallClockTime() ) + fraction_timespec(relative_time, &overflow);
233 if( overflow ) {
234 return std::cv_status::timeout;
235 } else {
236 return wait_until(cv, lock, atime, monotonic);
237 }
238}
239
240jau::ExceptionBase::ExceptionBase(std::string type, std::string const& m, const char* file, int line) noexcept
241: msg_( std::move( type.append(" @ ").append(file).append(":").append(std::to_string(line)).append(": ").append(m) ) ),
242 backtrace_( jau::get_backtrace(true /* skip_anon_frames */) )
243{
244 what_ = msg_;
245 what_.append("\nNative backtrace:\n");
246 what_.append(backtrace_);
247}
248
249std::string jau::get_string(const uint8_t *buffer, nsize_t const buffer_len, nsize_t const max_len) noexcept {
250 const nsize_t cstr_max_len = std::min(buffer_len, max_len);
251 const size_t cstr_len = ::strnlen(reinterpret_cast<const char*>(buffer), cstr_max_len); // if cstr_len == cstr_max_len then no EOS
252 return std::string(reinterpret_cast<const char*>(buffer), cstr_len);
253}
254
255void jau::trimInPlace(std::string &s) noexcept {
256 s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
257 return !std::isspace(ch);
258 }));
259 s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
260 return !std::isspace(ch);
261 }).base(), s.end());
262}
263
264std::string jau::trim(const std::string &_s) noexcept {
265 std::string s(_s);
266 trimInPlace(s);
267 return s;
268}
269
270std::vector<std::string> jau::split_string(const std::string& str, const std::string& separator) noexcept {
271 std::vector<std::string> res;
272 size_t p0 = 0;
273 while( p0 != std::string::npos && p0 < str.size() ) {
274 size_t p1 = str.find(separator, p0);
275 res.push_back(str.substr(p0, p1)); // incl. npos
276 if( p1 != std::string::npos ) {
277 p1 += separator.length();
278 }
279 p0 = p1;
280 }
281 return res;
282}
283
284std::string& jau::toLowerInPlace(std::string& s) noexcept {
285 std::transform(s.begin(), s.end(), s.begin(),
286 [](unsigned char c){ return std::tolower(c); });
287 return s;
288}
289std::string jau::toLower(const std::string& s) noexcept {
290 std::string t(s); toLowerInPlace(t); return t;
291}
292
293// one static_assert is sufficient for whole compilation unit
294static_assert( is_defined_endian(endian_t::native) );
295static_assert( is_little_or_big_endian() );
296
297uint128dp_t jau::merge_uint128(uint16_t const uuid16, uint128dp_t const & base_uuid, nsize_t const uuid16_le_octet_index)
298{
299 if( uuid16_le_octet_index > 14 ) {
300 std::string msg("uuid16_le_octet_index ");
301 msg.append(std::to_string(uuid16_le_octet_index));
302 msg.append(", not within [0..14]");
304 }
305 uint128dp_t dest = base_uuid;
306
307 // base_uuid: 00000000-0000-1000-8000-00805F9B34FB
308 // uuid16: DCBA
309 // uuid16_le_octet_index: 12
310 // result: 0000DCBA-0000-1000-8000-00805F9B34FB
311 //
312 // LE: low-mem - FB349B5F8000-0080-0010-0000-ABCD0000 - high-mem
313 // ^ index 12
314 // LE: uuid16 -> value.data[12+13]
315 //
316 // BE: low-mem - 0000DCBA-0000-1000-8000-00805F9B34FB - high-mem
317 // ^ index 2
318 // BE: uuid16 -> value.data[2+3]
319 //
320 nsize_t offset;
321 if( is_big_endian() ) {
322 offset = 15 - 1 - uuid16_le_octet_index;
323 } else {
324 offset = uuid16_le_octet_index;
325 }
326 // uint16_t * destu16 = (uint16_t*)(dest.data + offset);
327 // *destu16 += uuid16;
328 reinterpret_cast<packed_t<uint16_t>*>( dest.data + offset )->store += uuid16;
329 return dest;
330}
331
332uint128dp_t jau::merge_uint128(uint32_t const uuid32, uint128dp_t const & base_uuid, nsize_t const uuid32_le_octet_index)
333{
334 if( uuid32_le_octet_index > 12 ) {
335 std::string msg("uuid32_le_octet_index ");
336 msg.append(std::to_string(uuid32_le_octet_index));
337 msg.append(", not within [0..12]");
339 }
340 uint128dp_t dest = base_uuid;
341
342 // base_uuid: 00000000-0000-1000-8000-00805F9B34FB
343 // uuid32: 87654321
344 // uuid32_le_octet_index: 12
345 // result: 87654321-0000-1000-8000-00805F9B34FB
346 //
347 // LE: low-mem - FB349B5F8000-0080-0010-0000-12345678 - high-mem
348 // ^ index 12
349 // LE: uuid32 -> value.data[12..15]
350 //
351 // BE: low-mem - 87654321-0000-1000-8000-00805F9B34FB - high-mem
352 // ^ index 0
353 // BE: uuid32 -> value.data[0..3]
354 //
355 nsize_t offset;;
356 if( is_big_endian() ) {
357 offset = 15 - 3 - uuid32_le_octet_index;
358 } else {
359 offset = uuid32_le_octet_index;
360 }
361 // uint32_t * destu32 = (uint32_t*)(dest.data + offset);
362 // *destu32 += uuid32;
363 reinterpret_cast<packed_t<uint32_t>*>( dest.data + offset )->store += uuid32;
364 return dest;
365}
366
367std::string jau::vformat_string(const char* format, va_list ap) noexcept {
368 size_t nchars;
369 std::string str;
370 {
371 const size_t bsz = 1024; // including EOS
372 str.reserve(bsz); // incl. EOS
373 str.resize(bsz-1); // excl. EOS
374
375 nchars = vsnprintf(&str[0], bsz, format, ap); // NOLINT(clang-analyzer-valist.Uninitialized): clang-tidy bug
376 if( nchars < bsz ) {
377 str.resize(nchars);
378 str.shrink_to_fit();
379 return str;
380 }
381 }
382 {
383 const size_t bsz = std::min<size_t>(nchars+1, str.max_size()+1); // limit incl. EOS
384 str.reserve(bsz); // incl. EOS
385 str.resize(bsz-1); // excl. EOS
386 nchars = vsnprintf(&str[0], bsz, format, ap); // NOLINT(clang-analyzer-valist.Uninitialized): clang-tidy bug
387 str.resize(nchars);
388 return str;
389 }
390}
391
392std::string jau::format_string(const char* format, ...) noexcept {
393 va_list args;
394 va_start (args, format);
395 std::string str = vformat_string(format, args);
396 va_end (args);
397 return str;
398}
399
400static snsize_t hexCharByte_(const uint8_t c)
401{
402 if('0' <= c && c <= '9') {
403 return c - '0';
404 }
405 if('A' <= c && c <= 'F') {
406 return c - 'A' + 10;
407 }
408 if('a' <= c && c <= 'f') {
409 return c - 'a' + 10;
410 }
411 return -1;
412}
413
414size_t jau::hexStringBytes(std::vector<uint8_t>& out, const std::string& hexstr, const bool lsbFirst, const bool checkLeading0x) noexcept {
415 return jau::hexStringBytes(out, cast_char_ptr_to_uint8(hexstr.data()), hexstr.size(), lsbFirst, checkLeading0x);
416}
417size_t jau::hexStringBytes(std::vector<uint8_t>& out, const uint8_t hexstr[], const size_t hexstr_len, const bool lsbFirst, const bool checkLeading0x) noexcept {
418 size_t offset;
419 if( checkLeading0x && hexstr_len >= 2 && hexstr[0] == '0' && hexstr[1] == 'x' ) {
420 offset = 2;
421 } else {
422 offset = 0;
423 }
424 size_t lsb, msb;
425 if( lsbFirst ) {
426 lsb = 1; msb = 0;
427 } else {
428 lsb = 0; msb = 1;
429 }
430 const size_t hexlen_in = hexstr_len - offset;
431 const size_t bsize = hexlen_in / 2;
432 out.clear();
433 out.reserve(bsize);
434
435 size_t i = 0;
436 if( 0 < hexlen_in % 2 ) {
437 // no leading '0', digest a single digit
438 const size_t idx = ( lsb*i + msb*(bsize-1-i) ) * 2;
439 const snsize_t l = hexCharByte_( hexstr[ offset + idx + 1 ] );
440 if( 0 <= l ) {
441 out.push_back( static_cast<uint8_t>( l ) );
442 } else {
443 // invalid char
444 return out.size();
445 }
446 ++i;
447 }
448 for (; i < bsize; ++i) {
449 const size_t idx = ( lsb*i + msb*(bsize-1-i) ) * 2;
450 const snsize_t h = hexCharByte_( hexstr[ offset + idx ] );
451 const snsize_t l = hexCharByte_( hexstr[ offset + idx + 1 ] );
452 if( 0 <= h && 0 <= l ) {
453 out.push_back( static_cast<uint8_t>( (h << 4) + l ) );
454 } else {
455 // invalid char
456 return out.size();
457 }
458 }
459 return out.size();
460}
461
462
463static const char* HEX_ARRAY_LOW = "0123456789abcdef";
464static const char* HEX_ARRAY_BIG = "0123456789ABCDEF";
465
466std::string jau::bytesHexString(const void* data, const nsize_t offset, const nsize_t length,
467 const bool lsbFirst, const bool lowerCase) noexcept
468{
469 const char* hex_array = lowerCase ? HEX_ARRAY_LOW : HEX_ARRAY_BIG;
470 std::string str;
471
472 if( nullptr == data ) {
473 return "null";
474 }
475 if( 0 == length ) {
476 return "nil";
477 }
478 const uint8_t * const bytes = static_cast<const uint8_t*>(data);
479 if( lsbFirst ) {
480 // LSB left -> MSB right, no leading `0x`
481 str.reserve(length * 2 +1);
482 for (nsize_t j = 0; j < length; j++) {
483 const int v = bytes[offset+j] & 0xFF;
484 str.push_back(hex_array[v >> 4]);
485 str.push_back(hex_array[v & 0x0F]);
486 }
487 } else {
488 // MSB left -> LSB right, with leading `0x`
489 str.reserve(2 + length * 2 +1);
490 str.push_back('0');
491 str.push_back('x');
492 nsize_t j = length;
493 do {
494 j--;
495 const int v = bytes[offset+j] & 0xFF;
496 str.push_back(hex_array[v >> 4]);
497 str.push_back(hex_array[v & 0x0F]);
498 } while( j != 0);
499 }
500 return str;
501}
502
503std::string& jau::byteHexString(std::string& dest, const uint8_t value, const bool lowerCase) noexcept
504{
505 const char* hex_array = lowerCase ? HEX_ARRAY_LOW : HEX_ARRAY_BIG;
506
507 if( 2 > dest.capacity() - dest.size() ) { // Until C++20, then reserve is ignored if capacity > reserve
508 dest.reserve(dest.size()+2);
509 }
510 const int v = value & 0xFF;
511 dest.push_back(hex_array[v >> 4]);
512 dest.push_back(hex_array[v & 0x0F]);
513 return dest;
514}
515
516std::string jau::to_string(const endian_t v) noexcept {
517 switch(v) {
518 case endian_t::little: return "little";
519 case endian_t::big: return "big";
520 case endian_t::pdp: return "pdb";
521 case endian_t::honeywell: return "honeywell";
522 case endian_t::undefined: return "undefined";
523 }
524 return "undef";
525}
526
527std::string jau::to_string(const lb_endian_t v) noexcept {
528 switch(v) {
529 case lb_endian_t::little: return "little";
530 case lb_endian_t::big: return "big";
531 }
532 return "undef";
533}
534
535std::string jau::to_string(const jau::func::target_type v) noexcept {
536 switch(v) {
537 case jau::func::target_type::null: return "null";
538 case jau::func::target_type::member: return "member";
539 case jau::func::target_type::free: return "free";
540 case jau::func::target_type::lambda: return "lambda";
541 case jau::func::target_type::ylambda: return "ylambda";
542 case jau::func::target_type::capval: return "capval";
543 case jau::func::target_type::capref: return "capref";
544 case jau::func::target_type::std: return "std";
545 }
546 return "undef";
547}
548
549bool jau::to_integer(long long & result, const char * str, size_t str_len, const char limiter, const char *limiter_pos) {
550 static constexpr const bool _debug = false;
551 char *endptr = nullptr;
552 if( nullptr == limiter_pos ) {
553 limiter_pos = str + str_len;
554 }
555 errno = 0;
556 const long long num = std::strtoll(str, &endptr, 10);
557 if( 0 != errno ) {
558 // value under- or overflow occured
559 if constexpr ( _debug ) {
560 INFO_PRINT("Value under- or overflow occurred, value %lld in: '%s', errno %d %s", num, str, errno, strerror(errno));
561 }
562 return false;
563 }
564 if( nullptr == endptr || endptr == str ) {
565 // no digits consumed
566 if constexpr ( _debug ) {
567 INFO_PRINT("Value no digits consumed @ idx %d, %p == start, in: '%s'", endptr-str, endptr, str);
568 }
569 return false;
570 }
571 if( endptr < limiter_pos ) {
572 while( endptr < limiter_pos && ::isspace(*endptr) ) { // only accept whitespace
573 ++endptr;
574 }
575 }
576 if( *endptr != limiter || endptr != limiter_pos ) {
577 // numerator value not completely valid
578 if constexpr ( _debug ) {
579 INFO_PRINT("Value end not '%c' @ idx %d, %p != %p, in: %p '%s' len %zd", limiter, endptr-str, endptr, limiter_pos, str, str, str_len);
580 }
581 return false;
582 }
583 result = num;
584 return true;
585}
586
587bool jau::to_integer(long long & result, const std::string& str, const char limiter, const char *limiter_pos) {
588 return to_integer(result, str.c_str(), str.size(), limiter, limiter_pos);
589}
590
591bool jau::to_fraction_i64(fraction_i64& result, const std::string & value, const fraction_i64& min_allowed, const fraction_i64& max_allowed) noexcept {
592 static constexpr const bool _debug = false;
593 const char * str = const_cast<const char*>(value.c_str());
594 const size_t str_len = value.length();
595 const char *divptr = nullptr;
596
597 divptr = std::strstr(str, "/");
598 if( nullptr == divptr ) {
599 if constexpr ( _debug ) {
600 INFO_PRINT("Missing '/' in: '%s'", str);
601 }
602 return false;
603 }
604
605 long long num;
606 if( !to_integer(num, str, str_len, '/', divptr) ) {
607 return false;
608 }
609
610 long long denom; // 0x7ffc7090d904 != 0x7ffc7090d907 " 10 / 1000000 "
611 if( !to_integer(denom, divptr+1, str_len-(divptr-str)-1, '\0', str + str_len) ) {
612 return false;
613 }
614
615 fraction_i64 temp((int64_t)num, (uint64_t)denom);
616 if( ! ( min_allowed <= temp && temp <= max_allowed ) ) {
617 // invalid user value range
618 if constexpr ( _debug ) {
619 INFO_PRINT("Numerator out of range, not %s <= %s <= %s, in: '%s'", min_allowed.to_string().c_str(), temp.to_string().c_str(), max_allowed.to_string().c_str(), str);
620 }
621 return false;
622 }
623 result = temp;
624 return true;
625}
626
627std::string jau::math::to_string(const jau::math::math_error_t v) noexcept {
628 switch(v) {
629 case jau::math::math_error_t::invalid: return "invalid";
630 case jau::math::math_error_t::div_by_zero: return "div_by_zero";
631 case jau::math::math_error_t::overflow: return "overflow";
632 case jau::math::math_error_t::underflow: return "underflow";
633 case jau::math::math_error_t::inexact: return "inexact";
634 }
635 return "unknown";
636}
static const char * HEX_ARRAY_BIG
static snsize_t hexCharByte_(const uint8_t c)
static constexpr const uint64_t MilliPerOne
Definition: basic_types.cpp:41
static constexpr const uint64_t NanoPerMilli
Definition: basic_types.cpp:40
int32_t os_clockid_t
static int pthread_cond_clockwait(pthread_cond_t *__cond, pthread_mutex_t *__mutex, os_clockid_t __clock_id, const struct timespec *__abstime)
static bool jau_has_pthread_cond_clockwait() noexcept
static const char * HEX_ARRAY_LOW
constexpr const uint64_t NanoPerOne
Definition: basic_types.cpp:42
#define E_FILE_LINE
ExceptionBase(std::string type, std::string const &m, const char *file, int line) noexcept
std::string to_string(const bool show_double=false) const noexcept
Returns a string representation of this fraction.
constexpr InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
Like std::find_if() of 'algorithm'.
constexpr bool is_big_endian() noexcept
Evaluates true if platform is running in big endian mode, i.e.
Definition: byte_util.hpp:316
constexpr bool is_defined_endian(const endian_t &v) noexcept
Evaluates true if the given endian is defined, i.e.
Definition: byte_util.hpp:275
constexpr bool is_little_or_big_endian() noexcept
Evaluates true if platform is running in little or big endian mode, i.e.
Definition: byte_util.hpp:324
endian_t
Endian identifier, indicating endianess of all scalar types.
Definition: byte_util.hpp:203
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
Definition: byte_util.hpp:227
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
const uint8_t * cast_char_ptr_to_uint8(const char *s) noexcept
Definition: byte_util.hpp:155
@ pdp
Identifier for DEC PDP-11, aka ENDIAN_LITTLE_WORD.
@ undefined
Undetermined endian.
@ native
Identifier for native platform type, one of the above.
@ little
Identifier for little endian.
@ honeywell
Identifier for Honeywell 316, aka ENDIAN_BIG_WORD.
@ big
Identifier for big endian.
@ little
Identifier for little endian, equivalent to endian::little.
@ big
Identifier for big endian, equivalent to endian::big.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
bool to_fraction_i64(fraction_i64 &result, const std::string &value, const fraction_i64 &min_allowed, const fraction_i64 &max_allowed) noexcept
Stores the fraction_i64 value of the given string value in format <num>/<denom>, which may contain wh...
fraction_timespec getWallClockTime() noexcept
Returns current wall-clock real-time since Unix Epoch 00:00:00 UTC on 1970-01-01.
Definition: basic_types.cpp:58
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
Definition: basic_types.cpp:52
target_type
func::target_type identifier for the target function delegate_t<R, A...> object, exposed by jau::func...
Definition: functional.hpp:341
@ null
Denotes a func::null_target_t.
@ lambda
Denotes a func::lambda_target_t.
@ capval
Denotes a func::capval_target_t.
@ capref
Denotes a func::capref_target_t.
@ member
Denotes a func::member_target_t.
@ free
Denotes a func::free_target_t.
@ std
Denotes a func::std_target_t.
@ ylambda
Denotes a func::ylambda_target_t.
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:177
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
uint128dp_t merge_uint128(uint16_t const uuid16, uint128dp_t const &base_uuid, nsize_t const uuid16_le_octet_index)
Merge the given 'uuid16' into a 'base_uuid' copy at the given little endian 'uuid16_le_octet_index' p...
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:65
math_error_t
Error types as specified by C++ Math Error Handling
Definition: math_error.hpp:46
std::string to_string(const math_error_t v) noexcept
Returns std::string representation of math_error_t.
@ underflow
See FE_UNDERFLOW.
@ overflow
See FE_OVERFLOW.
@ div_by_zero
See FE_DIVBYZERO.
@ inexact
See FE_INEXACT.
@ invalid
See FE_INVALID.
std::string & toLowerInPlace(std::string &s) noexcept
std::string format_string(const char *format,...) noexcept
Returns a string according to printf() formatting rules and variable number of arguments following th...
std::string trim(const std::string &s) noexcept
trim copy
std::string bytesHexString(const void *data, const nsize_t offset, const nsize_t length, const bool lsbFirst, const bool lowerCase=true) noexcept
Produce a hexadecimal string representation of the given byte values.
void trimInPlace(std::string &s) noexcept
trim in place
std::string get_string(const uint8_t *buffer, nsize_t const buffer_len, nsize_t const max_len) noexcept
Returns a C++ String taken from buffer with maximum length of min(max_len, max_len).
std::string & byteHexString(std::string &dest, const uint8_t value, const bool lowerCase) noexcept
Produce a hexadecimal string representation of the given byte value.
std::string vformat_string(const char *format, va_list ap) noexcept
Returns a string according to vprintf() formatting rules using va_list instead of a variable number o...
bool to_integer(long long &result, const std::string &str, const char limiter='\0', const char *limiter_pos=nullptr)
std::vector< std::string > split_string(const std::string &str, const std::string &separator) noexcept
Split given string str at separator into the resulting std::vector excluding the separator sequence .
std::string toLower(const std::string &s) noexcept
size_t hexStringBytes(std::vector< uint8_t > &out, const std::string &hexstr, const bool lsbFirst, const bool checkLeading0x) noexcept
Converts a given hexadecimal string representation into a byte vector.
constexpr const jau::fraction_timespec zero(0, 0)
jau::fraction_timespec zero is { 0, 0 }
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
std::string get_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::snsize_t skip_frames=1) noexcept
Returns a de-mangled backtrace string separated by newline excluding this function.
Definition: debug.cpp:94
std::cv_status wait_for(std::condition_variable &cv, std::unique_lock< std::mutex > &lock, const fraction_timespec &relative_time, const bool monotonic=true) noexcept
wait_for causes the current thread to block until the condition variable is notified,...
uint64_t getWallClockSeconds() noexcept
Returns current wall-clock system time of day in seconds since Unix Epoch 00:00:00 UTC on 1 January 1...
Definition: basic_types.cpp:71
void INFO_PRINT(const char *format,...) noexcept
Use for unconditional informal messages, prefix '[elapsed_time] Info: '.
Definition: debug.cpp:248
std::cv_status wait_until(std::condition_variable &cv, std::unique_lock< std::mutex > &lock, const fraction_timespec &absolute_time, const bool monotonic=true) noexcept
wait_until causes the current thread to block until the condition variable is notified,...
bool sleep_until(const fraction_timespec &absolute_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_until causes the current thread to block until the specific time is reached.
bool sleep(const fraction_timespec &relative_time, const bool ignore_irq=true) noexcept
sleep using high precision monotonic timer, useful for one-shot delays (only).
bool milli_sleep(uint64_t td_ms, const bool ignore_irq=true) noexcept
millisecond sleep using high precision monotonic timer, useful for one-shot delays (only).
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:64
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
int64_t tv_nsec
Nanoseconds component with its absolute value in range [0..1'000'000'000[ or [0..1'000'000'000),...
int64_t tv_sec
Seconds component, with its absolute value in range [0..inf[ or [0..inf), sharing same sign with tv_n...
std::string to_iso8601_string() const noexcept
Convenience string conversion interpreted since Unix Epoch in UTC to ISO 8601 YYYY-mm-ddTHH:MM:SS....
Definition: basic_types.cpp:81
Support aligned memory transfer from and to potentially unaligned memory.
A 128-bit packed uint8_t data array.
Definition: int_types.hpp:114
uint8_t data[16]
Definition: int_types.hpp:114