// // gravity_utils.c // gravity // // Created by Marco Bambini on 29/08/14. // Copyright (c) 2014 CreoLabs. All rights reserved. // #include #include #include #include #include #include #include #if defined(__linux) #include #endif #if defined(__MACH__) #include #endif #if defined(_WIN32) #include #include #include #endif #include "gravity_utils.h" #include "gravity_memory.h" #define SWP(x,y) (x^=y, y^=x, x^=y) // MARK: Timer - nanotime_t nanotime (void) { nanotime_t value; #if defined(_WIN32) static LARGE_INTEGER win_frequency; QueryPerformanceFrequency(&win_frequency); LARGE_INTEGER t; if (!QueryPerformanceCounter(&t)) return 0; value = (t.QuadPart / win_frequency.QuadPart) * 1000000000; value += (t.QuadPart % win_frequency.QuadPart) * 1000000000 / win_frequency.QuadPart; #elif defined(__MACH__) mach_timebase_info_data_t info; kern_return_t r; nanotime_t t; t = mach_absolute_time(); r = mach_timebase_info(&info); if (r != 0) return 0; value = (t / info.denom) * info.numer; value += (t % info.denom) * info.numer / info.denom; #elif defined(__linux) struct timespec ts; int r; r = clock_gettime(CLOCK_MONOTONIC, &ts); if (r != 0) return 0; value = ts.tv_sec * (nanotime_t)1000000000 + ts.tv_nsec; #else struct timeval tv; int r; r = gettimeofday(&tv, 0); if (r != 0) return 0; value = tv.tv_sec * (nanotime_t)1000000000 + tv.tv_usec * 1000; #endif return value; } double microtime (nanotime_t tstart, nanotime_t tend) { nanotime_t t = tend - tstart; return ((double)t / 1000.0f); } double millitime (nanotime_t tstart, nanotime_t tend) { nanotime_t t = tend - tstart; return ((double)t / 1000000.0f); } // MARK: - I/O Functions - uint64_t file_size (const char *path) { #ifdef WIN32 WIN32_FILE_ATTRIBUTE_DATA fileInfo; if (GetFileAttributesExA(path, GetFileExInfoStandard, (void*)&fileInfo) == 0) return -1; return (uint64_t)(((__int64)fileInfo.nFileSizeHigh) << 32 ) + fileInfo.nFileSizeLow; #else struct stat sb; if (stat(path, &sb) > 0) return -1; return (uint64_t)sb.st_size; #endif } const char *file_read(const char *path, size_t *len) { int fd = 0; off_t fsize = 0; size_t fsize2 = 0; char *buffer = NULL; fsize = (size_t) file_size(path); if (fsize < 0) goto abort_read; fd = open(path, O_RDONLY); if (fd < 0) goto abort_read; buffer = (char *)mem_alloc((size_t)fsize + 1); if (buffer == NULL) goto abort_read; buffer[fsize] = 0; fsize2 = read(fd, buffer, fsize); if (fsize2 == -1) goto abort_read; if (len) *len = fsize2; close(fd); return (const char *)buffer; abort_read: if (buffer) mem_free((void *)buffer); if (fd >= 0) close(fd); return NULL; } bool file_exists (const char *path) { #ifdef WIN32 BOOL isDirectory; DWORD attributes = GetFileAttributesA(path); // special directory case to drive the network path check if (attributes == INVALID_FILE_ATTRIBUTES) isDirectory = (GetLastError() == ERROR_BAD_NETPATH); else isDirectory = (FILE_ATTRIBUTE_DIRECTORY & attributes); if (isDirectory) { if (PathIsNetworkPathA(path)) return true; if (PathIsUNCA(path)) return true; } if (PathFileExistsA(path) == 1) return true; #else if (access(path, F_OK)==0) return true; #endif return false; } const char *file_buildpath (const char *filename, const char *dirpath) { // #ifdef WIN32 // PathCombineA(result, filename, dirpath); // #else size_t len1 = strlen(filename); size_t len2 = strlen(dirpath); size_t len = len1+len2+2; char *full_path = (char *)mem_alloc(len); if (!full_path) return NULL; if ((len2) && (dirpath[len2-1] != '/')) snprintf(full_path, len, "%s/%s", dirpath, filename); else snprintf(full_path, len, "%s%s", dirpath, filename); // #endif return (const char *)full_path; } bool file_write (const char *path, const char *buffer, size_t len) { // RW for owner, R for group, R for others #ifdef _WIN32 mode_t mode = _S_IWRITE; #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; #endif int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); if (fd < 0) return false; ssize_t nwrite = write(fd, buffer, len); close(fd); return (nwrite == len); } // MARK: - Directory Functions - bool is_directory (const char *path) { #ifdef WIN32 DWORD dwAttrs; dwAttrs = GetFileAttributesA(path); if (dwAttrs == INVALID_FILE_ATTRIBUTES) return false; if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) return true; #else struct stat buf; if (lstat(path, &buf) < 0) return false; if (S_ISDIR(buf.st_mode)) return true; #endif return false; } DIRREF directory_init (const char *dirpath) { #ifdef WIN32 WIN32_FIND_DATA findData; WCHAR path[MAX_PATH]; WCHAR dirpathW[MAX_PATH]; HANDLE hFind; // convert dirpath to dirpathW MultiByteToWideChar(CP_UTF8, 0, dirpath, -1, dirpathW, MAX_PATH); // in this way I can be sure that the first file returned (and lost) is . PathCombineW(path, dirpathW, _T("*")); // if the path points to a symbolic link, the WIN32_FIND_DATA buffer contains // information about the symbolic link, not the target return FindFirstFileW(path, &findData); #else return opendir(dirpath); #endif } const char *directory_read (DIRREF ref) { if (ref == NULL) return NULL; while (1) { #ifdef WIN32 WIN32_FIND_DATA findData; const char *file_name; if (FindNextFile(ref, &findData) == 0) { FindClose(ref); return NULL; } if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; if (findData.cFileName == NULL) continue; if (findData.cFileName[0] == '.') continue; file_name = malloc(MAX_PATH); strncpy(file_name, findData.cFileName, MAX_PATH); return (const char *)file_name; #else struct dirent *d; if ((d = readdir(ref)) == NULL) { closedir(ref); return NULL; } if (d->d_name[0] == 0) continue; if (d->d_name[0] == '.') continue; return (const char *)d->d_name; #endif } return NULL; } // MARK: - String Functions - int string_nocasencmp(const char *s1, const char *s2, size_t n) { while(n > 0 && tolower((unsigned char)*s1) == tolower((unsigned char)*s2)) { if(*s1 == '\0') return 0; s1++; s2++; n--; } if(n == 0) return 0; return tolower((unsigned char)*s1) - tolower((unsigned char)*s2); } int string_casencmp(const char *s1, const char *s2, size_t n) { while(n > 0 && ((unsigned char)*s1) == ((unsigned char)*s2)) { if(*s1 == '\0') return 0; s1++; s2++; n--; } if(n == 0) return 0; return ((unsigned char)*s1) - ((unsigned char)*s2); } int string_cmp (const char *s1, const char *s2) { if (!s1) return 1; return strcmp(s1, s2); } const char *string_dup (const char *s1) { size_t len = (size_t)strlen(s1); char *s = (char *)mem_alloc(len + 1); memcpy(s, s1, len); return s; } const char *string_ndup (const char *s1, size_t n) { char *s = (char *)mem_alloc(n + 1); memcpy(s, s1, n); return s; } char *string_unescape (const char *s1, uint32_t *s1len, char *buffer) { uint32_t len = *s1len; uint32_t orig_len = len; for (uint32_t i=0, j=0; i 0) && (c <= 127)) return 1; if ((c >= 194) && (c <= 223)) return 2; if ((c >= 224) && (c <= 239)) return 3; if ((c >= 240) && (c <= 244)) return 4; // means error return 0; } uint32_t utf8_len (const char *s, uint32_t nbytes) { if (nbytes == 0) nbytes = (uint32_t)strlen(s); uint32_t pos = 1; uint32_t len = 0; while (pos <= nbytes) { ++len; uint32_t n = utf8_charbytes(s, pos); if (n == 0) return 0; // means error pos += n; } return len; } // From: http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c void utf8_reverse (char *p) { char *q = p; string_reverse(p); // now fix bass-ackwards UTF chars. while(q && *q) ++q; // find eos while(p < --q) switch( (*q & 0xF0) >> 4 ) { case 0xF: /* U+010000-U+10FFFF: four bytes. */ SWP(*(q-0), *(q-3)); SWP(*(q-1), *(q-2)); q -= 3; break; case 0xE: /* U+000800-U+00FFFF: three bytes. */ SWP(*(q-0), *(q-2)); q -= 2; break; case 0xC: /* fall-through */ case 0xD: /* U+000080-U+0007FF: two bytes. */ SWP(*(q-0), *(q-1)); q--; break; } } // MARK: - Math - // From: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2Float uint32_t power_of2_ceil (uint32_t n) { n--; n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16; n++; return n; } int64_t number_from_hex (const char *s, uint32_t len) { #pragma unused(len) return (int64_t) strtoll(s, NULL, 16); } int64_t number_from_oct (const char *s, uint32_t len) { #pragma unused(len) return (int64_t) strtoll(s, NULL, 8); } int64_t number_from_bin (const char *s, uint32_t len) { int64_t value = 0; for (uint32_t i=0; i