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