1 // =====================================================================
2 //
3 // util.cxx
4 //
5 // Author: Stelios Buonanos, M0GLD, Dave Freese, W1HKJ
6 // Copyright: 2010
7 //
8 // This file is part of FLCLUSTER.
9 //
10 // This is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 //
23 // =====================================================================
24
25 #include <string.h>
26 #include <time.h>
27
28 #include "config.h"
29 #include "util.h"
30 #ifdef __MINGW32__
31 # include "compat.h"
32 #endif
33
34 /* Return the smallest power of 2 not less than n */
ceil2(uint32_t n)35 uint32_t ceil2(uint32_t n)
36 {
37 --n;
38 n |= n >> 1;
39 n |= n >> 2;
40 n |= n >> 4;
41 n |= n >> 8;
42 n |= n >> 16;
43 return n + 1;
44 }
45
46 /* Return the largest power of 2 not greater than n */
floor2(uint32_t n)47 uint32_t floor2(uint32_t n)
48 {
49 n |= n >> 1;
50 n |= n >> 2;
51 n |= n >> 4;
52 n |= n >> 8;
53 n |= n >> 16;
54 return n - (n >> 1);
55 }
56
57 #include <stdlib.h>
ver2int(const char * version)58 unsigned long ver2int(const char* version)
59 {
60 unsigned long v;
61 char* p;
62
63 v = (unsigned long)(strtod(version, &p) * 1e7 + 0.5);
64 while (*p)
65 v += *p++;
66
67 return v;
68 }
69
70 #if !HAVE_STRCASESTR
71 # include <ctype.h>
72 // from git 1.6.1.2 compat/strcasestr.c
strcasestr(const char * haystack,const char * needle)73 char *strcasestr(const char *haystack, const char *needle)
74 {
75 int nlen = strlen(needle);
76 int hlen = strlen(haystack) - nlen + 1;
77 int i;
78
79 for (i = 0; i < hlen; i++) {
80 int j;
81 for (j = 0; j < nlen; j++) {
82 unsigned char c1 = haystack[i+j];
83 unsigned char c2 = needle[j];
84 if (toupper(c1) != toupper(c2))
85 goto next;
86 }
87 return (char *) haystack + i;
88 next: ;
89 }
90 return NULL;
91 }
92 #endif // !HAVE_STRCASESTR
93
94 #if !HAVE_STRLCPY
95 // from git 1.6.1.2 compat/strcasestr.c
strlcpy(char * dest,const char * src,size_t size)96 size_t strlcpy(char *dest, const char *src, size_t size)
97 {
98 size_t ret = strlen(src);
99
100 if (size) {
101 size_t len = (ret >= size) ? size - 1 : ret;
102 memcpy(dest, src, len);
103 dest[len] = '\0';
104 }
105 return ret;
106 }
107 #endif // !HAVE_STRLCPY
108
109 #ifdef __WIN32__
set_cloexec(int fd,unsigned char v)110 int set_cloexec(int fd, unsigned char v) { return 0; }
111 #else
112 # include <unistd.h>
113 # include <fcntl.h>
set_cloexec(int fd,unsigned char v)114 int set_cloexec(int fd, unsigned char v)
115 {
116 int f = fcntl(fd, F_GETFD);
117 return f == -1 ? f : fcntl(fd, F_SETFD, (v ? f | FD_CLOEXEC : f & ~FD_CLOEXEC));
118 }
119 #endif // __WIN32__
120
121
set_nonblock(int fd,unsigned char v)122 int set_nonblock(int fd, unsigned char v)
123 {
124 #ifndef __WIN32__
125 int f = fcntl(fd, F_GETFL);
126 return f == -1 ? f : fcntl(fd, F_SETFL, (v ? f | O_NONBLOCK : f & ~O_NONBLOCK));
127 #else // __WIN32__
128 u_long v_ = (u_long)v;
129 errno = 0;
130 if (ioctlsocket(fd, FIONBIO, &v_) == SOCKET_ERROR) {
131 errno = WSAGetLastError();
132 return -1;
133 }
134 else
135 return 0;
136 #endif // __WIN32__
137 }
138
139 #ifndef __WIN32__
140 # include <sys/types.h>
141 # include <sys/socket.h>
142 # include <netinet/in.h>
143 # include <netinet/tcp.h>
144 #endif
set_nodelay(int fd,unsigned char v)145 int set_nodelay(int fd, unsigned char v)
146 {
147 int val = v;
148 return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&val, sizeof(val));
149 }
150
151
152 #ifdef __WIN32__
153 # include <ws2tcpip.h>
154 #endif
155
get_bufsize(int fd,int dir,int * len)156 int get_bufsize(int fd, int dir, int* len)
157 {
158 socklen_t optlen = sizeof(*len);
159 return getsockopt(fd, SOL_SOCKET, (dir == 0 ? SO_RCVBUF : SO_SNDBUF),
160 (char*)len, &optlen);
161 }
set_bufsize(int fd,int dir,int len)162 int set_bufsize(int fd, int dir, int len)
163 {
164 return setsockopt(fd, SOL_SOCKET, (dir == 0 ? SO_RCVBUF : SO_SNDBUF),
165 (const char*)&len, sizeof(len));
166 }
167
168 #ifndef __WIN32__
169 #include <pthread.h>
170 #include <signal.h>
171 #ifndef NSIG
172 # define NSIG 64
173 #endif
174 static size_t nsig = 0;
175 static struct sigaction* sigact = 0;
176 static pthread_mutex_t sigmutex = PTHREAD_MUTEX_INITIALIZER;
177 #endif
178
save_signals(void)179 void save_signals(void)
180 {
181 #ifndef __WIN32__
182 pthread_mutex_lock(&sigmutex);
183 if (!sigact)
184 sigact = new struct sigaction[NSIG];
185 for (nsig = 1; nsig <= NSIG; nsig++)
186 if (sigaction(nsig, NULL, &sigact[nsig-1]) == -1)
187 break;
188 pthread_mutex_unlock(&sigmutex);
189 #endif
190 }
191
restore_signals(void)192 void restore_signals(void)
193 {
194 #ifndef __WIN32__
195 pthread_mutex_lock(&sigmutex);
196 for (size_t i = 1; i <= nsig; i++)
197 sigaction(i, &sigact[i-1], NULL);
198 delete [] sigact;
199 sigact = 0;
200 nsig = 0;
201 pthread_mutex_unlock(&sigmutex);
202 #endif
203 }
204
205
simple_hash_data(const unsigned char * buf,size_t len,uint32_t code)206 uint32_t simple_hash_data(const unsigned char* buf, size_t len, uint32_t code)
207 {
208 for (size_t i = 0; i < len; i++)
209 code = ((code << 4) | (code >> (32 - 4))) ^ (uint32_t)buf[i];
210
211 return code;
212 }
simple_hash_str(const unsigned char * str,uint32_t code)213 uint32_t simple_hash_str(const unsigned char* str, uint32_t code)
214 {
215 while (*str)
216 code = ((code << 4) | (code >> (32 - 4))) ^ (uint32_t)*str++;
217 return code;
218 }
219
220 #include <vector>
221 #include <climits>
222
223 static const char hexsym[] = "0123456789ABCDEF";
224 static std::vector<char>* hexbuf;
str2hex(const unsigned char * str,size_t len)225 const char* str2hex(const unsigned char* str, size_t len)
226 {
227 if (unlikely(len == 0))
228 return "";
229 if (unlikely(!hexbuf)) {
230 hexbuf = new std::vector<char>;
231 hexbuf->reserve(192);
232 }
233 if (unlikely(hexbuf->size() < len * 3))
234 hexbuf->resize(len * 3);
235
236 char* p = &(*hexbuf)[0];
237 size_t i;
238 for (i = 0; i < len; i++) {
239 *p++ = hexsym[str[i] >> 4];
240 *p++ = hexsym[str[i] & 0xF];
241 *p++ = ' ';
242 }
243 *(p - 1) = '\0';
244
245 return &(*hexbuf)[0];
246 }
247
str2hex(const char * str,size_t len)248 const char* str2hex(const char* str, size_t len)
249 {
250 return str2hex((const unsigned char*)str, len ? len : strlen(str));
251 }
252
253 static std::vector<char>* binbuf;
uint2bin(unsigned u,size_t len)254 const char* uint2bin(unsigned u, size_t len)
255 {
256 if (unlikely(len == 0))
257 len = sizeof(u) * CHAR_BIT;
258
259 if (unlikely(!binbuf)) {
260 binbuf = new std::vector<char>;
261 binbuf->reserve(sizeof(u) * CHAR_BIT);
262 }
263 if (unlikely(binbuf->size() < len + 1))
264 binbuf->resize(len + 1);
265
266 for (size_t i = 0; i < len; i++) {
267 (*binbuf)[len - i - 1] = '0' + (u & 1);
268 u >>= 1;
269 }
270 (*binbuf)[len] = '\0';
271
272 return &(*binbuf)[0];
273 }
274
MilliSleep(long msecs)275 void MilliSleep(long msecs)
276 {
277 #ifndef __WIN32__
278 struct timespec tv;
279 tv.tv_sec = msecs / 1000;
280 tv.tv_nsec = (msecs - tv.tv_sec * 1000) * 1000000L;
281 nanosleep(&tv, NULL);
282 #else
283 Sleep(msecs);
284 #endif
285
286 }
287
288 //======================================================================
289
ucase(std::string & s)290 void ucase(std::string &s)
291 {
292 for (size_t n = 0; n < s.length(); n++) s[n] = toupper(s[n]);
293 }
294
strip_spaces(std::string & s)295 void strip_spaces(std::string &s)
296 {
297 while (!s.empty() && s[0] == ' ') s.erase(0,1);
298 while (!s.empty() && s[s.length() - 1] == ' ') s.erase(s.length() - 1, 1);
299 }
300
strip_leading_zeros(std::string & s)301 void strip_leading_zeros(std::string &s)
302 {
303 while(!s.empty() && s[0] == '0') s.erase(0,1);
304 }
305
strip_lfs(std::string & s)306 void strip_lfs(std::string &s)
307 {
308 while (!s.empty() && s[0] == '\n') s.erase(0,1);
309 while (!s.empty() && s[s.length() - 1] == '\n') s.erase(s.length() - 1, 1);
310 }
311
wordwrap(std::string & s,int cnt)312 std::string wordwrap(std::string &s, int cnt)
313 {
314 static std::string nustr;
315 nustr.clear();
316 int cntr = 1;
317 char c;
318 for (size_t n = 0; n < s.length(); n++) {
319 c = s[n];
320 if (c == '\n') {nustr += c; cntr = 1; }
321 else if (c == ' ' && cntr >= cnt) {
322 nustr += '\n';
323 cntr = 1;
324 }
325 else { nustr += c; cntr++; }
326 }
327 return nustr;
328 }
329
330 #ifndef HAVE_STRNLEN
331
strnlen(const char * cPtr,int limit)332 int strnlen(const char *cPtr, int limit)
333 {
334 int count = 0;
335 if(!cPtr || limit < 1) return 0;
336 while((limit-- > 0) && *cPtr++) count++;
337 return count;
338 }
339
340 #endif
341