utils.hpp (3793B)
1 // Copyright (c) 2020 Morel BĂ©renger 2 // 3 // This software is provided 'as-is', without any express or implied 4 // warranty. In no event will the authors be held liable for any damages 5 // arising from the use of this software. 6 // 7 // Permission is granted to anyone to use this software for any purpose, 8 // including commercial applications, and to alter it and redistribute it 9 // freely, subject to the following restrictions: 10 // 11 // 1. The origin of this software must not be misrepresented; you must not 12 // claim that you wrote the original software. If you use this software 13 // in a product, an acknowledgment in the product documentation would be 14 // appreciated but is not required. 15 // 2. Altered source versions must be plainly marked as such, and must not be 16 // misrepresented as being the original software. 17 // 3. This notice may not be removed or altered from any source distribution. 18 19 // This files contains various utilities and macros, some 20 // useful, some useless, some harmful. 21 22 #ifndef UTILS_HPP 23 #define UTILS_HPP 24 25 //TODO I wish this could be avoided, but FILE* is used there. 26 #include <stdio.h> 27 28 #define xstr(s) str(s) 29 #define str(s) #s 30 #define HEADER_LOG __FILE__ "[" xstr(__LINE__) "]" 31 32 #ifndef NDEBUG 33 //abort-like macro, but more flexible 34 #define BUG_CHECK( cond, err ) \ 35 do \ 36 { \ 37 if( cond ) \ 38 { \ 39 fputs( HEADER_LOG ": " #err " caused by " #cond, stderr ); \ 40 abort(); \ 41 } \ 42 } while( 0 ) 43 #else 44 #define BUG_CHECK( cond, err ) if( cond ) return err 45 #endif 46 47 //display a system error 48 #define syserr( str ) \ 49 do { \ 50 fputs( HEADER_LOG ": ", stderr ); \ 51 fputs( strerror( errno ), stderr ); \ 52 fputs( ": " str "\n", stderr ); \ 53 } while( 0 ) 54 55 // C++ malloc, because casting from malloc is annoying and 56 // new does not just allocates (it constructs, too). 57 #define ALLOC( type ) static_cast<type*>( malloc( sizeof( type ) ) ) 58 // tired of looooong lines of code because casting and 59 // dereferencing? This saves 6 out of 11 characters per use. 60 #define REDEF( type, dst, src ) type& dst = *static_cast<type*>( src ) 61 62 //simply check if an array is nullptr or starts with a value considered invalid 63 template <typename T, T INVALID=T()> 64 inline bool empty_array( T* arr ) 65 { 66 return !arr || *arr == INVALID; 67 } 68 69 //like fputs, but when character is blank, prints the C escape instead 70 //returns 0 on success, INT_MAX on error 71 int esc_fputs( const char *s, FILE *stream ); 72 73 // prints a string into stdin for further reading. Might not 74 // be null-terminated. 75 inline size_t ungets( char const* const str, size_t str_sz ); 76 77 // search for a specific character, if not preceded by an escape one. 78 // return the distance, or end - start if not found 79 inline uint16_t find_unescaped( int ch, int esc_ch, char const* start, char const* end ) 80 { 81 uint16_t ret = 0; 82 for( ; start != end && *start != ch; ++start, ++ret ) 83 { 84 if( *start == esc_ch ) 85 { 86 ++start; 87 ++ret; 88 } 89 } 90 return ret; 91 } 92 93 // returns the size in characters of terminal fd in w and h. 94 // returns true on error. 95 bool term_ch_size( uint16_t *w, uint16_t *h, int fd ); 96 97 // print [txt,end) on target, indenting it level times. 98 // When a line is wider than max_width, try to break at last isblank(3). 99 // returns true on error. 100 // note: 101 bool indent_txt( char const* txt, char const* end, uint8_t level, uint16_t max_width, uint8_t tab_width, FILE* target ); 102 103 #endif