Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003-2023, John Wiegley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of New Artisans LLC nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
44#pragma once
45
46#include <boost/uuid/detail/sha1.hpp>
47#include <ledger.hh>
48
49#define TIMERS_ON 1
50
55
56namespace ledger {
57 using namespace boost;
58
59 typedef std::string string;
60 typedef std::list<string> strings_list;
61
62 typedef posix_time::ptime ptime;
63 typedef ptime::time_duration_type time_duration;
64 typedef gregorian::date date;
65 typedef gregorian::date_duration date_duration;
66 typedef posix_time::seconds seconds;
67
68 typedef boost::filesystem::path path;
69 typedef boost::filesystem::ifstream ifstream;
70 typedef boost::filesystem::ofstream ofstream;
71 typedef boost::filesystem::filesystem_error filesystem_error;
72}
73
80
81#ifdef assert
82#undef assert
83#endif
84
85#if !NO_ASSERTS
86
87namespace ledger {
88 void debug_assert(const string& reason, const string& func,
89 const string& file, std::size_t line);
90}
91
92#define assert(x) \
93 ((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \
94 __FILE__, __LINE__))
95
96#else // !NO_ASSERTS
97
98#define assert(x) ((void)(x))
99
100#endif // !NO_ASSERTS
101
108
109#if VERIFY_ON
110
111namespace ledger {
112
113extern bool verify_enabled;
114
115#define VERIFY(x) if (ledger::verify_enabled) { assert(x); }
116#define DO_VERIFY() ledger::verify_enabled
117
120
121std::size_t current_memory_size();
122std::size_t current_objects_size();
123
124void trace_ctor_func(void * ptr, const char * cls_name, const char * args,
125 std::size_t cls_size);
126void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size);
127
128#define TRACE_CTOR(cls, args) \
129 (DO_VERIFY() ? \
130 ledger::trace_ctor_func(this, #cls, args, sizeof(cls)) : ((void)0))
131#define TRACE_DTOR(cls) \
132 (DO_VERIFY() ? \
133 ledger::trace_dtor_func(this, #cls, sizeof(cls)) : ((void)0))
134
135void report_memory(std::ostream& out, bool report_all = false);
136
137} // namespace ledger
138
139#else // ! VERIFY_ON
140
141#define VERIFY(x)
142#define DO_VERIFY() false
143#define TRACE_CTOR(cls, args)
144#define TRACE_DTOR(cls)
145
146#endif // VERIFY_ON
147
148#define IF_VERIFY() if (DO_VERIFY())
149
161
162namespace ledger {
163
164extern string empty_string;
165
167
168inline string to_string(long num) {
169 std::ostringstream buf;
170 buf << num;
171 return buf.str();
172}
173
174inline string to_string(std::size_t num) {
175 std::ostringstream buf;
176 buf << num;
177 return buf.str();
178}
179
180inline string lowered(const string& str) {
181 string tmp(str);
182 to_lower(tmp);
183 return tmp;
184}
185
186inline string operator+(const char * left, const string& right) {
187 return string(left) + right;
188}
189
190} // namespace ledger
191
198
199#if LOGGING_ON
200
201namespace ledger {
202
203enum log_level_t {
204 LOG_OFF = 0,
205 LOG_CRIT,
206 LOG_FATAL,
208 LOG_ERROR,
210 LOG_WARN,
211 LOG_INFO,
213 LOG_DEBUG,
214 LOG_TRACE,
215 LOG_ALL
216};
217
219extern std::ostream * _log_stream;
220extern std::ostringstream _log_buffer;
221
223
224#define LOGGER(cat) \
225 static const char * const _this_category = cat
226
227#if TRACING_ON
228
230
231#define SHOW_TRACE(lvl) \
232 (ledger::_log_level >= ledger::LOG_TRACE && lvl <= ledger::_trace_level)
233#define TRACE(lvl, msg) \
234 (SHOW_TRACE(lvl) ? \
235 ((ledger::_log_buffer << msg), \
236 ledger::logger_func(ledger::LOG_TRACE)) : (void)0)
237
238#else // TRACING_ON
239
240#define SHOW_TRACE(lvl) false
241#define TRACE(lvl, msg)
242
243#endif // TRACING_ON
244
245#if DEBUG_ON
246
248#if HAVE_BOOST_REGEX_UNICODE
250#else
252#endif
253
254inline bool category_matches(const char * cat) {
255 if (_log_category) {
256 if (! _log_category_re) {
258#if HAVE_BOOST_REGEX_UNICODE
259 boost::make_u32regex(_log_category->c_str(),
260 boost::regex::perl | boost::regex::icase);
261#else
262 boost::regex(_log_category->c_str(),
263 boost::regex::perl | boost::regex::icase);
264#endif
265 }
266#if HAVE_BOOST_REGEX_UNICODE
267 return boost::u32regex_search(cat, *_log_category_re);
268#else
269 return boost::regex_search(cat, *_log_category_re);
270#endif
271 }
272 return false;
273}
274
275#define SHOW_DEBUG(cat) \
276 (ledger::_log_level >= ledger::LOG_DEBUG && ledger::category_matches(cat))
277#define SHOW_DEBUG_() SHOW_DEBUG(_this_category)
278
279#define DEBUG(cat, msg) \
280 (SHOW_DEBUG(cat) ? \
281 ((ledger::_log_buffer << msg), \
282 ledger::logger_func(ledger::LOG_DEBUG)) : (void)0)
283#define DEBUG_(msg) DEBUG(_this_category, msg)
284
285#else // DEBUG_ON
286
287#define SHOW_DEBUG(cat) false
288#define SHOW_DEBUG_() false
289#define DEBUG(cat, msg)
290#define DEBUG_(msg)
291
292#endif // DEBUG_ON
293
294#define LOG_MACRO(level, msg) \
295 (ledger::_log_level >= level ? \
296 ((ledger::_log_buffer << msg), ledger::logger_func(level)) : (void)0)
297
298#define SHOW_INFO() (ledger::_log_level >= ledger::LOG_INFO)
299#define SHOW_WARN() (ledger::_log_level >= ledger::LOG_WARN)
300#define SHOW_ERROR() (ledger::_log_level >= ledger::LOG_ERROR)
301#define SHOW_FATAL() (ledger::_log_level >= ledger::LOG_FATAL)
302#define SHOW_CRITICAL() (ledger::_log_level >= ledger::LOG_CRIT)
303
304#define INFO(msg) LOG_MACRO(ledger::LOG_INFO, msg)
305#define WARN(msg) LOG_MACRO(ledger::LOG_WARN, msg)
306#define ERROR(msg) LOG_MACRO(ledger::LOG_ERROR, msg)
307#define FATAL(msg) LOG_MACRO(ledger::LOG_FATAL, msg)
308#define CRITICAL(msg) LOG_MACRO(ledger::LOG_CRIT, msg)
309#define EXCEPTION(msg) LOG_MACRO(ledger::LOG_EXCEPT, msg)
310
311} // namespace ledger
312
313#else // ! LOGGING_ON
314
315#define LOGGER(cat)
316
317#define SHOW_TRACE(lvl) false
318#define SHOW_DEBUG(cat) false
319#define SHOW_DEBUG_() false
320#define SHOW_INFO() false
321#define SHOW_WARN() false
322#define SHOW_ERROR() false
323#define SHOW_FATAL() false
324#define SHOW_CRITICAL() false
325
326#define TRACE(lvl, msg)
327#define DEBUG(cat, msg)
328#define DEBUG_(msg)
329#define INFO(msg)
330#define WARN(msg)
331#define ERROR(msg)
332#define FATAL(msg)
333#define CRITICAL(msg)
334
335#endif // LOGGING_ON
336
337#define IF_TRACE(lvl) if (SHOW_TRACE(lvl))
338#define IF_DEBUG(cat) if (SHOW_DEBUG(cat))
339#define IF_DEBUG_() if (SHOW_DEBUG_())
340#define IF_INFO() if (SHOW_INFO())
341#define IF_WARN() if (SHOW_WARN())
342#define IF_ERROR() if (SHOW_ERROR())
343#define IF_FATAL() if (SHOW_FATAL())
344#define IF_CRITICAL() if (SHOW_CRITICAL())
345
353
354#if LOGGING_ON && TIMERS_ON
355
356namespace ledger {
357
358void start_timer(const char * name, log_level_t lvl);
359void stop_timer(const char * name);
360void finish_timer(const char * name);
361
362#if TRACING_ON
363#define TRACE_START(name, lvl, msg) \
364 (SHOW_TRACE(lvl) ? \
365 ((ledger::_log_buffer << msg), \
366 ledger::start_timer(#name, ledger::LOG_TRACE)) : ((void)0))
367#define TRACE_STOP(name, lvl) \
368 (SHOW_TRACE(lvl) ? ledger::stop_timer(#name) : ((void)0))
369#define TRACE_FINISH(name, lvl) \
370 (SHOW_TRACE(lvl) ? ledger::finish_timer(#name) : ((void)0))
371#else
372#define TRACE_START(name, lvl, msg)
373#define TRACE_STOP(name, lvl)
374#define TRACE_FINISH(name, lvl)
375#endif
376
377#if DEBUG_ON
378#define DEBUG_START(name, cat, msg) \
379 (SHOW_DEBUG(cat) ? \
380 ((ledger::_log_buffer << msg), \
381 ledger::start_timer(#name, ledger::LOG_DEBUG)) : ((void)0))
382#define DEBUG_START_(name, msg) \
383 DEBUG_START_(name, _this_category, msg)
384#define DEBUG_STOP(name, cat) \
385 (SHOW_DEBUG(cat) ? ledger::stop_timer(#name) : ((void)0))
386#define DEBUG_STOP_(name) \
387 DEBUG_STOP_(name, _this_category)
388#define DEBUG_FINISH(name, cat) \
389 (SHOW_DEBUG(cat) ? ledger::finish_timer(#name) : ((void)0))
390#define DEBUG_FINISH_(name) \
391 DEBUG_FINISH_(name, _this_category)
392#else
393#define DEBUG_START(name, cat, msg)
394#define DEBUG_START_(name, msg)
395#define DEBUG_STOP(name)
396#define DEBUG_FINISH(name)
397#endif
398
399#define INFO_START(name, msg) \
400 (SHOW_INFO() ? \
401 ((ledger::_log_buffer << msg), \
402 ledger::start_timer(#name, ledger::LOG_INFO)) : ((void)0))
403#define INFO_STOP(name) \
404 (SHOW_INFO() ? stop_timer(#name) : ((void)0))
405#define INFO_FINISH(name) \
406 (SHOW_INFO() ? finish_timer(#name) : ((void)0))
407
408} // namespace ledger
409
410#else // ! (LOGGING_ON && TIMERS_ON)
411
412#define TRACE_START(lvl, msg, name)
413#define TRACE_STOP(name, lvl)
414#define TRACE_FINISH(name, lvl)
415
416#define DEBUG_START(name, msg)
417#define DEBUG_START_(name, cat, msg)
418#define DEBUG_STOP(name)
419#define DEBUG_FINISH(name)
420
421#define INFO_START(name, msg)
422#define INFO_STOP(name)
423#define INFO_FINISH(name)
424
425#endif // TIMERS_ON
426
429/*
430 * These files define the other internal facilities.
431 */
432
433#include "error.h"
434
440
442
443void sigint_handler(int sig);
444void sigpipe_handler(int sig);
445
446inline void check_for_signal() {
447 switch (caught_signal) {
448 case NONE_CAUGHT:
449 break;
450 case INTERRUPTED:
451 throw std::runtime_error(_("Interrupted by user (use Control-D to quit)"));
452 case PIPE_CLOSED:
453 throw std::runtime_error(_("Pipe terminated"));
454 }
455}
456
461
462#define foreach BOOST_FOREACH
463using std::unique_ptr;
464
465namespace ledger {
466
467template <typename T, typename U>
468inline T& downcast(U& object) {
469 return *polymorphic_downcast<T *>(&object);
470}
471
472path resolve_path(const path& pathname);
473
474inline const string& either_or(const string& first,
475 const string& second) {
476 return first.empty() ? second : first;
477}
478
479inline char * skip_ws(char * ptr) {
480 while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
481 ptr++;
482 return ptr;
483}
484
485inline char * trim_ws(char * ptr) {
486 std::size_t len = std::strlen(ptr);
487 int i = int(len) - 1;
488 while (i >= 0 && (ptr[i] == ' ' || ptr[i] == '\t' || ptr[i] == '\n'))
489 ptr[i--] = '\0';
490 return skip_ws(ptr);
491}
492
493inline char * next_element(char * buf, bool variable = false) {
494 for (char * p = buf; *p; p++) {
495 if (! (*p == ' ' || *p == '\t'))
496 continue;
497
498 if (! variable) {
499 *p = '\0';
500 return skip_ws(p + 1);
501 }
502 else if (*p == '\t') {
503 *p = '\0';
504 return skip_ws(p + 1);
505 }
506 else if (*(p + 1) == ' ') {
507 *p = '\0';
508 return skip_ws(p + 2);
509 }
510 }
511 return NULL;
512}
513
514inline int peek_next_nonws(std::istream& in) {
515 int c = in.peek();
516 while (in.good() && ! in.eof() && std::isspace(c)) {
517 in.get();
518 c = in.peek();
519 }
520 return c;
521}
522
523#define READ_INTO(str, targ, size, var, cond) { \
524 char * _p = targ; \
525 var = str.peek(); \
526 while (str.good() && ! str.eof() && var != '\n' && \
527 (cond) && _p - targ < size) { \
528 var = str.get(); \
529 if (str.eof()) \
530 break; \
531 if (var == '\\') { \
532 var = str.get(); \
533 if (in.eof()) \
534 break; \
535 switch (var) { \
536 case 'b': var = '\b'; break; \
537 case 'f': var = '\f'; break; \
538 case 'n': var = '\n'; break; \
539 case 'r': var = '\r'; break; \
540 case 't': var = '\t'; break; \
541 case 'v': var = '\v'; break; \
542 default: break; \
543 } \
544 } \
545 *_p++ = var; \
546 var = str.peek(); \
547 } \
548 *_p = '\0'; \
549 }
550
551#define READ_INTO_(str, targ, size, var, idx, cond) { \
552 char * _p = targ; \
553 var = str.peek(); \
554 while (str.good() && ! str.eof() && var != '\n' && \
555 (cond) && _p - targ < size) { \
556 var = str.get(); \
557 if (str.eof()) \
558 break; \
559 idx++; \
560 if (var == '\\') { \
561 var = str.get(); \
562 if (in.eof()) \
563 break; \
564 switch (var) { \
565 case 'b': var = '\b'; break; \
566 case 'f': var = '\f'; break; \
567 case 'n': var = '\n'; break; \
568 case 'r': var = '\r'; break; \
569 case 't': var = '\t'; break; \
570 case 'v': var = '\v'; break; \
571 default: break; \
572 } \
573 idx++; \
574 } \
575 *_p++ = var; \
576 var = str.peek(); \
577 } \
578 *_p = '\0'; \
579 }
580
581inline string digest_to_hex(
582 const boost::uuids::detail::sha1::digest_type& message_digest,
583 size_t len = sizeof(boost::uuids::detail::sha1::digest_type) * 2
584) {
585 std::ostringstream buf;
586 buf.setf(std::ios_base::hex, std::ios_base::basefield);
587 buf.fill('0');
588
589 // sha1::digest_type is an array type and may change between Boost versions
590 const size_t count = std::min(
591 sizeof(message_digest) / sizeof(message_digest[0]),
592 (len - 1) / (sizeof(message_digest[0]) * 2) + 1
593 );
594 for(size_t i = 0; i < count; i++) {
595 buf.width(sizeof(message_digest[i]) * 2);
596 buf << (unsigned int)message_digest[i];
597 }
598 string hex = buf.str();
599 hex.resize(len, '0'); // in case a partial element is requested
600 return hex;
601}
602
603inline string sha1sum(
604 const string& str,
605 size_t len = sizeof(boost::uuids::detail::sha1::digest_type) * 2
606) {
607 static boost::uuids::detail::sha1 sha;
608 boost::uuids::detail::sha1::digest_type message_digest;
609
610 sha.reset();
611 sha.process_bytes(str.c_str(), str.length());
612 sha.get_digest(message_digest);
613 return digest_to_hex(message_digest, len);
614}
615
616extern const string version;
617
623
624} // namespace ledger
625
void sigint_handler(int sig)
void sigpipe_handler(int sig)
caught_signal_t
Definition utils.h:435
@ INTERRUPTED
Definition utils.h:437
@ PIPE_CLOSED
Definition utils.h:438
@ NONE_CAUGHT
Definition utils.h:436
caught_signal_t caught_signal
void check_for_signal()
Definition utils.h:446
boost::filesystem::ifstream ifstream
Definition utils.h:69
boost::filesystem::ofstream ofstream
Definition utils.h:70
string operator+(const char *left, const string &right)
Definition utils.h:186
string lowered(const string &str)
Definition utils.h:180
gregorian::date date
Definition utils.h:64
const string & either_or(const string &first, const string &second)
Definition utils.h:474
ptime::time_duration_type time_duration
Definition utils.h:63
string empty_string
boost::filesystem::filesystem_error filesystem_error
Definition utils.h:71
gregorian::date_duration date_duration
Definition utils.h:65
string sha1sum(const string &str, size_t len=sizeof(boost::uuids::detail::sha1::digest_type) *2)
Definition utils.h:603
hash_type_t
Definition utils.h:618
@ HASH_SHA512_Half
Definition utils.h:621
@ NO_HASHES
Definition utils.h:619
@ HASH_SHA512
Definition utils.h:620
posix_time::ptime ptime
Definition utils.h:62
char * next_element(char *buf, bool variable=false)
Definition utils.h:493
string to_string(long num)
Definition utils.h:168
boost::filesystem::path path
Definition utils.h:68
char * trim_ws(char *ptr)
Definition utils.h:485
int peek_next_nonws(std::istream &in)
Definition utils.h:514
void debug_assert(const string &reason, const string &func, const string &file, std::size_t line)
std::string string
Definition utils.h:59
std::list< string > strings_list
Definition utils.h:60
posix_time::seconds seconds
Definition utils.h:66
string digest_to_hex(const boost::uuids::detail::sha1::digest_type &message_digest, size_t len=sizeof(boost::uuids::detail::sha1::digest_type) *2)
Definition utils.h:581
path resolve_path(const path &pathname)
T & downcast(U &object)
Definition utils.h:468
const string version
strings_list split_arguments(const char *line)
char * skip_ws(char *ptr)
Definition utils.h:479