Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/utils/gravity_utils.c
1214 views
1
//
2
// gravity_utils.c
3
// gravity
4
//
5
// Created by Marco Bambini on 29/08/14.
6
// Copyright (c) 2014 CreoLabs. All rights reserved.
7
//
8
9
#include <time.h>
10
#include <fcntl.h>
11
#include <ctype.h>
12
#include <string.h>
13
#include <assert.h>
14
#include <unistd.h>
15
#include <sys/stat.h>
16
17
#if defined(__linux)
18
#include <sys/time.h>
19
#endif
20
#if defined(__MACH__)
21
#include <mach/mach_time.h>
22
#endif
23
#if defined(_WIN32)
24
#include <windows.h>
25
#endif
26
27
#include "gravity_utils.h"
28
#include "gravity_memory.h"
29
30
#define SWP(x,y) (x^=y, y^=x, x^=y)
31
32
// MARK: Timer -
33
34
nanotime_t nanotime (void) {
35
nanotime_t value;
36
37
#if defined(_WIN32)
38
static LARGE_INTEGER win_frequency;
39
static BOOL flag = QueryPerformanceFrequency(&s_frequency);
40
LARGE_INTEGER t;
41
42
if (!QueryPerformanceCounter(&t)) return 0;
43
value = (t.QuadPart / win_frequency.QuadPart) * 1000000000;
44
value += (t.QuadPart % win_frequency.QuadPart) * 1000000000 / win_frequency.QuadPart;
45
46
#elif defined(__MACH__)
47
mach_timebase_info_data_t info;
48
kern_return_t r;
49
nanotime_t t;
50
51
t = mach_absolute_time();
52
r = mach_timebase_info(&info);
53
if (r != 0) return 0;
54
value = (t / info.denom) * info.numer;
55
value += (t % info.denom) * info.numer / info.denom;
56
57
#elif defined(__linux)
58
struct timespec ts;
59
int r;
60
61
r = clock_gettime(CLOCK_MONOTONIC, &ts);
62
if (r != 0) return 0;
63
value = ts.tv_sec * (nanotime_t)1000000000 + ts.tv_nsec;
64
65
#else
66
struct timeval tv;
67
int r;
68
69
r = gettimeofday(&tv, 0);
70
if (r != 0) return 0;
71
value = tv.tv_sec * (nanotime_t)1000000000 + tv.tv_usec * 1000;
72
#endif
73
74
return value;
75
}
76
77
double microtime (nanotime_t tstart, nanotime_t tend) {
78
nanotime_t t = tend - tstart;
79
return ((double)t / 1000.0f);
80
}
81
82
double millitime (nanotime_t tstart, nanotime_t tend) {
83
nanotime_t t = tend - tstart;
84
return ((double)t / 1000000.0f);
85
}
86
87
// MARK: - I/O Functions -
88
89
uint64_t file_size (const char *path) {
90
#ifdef WIN32
91
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
92
if (GetFileAttributesExA(path, GetFileExInfoStandard, (void*)&fileInfo) == 0) return -1;
93
return (uint64_t)(((__int64)fileInfo.nFileSizeHigh) << 32 ) + fileInfo.nFileSizeLow;
94
#else
95
struct stat sb;
96
if (stat(path, &sb) > 0) return -1;
97
return (uint64_t)sb.st_size;
98
#endif
99
}
100
101
const char *file_read(const char *path, size_t *len) {
102
int fd = 0;
103
off_t fsize = 0;
104
size_t fsize2 = 0;
105
char *buffer = NULL;
106
107
fsize = (size_t) file_size(path);
108
if (fsize < 0) goto abort_read;
109
110
fd = open(path, O_RDONLY);
111
if (fd < 0) goto abort_read;
112
113
buffer = (char *)mem_alloc((size_t)fsize + 1);
114
if (buffer == NULL) goto abort_read;
115
buffer[fsize] = 0;
116
117
fsize2 = read(fd, buffer, fsize);
118
if (fsize != fsize2) goto abort_read;
119
120
if (len) *len = fsize;
121
close(fd);
122
return (const char *)buffer;
123
124
abort_read:
125
if (buffer) mem_free((void *)buffer);
126
if (fd >= 0) close(fd);
127
return NULL;
128
}
129
130
bool file_exists (const char *path) {
131
#ifdef WIN32
132
BOOL isDirectory;
133
DWORD attributes = GetFileAttributesA(path);
134
135
// special directory case to drive the network path check
136
if (attributes == INVALID_FILE_ATTRIBUTES)
137
isDirectory = (GetLastError() == ERROR_BAD_NETPATH);
138
else
139
isDirectory = (FILE_ATTRIBUTE_DIRECTORY & attributes);
140
141
if (isDirectory) {
142
if (PathIsNetworkPathA(path)) return true;
143
if (PathIsUNCA(path)) return true;
144
}
145
146
if (PathFileExistsA(path) == 1) return true;
147
#else
148
if (access(path, F_OK)==0) return true;
149
#endif
150
151
return false;
152
}
153
154
const char *file_buildpath (const char *filename, const char *dirpath) {
155
// #ifdef WIN32
156
// PathCombineA(result, filename, dirpath);
157
// #else
158
size_t len1 = strlen(filename);
159
size_t len2 = strlen(dirpath);
160
size_t len = len1+len2+2;
161
162
char *full_path = (char *)mem_alloc(len);
163
if (!full_path) return NULL;
164
165
if ((len2) && (dirpath[len2-1] != '/'))
166
snprintf(full_path, len, "%s/%s", dirpath, filename);
167
else
168
snprintf(full_path, len, "%s%s", dirpath, filename);
169
// #endif
170
171
return (const char *)full_path;
172
}
173
174
bool file_write (const char *path, const char *buffer, size_t len) {
175
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // RW for owner, R for group, R for others
176
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
177
if (fd < 0) return false;
178
179
ssize_t nwrite = write(fd, buffer, len);
180
close(fd);
181
182
return (nwrite == len);
183
}
184
185
// MARK: - Directory Functions -
186
187
bool is_directory (const char *path) {
188
#ifdef WIN32
189
DWORD dwAttrs;
190
191
dwAttrs = GetFileAttributesA(path);
192
if (dwAttrs == INVALID_FILE_ATTRIBUTES) return false;
193
if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) return true;
194
#else
195
struct stat buf;
196
197
if (lstat(path, &buf) < 0) return false;
198
if (S_ISDIR(buf.st_mode)) return true;
199
#endif
200
201
return false;
202
}
203
204
DIRREF directory_init (const char *dirpath) {
205
#ifdef WIN32
206
WIN32_FIND_DATA findData;
207
WCHAR path[MAX_PATH];
208
WCHAR dirpathW[MAX_PATH];
209
HANDLE hFind;
210
211
// convert dirpath to dirpathW
212
MultiByteToWideChar(CP_UTF8, 0, dirpath, -1, dirpathW, MAX_PATH);
213
214
// in this way I can be sure that the first file returned (and lost) is .
215
PathCombine(path, dirpathW, _T("*"));
216
217
// if the path points to a symbolic link, the WIN32_FIND_DATA buffer contains
218
// information about the symbolic link, not the target
219
return FindFirstFile(path, &findData);
220
#else
221
return opendir(dirpath);
222
#endif
223
}
224
225
const char *directory_read (DIRREF ref) {
226
if (ref == NULL) return NULL;
227
228
while (1) {
229
#ifdef WIN32
230
WIN32_FIND_DATA findData;
231
if (FindNextFile(ref, &findData) == 0) {
232
FindClose(dref);
233
return NULL;
234
}
235
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
236
if (findData.cFileName == NULL) continue;
237
if (findData.cFileName[0] == '.') continue;
238
return (const char *)findData.cFileName;
239
#else
240
struct dirent *d;
241
if ((d = readdir(ref)) == NULL) {
242
closedir(ref);
243
return NULL;
244
}
245
if (d->d_name[0] == 0) continue;
246
if (d->d_name[0] == '.') continue;
247
return (const char *)d->d_name;
248
#endif
249
}
250
return NULL;
251
}
252
253
// MARK: - String Functions -
254
255
int string_nocasencmp(const char *s1, const char *s2, size_t n) {
256
while(n > 0 && tolower((unsigned char)*s1) == tolower((unsigned char)*s2)) {
257
if(*s1 == '\0') return 0;
258
s1++;
259
s2++;
260
n--;
261
}
262
263
if(n == 0) return 0;
264
return tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
265
}
266
267
int string_casencmp(const char *s1, const char *s2, size_t n) {
268
while(n > 0 && ((unsigned char)*s1) == ((unsigned char)*s2)) {
269
if(*s1 == '\0') return 0;
270
s1++;
271
s2++;
272
n--;
273
}
274
275
if(n == 0) return 0;
276
return ((unsigned char)*s1) - ((unsigned char)*s2);
277
}
278
279
int string_cmp (const char *s1, const char *s2) {
280
if (!s1) return 1;
281
return strcmp(s1, s2);
282
}
283
284
const char *string_dup (const char *s1) {
285
size_t len = (size_t)strlen(s1);
286
char *s = (char *)mem_alloc(len + 1);
287
288
memcpy(s, s1, len);
289
return s;
290
}
291
292
const char *string_ndup (const char *s1, size_t n) {
293
char *s = (char *)mem_alloc(n + 1);
294
memcpy(s, s1, n);
295
return s;
296
}
297
298
char *string_unescape (const char *s1, uint32_t *s1len, char *buffer) {
299
uint32_t len = *s1len;
300
uint32_t orig_len = len;
301
302
for (uint32_t i=0, j=0; i<orig_len; ++i, ++j) {
303
char c = s1[i];
304
if ((c == '\\') && (i+1<orig_len)) {
305
c = s1[i+1];
306
switch (c) {
307
case '"':
308
case '\\':
309
case '\b':
310
case '\f':
311
case '\n':
312
case '\r':
313
case '\t':
314
++i; --len; break;
315
default:
316
c = s1[i]; break;
317
}
318
}
319
buffer[j] = c;
320
}
321
322
*s1len = len;
323
return buffer;
324
}
325
326
// From: http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c
327
void string_reverse (char *p) {
328
char *q = p;
329
while(q && *q) ++q; /* find eos */
330
for(--q; p < q; ++p, --q) SWP(*p, *q);
331
}
332
333
uint32_t string_size (const char *p) {
334
if (!p) return 0;
335
return (uint32_t)strlen(p);
336
}
337
338
// MARK: - UTF-8 Functions -
339
340
/*
341
Based on: https://github.com/Stepets/utf8.lua/blob/master/utf8.lua
342
ABNF from RFC 3629
343
344
UTF8-octets = *( UTF8-char )
345
UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
346
UTF8-1 = %x00-7F
347
UTF8-2 = %xC2-DF UTF8-tail
348
UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
349
%xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
350
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
351
%xF4 %x80-8F 2( UTF8-tail )
352
UTF8-tail = %x80-BF
353
354
*/
355
356
inline uint32_t utf8_charbytes (const char *s, uint32_t i) {
357
unsigned char c = s[i];
358
359
// determine bytes needed for character, based on RFC 3629
360
if ((c > 0) && (c <= 127)) return 1;
361
if ((c >= 194) && (c <= 223)) return 2;
362
if ((c >= 224) && (c <= 239)) return 3;
363
if ((c >= 240) && (c <= 244)) return 4;
364
365
// means error
366
return 0;
367
}
368
369
uint32_t utf8_len (const char *s, uint32_t nbytes) {
370
if (nbytes == 0) nbytes = (uint32_t)strlen(s);
371
372
uint32_t pos = 1;
373
uint32_t len = 0;
374
375
while (pos <= nbytes) {
376
++len;
377
uint32_t n = utf8_charbytes(s, pos);
378
if (n == 0) return 0; // means error
379
pos += n;
380
}
381
382
return len;
383
}
384
385
// From: http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c
386
void utf8_reverse (char *p) {
387
char *q = p;
388
string_reverse(p);
389
390
// now fix bass-ackwards UTF chars.
391
while(q && *q) ++q; // find eos
392
while(p < --q)
393
switch( (*q & 0xF0) >> 4 ) {
394
case 0xF: /* U+010000-U+10FFFF: four bytes. */
395
SWP(*(q-0), *(q-3));
396
SWP(*(q-1), *(q-2));
397
q -= 3;
398
break;
399
case 0xE: /* U+000800-U+00FFFF: three bytes. */
400
SWP(*(q-0), *(q-2));
401
q -= 2;
402
break;
403
case 0xC: /* fall-through */
404
case 0xD: /* U+000080-U+0007FF: two bytes. */
405
SWP(*(q-0), *(q-1));
406
q--;
407
break;
408
}
409
}
410
411
// MARK: - Math -
412
413
// From: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2Float
414
uint32_t power_of2_ceil (uint32_t n) {
415
n--;
416
n |= n >> 1;
417
n |= n >> 2;
418
n |= n >> 4;
419
n |= n >> 8;
420
n |= n >> 16;
421
n++;
422
423
return n;
424
}
425
426
int64_t number_from_hex (const char *s, uint32_t len) {
427
#pragma unused(len)
428
return (int64_t) strtoll(s, NULL, 16);
429
}
430
431
int64_t number_from_oct (const char *s, uint32_t len) {
432
#pragma unused(len)
433
return (int64_t) strtoll(s, NULL, 8);
434
}
435
436
int64_t number_from_bin (const char *s, uint32_t len) {
437
int64_t value = 0;
438
439
for (uint32_t i=0; i<len; ++i) {
440
int c = s[i];
441
value = (value << 1) + (c - '0');
442
}
443
return value;
444
}
445
446
447