1 #ifndef BASE_H
2 #define BASE_H
3 
4 #include "debug.h"
5 #include <stddef.h>
6 
7 #ifndef __GNUC__
8 #define __attribute__(a)
9 #endif
10 
11 /*** Essential Arithmetic Functions *******************************************/
12 
13 /*
14  * Decimal digits required to write the largest element of type:
15  * bits(Type) * (2.5 = 5/2 ~ (8 * ln(2) / ln(10)))
16  */
17 #define DECIMAL_DIGIT_COUNT(Type) ((sizeof(Type) * 5 + 1) / 2)
18 
19 template <class T>
min(T a,T b)20 inline T min(T a, T b) {
21     return (a < b ? a : b);
22 }
23 
24 template <class T>
min(T a,T b,T c)25 inline T min(T a, T b, T c) {
26     return (a < b ? a < c ? a : c : b < c ? b : c);
27 }
28 
29 template <class T>
max(T a,T b)30 inline T max(T a, T b) {
31     return (a < b ? b : a);
32 }
33 
34 template <class T>
max(T a,T b,T c)35 inline T max(T a, T b, T c) {
36     return (a < b ? b < c ? c : b : a < c ? c : a);
37 }
38 
39 template <class T>
swap(T & a,T & b)40 inline void swap(T& a, T& b) {
41     T t(a); a = b; b = t;
42 }
43 
44 template <class T>
clamp(T value,T minimum,T maximum)45 inline T clamp(T value, T minimum, T maximum) {
46     return max(min(value, maximum), minimum);
47 }
48 
49 template <class T>
inrange(T value,T lower,T upper)50 inline bool inrange(T value, T lower, T upper) {
51     return !(value < lower) && !(upper < value);
52 }
53 
54 template <class T>
abs(T v)55 inline T abs(T v) {
56     return (v < 0 ? -v : v);
57 }
58 
59 // https://en.wikipedia.org/wiki/Elvis_operator
60 template <class T>
Elvis(T a,T b)61 inline T Elvis(T a, T b) {
62     return a ? a : b;
63 }
64 
65 template <class T>
non_zero(T x)66 inline T non_zero(T x) {
67     return Elvis(x, static_cast<T>(1));
68 }
69 
70 template <class L, class R>
71 class pair {
72 public:
73     L left;
74     R right;
pair(const L & l,const R & r)75     pair(const L& l, const R& r) : left(l), right(r) { }
76 };
77 
78 template<typename T>
79 class YRange {
80     T *b, *e;
81 public:
YRange(T * b,size_t n)82     YRange(T* b, size_t n) : b(b), e(b + n) { }
YRange(T * b,int n)83     YRange(T* b, int n) : b(b), e(b + n) { }
YRange(T * b,T * e)84     YRange(T* b, T* e) : b(b), e(e) { }
begin()85     const T* begin() const { return b; }
end()86     const T* end() const { return e; }
87 };
88 
89 class tokens {
90     const char* sep;
91     char* save, *tok;
92 public:
93     tokens(char* data, const char* sep);
94     operator char*() const { return tok; }
token()95     char* token() const { return tok; }
96     char* operator++();
97 };
98 
99 /*** String Functions *********************************************************/
100 
101 /* Prefer this as a safer alternative over strcpy. Return strlen(from). */
102 #if !defined(HAVE_STRLCPY) || !HAVE_STRLCPY
103 size_t strlcpy(char *dest, const char *from, size_t dest_size);
104 #endif
105 
106 /* Prefer this over strcat. Return strlen(dest) + strlen(from). */
107 #if !defined(HAVE_STRLCAT) || !HAVE_STRLCAT
108 size_t strlcat(char *dest, const char *from, size_t dest_size);
109 #endif
110 
111 char *newstr(char const *str);
112 char *newstr(char const *str, int len);
113 char *newstr(char const *str, char const *delim);
114 char *cstrJoin(char const *str, ...);
115 
116 char* demangle(const char* str);
117 unsigned long strhash(const char* str);
118 
nonempty(const char * s)119 inline bool nonempty(const char* s) { return s && *s; }
isEmpty(const char * s)120 inline bool isEmpty(const char* s) { return !(s && *s); }
121 
122 #ifndef HAVE_MEMRCHR
123 void* memrchr(const void*, char, size_t);
124 #endif
125 
126 /*** Message Functions ********************************************************/
127 
128 void die(int exitcode, char const *msg, ...) __attribute__((format(printf, 2, 3) ));
129 void warn(char const *msg, ...) __attribute__((format(printf, 1, 2) ));
130 void fail(char const *msg, ...) __attribute__((format(printf, 1, 2) ));
131 void msg(char const *msg, ...) __attribute__((format(printf, 1, 2) ));
132 void tlog(char const *msg, ...) __attribute__((format(printf, 1, 2) ));
133 void precondition(const char *expr, const char *file, int line);
134 
135 /*** User Environment ********************************************************/
136 
137 char* userhome(const char* username);
138 char* dollar_expansion(const char* name);
139 char* tilde_expansion(const char* name);
140 char* path_lookup(const char* name);
141 
142 char* progpath();
143 void show_backtrace(const int limit = 0);
144 
145 #define DEPRECATE(x) \
146     do { \
147     if (x) warn("Deprecated option: " #x); \
148     } while (0)
149 
150 /*** Misc Stuff (clean up!!!) *************************************************/
151 
152 #define ACOUNT(x) (sizeof(x)/sizeof(x[0]))
153 #define BUFNSIZE(x) x, sizeof(x)
154 
155 int strpcmp(char const *str, char const *pfx, char const *delim = "=:");
156 char const * strnxt(const char *str, const char *delim = " \t");
157 const char* errno_string();
158 const char *my_basename(const char *filename);
159 
boolstr(bool bval)160 inline const char* boolstr(bool bval) {
161     return bval ? "true" : "false";
162 }
163 
164 template <class T>
165 inline char const * niceUnit(T & val, char const * const units[],
166                              T const lim = 10240, T const div = 1024) {
167     char const * uname(nullptr);
168 
169     if (units && *units) {
170         uname = *units++;
171         while (val >= lim && *units) {
172             uname = *units++;
173             /* precise rounding errs */
174             val = (val + div / 2) / div;
175         }
176     }
177 
178     return uname;
179 }
180 
181 // be true just once: only the first evaluation
182 #define ONCE    testOnce(__FILE__, __LINE__)
183 
184 bool testOnce(const char* file, const int line);
185 
186 bool little();
187 
188 /*** Bit Operations ***********************************************************/
189 
190 template <class M, class B>
hasbit(M mask,B bits)191 inline bool hasbit(M mask, B bits) {
192     return (mask & static_cast<M>(bits)) != 0;
193 }
194 
195 template <class M, class B>
hasbits(M mask,B bits)196 inline bool hasbits(M mask, B bits) {
197     return (mask & static_cast<M>(bits)) == static_cast<M>(bits);
198 }
199 
200 template <class M, class B>
notbit(M mask,B bits)201 inline bool notbit(M mask, B bits) {
202     return (mask & static_cast<M>(bits)) == 0;
203 }
204 
205 /*
206  * Returns the lowest bit set in mask.
207  */
208 template <class T>
lowbit(T mask)209 inline unsigned lowbit(T mask) {
210 #if defined(CONFIG_X86_ASM) && defined(__i386__) && \
211     defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 208)
212     unsigned bit;
213     asm ("bsf %1,%0" : "=r" (bit) : "r" (mask));
214 #else
215     unsigned bit(0);
216     while (!(mask & ((static_cast<T>(1)) << bit)) && bit < sizeof(mask) * 8) ++bit;
217 #endif
218 
219     return bit;
220 }
221 
222 /*
223  * Returns the highest bit set in mask.
224  */
225 template <class T>
highbit(T mask)226 inline unsigned highbit(T mask) {
227 #if defined(CONFIG_X86_ASM) && defined(__i386__) && \
228     defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 208)
229     unsigned bit;
230     asm ("bsr %1,%0" : "=r" (bit) : "r" (mask));
231 #else
232     unsigned bit(sizeof(mask) * 8 - 1);
233     while (!(mask & ((static_cast<T>(1)) << bit)) && bit > 0) --bit;
234 #endif
235 
236     return bit;
237 }
238 
239 /*** argc/argv processing *****************************************************/
240 
241 extern char const *ApplicationName;
242 
243 bool GetShortArgument(char* &ret, const char *name, char** &argpp, char ** endpp);
244 bool GetLongArgument(char* &ret, const char *name, char** &argpp, char ** endpp);
245 bool GetArgument(char* &ret, const char *sn, const char *ln, char** &arg, char **end);
246 bool is_short_switch(const char *arg, const char *name);
247 bool is_long_switch(const char *arg, const char *name);
248 bool is_switch(const char *arg, const char *short_name, const char *long_name);
249 bool is_copying_switch(const char *arg);
250 bool is_help_switch(const char *arg);
251 bool is_version_switch(const char *arg);
252 void print_copying_exit();
253 void print_help_exit(const char *help);
254 void print_version_exit(const char *version);
255 typedef const char* (*help_text_fun)();
256 void check_help_version(const char *arg, help_text_fun help, const char *version);
257 void check_argv(int argc, char **argv, help_text_fun help, const char *version);
258 
intersection(int s1,int e1,int s2,int e2)259 inline int intersection(int s1, int e1, int s2, int e2) {
260     return max(0, min(e1, e2) - max(s1, s2));
261 }
262 
263 #endif
264 
265 // vim: set sw=4 ts=4 et:
266