#include <dirent.h>
#include <sys/stat.h>
#include "private.h"
int heliInitialized;
HeliArray heliObjectsSet;
struct _Directory {
HeliArray files;
};
static char *colors[][2] = {
{ "transparent", "0 0 0 0" },
{ "black", "0 0 0 1" },
{ "white", "1 1 1 1" },
{ "gray", "0.5 0.5 0.5 1" },
{ "red", "1 0 0 1" },
{ "green", "0 1 0 1" },
{ "blue", "0 0 1 1" },
{ "yellow", "1 1 0 1" },
{ "magenta", "1 0 1 1" },
{ "cyan", "0 1 1 1" },
{ "brown", "0.5 0.5 0 1" },
};
int randomNumber(int min, int max)
{ return max <= min ? min : rand()%(max - min + 1) + min; }
double randomFloat()
{ return (double)rand()/(double)RAND_MAX; }
Directory openDirectory(const char *path) {
if (!heliInitialized) return NULL;
DIR *dir = opendir(path);
if (!dir) return NULL;
Directory d = calloc(1, sizeof(*d));
struct dirent *ent;
while((ent = readdir(dir)) != NULL) {
if ( !ent->d_name[0]
|| strcmp(ent->d_name, ".") == 0
|| strcmp(ent->d_name, "..") == 0 ) continue;
heliStringmapAdd(&d->files, ent->d_name, NULL, NULL);
}
closedir(dir);
heliObjectRegister(d, (HeliFreeCallback)&closeDirectory);
return d;
}
void closeDirectory(Directory directory) {
if (!directory) return;
heliObjectUnregister(directory);
heliArrayDestroy(&directory->files);
free(directory);
}
int directoryGetCount(Directory directory)
{ return directory->files.count; }
const char* directoryGet(Directory directory, int i)
{ return (const char*)heliArrayGetKey(&directory->files, i); }
int fileExists(const char *path) {
struct stat s = {};
return stat(path, &s) == 0 && !(s.st_mode & S_IFDIR);
}
int directoryExists(const char *path) {
struct stat s = {};
return stat(path, &s) == 0 && (s.st_mode & S_IFDIR);
}
char* heliStringCopy(const char *x) {
int len = strlen(x) + 1;
char *cp = malloc(len);
memcpy(cp, x, len);
return cp;
}
char* heliStringConcat(const char *a, const char *b) {
int la = strlen(a);
int lb = strlen(b);
char *s = malloc(la + lb + 1);
memcpy(s, a, la);
memcpy(s + la, b, lb);
s[la + lb] = 0;
return s;
}
char* heliStringConcat3(const char *a, const char *b, const char *c) {
int la = strlen(a);
int lb = strlen(b);
int lc = strlen(c);
char *s = malloc(la + lb + lc + 1);
memcpy(s, a, la);
memcpy(s + la, b, lb);
memcpy(s + la + lb, c, lc);
s[la + lb + lc] = 0;
return s;
}
int heliStringEndsWithLowcase(const char *s, const char *tail) {
int ls = strlen(s);
int lt = strlen(tail);
if (lt > ls) return FALSE;
for(int i = 0; i < lt; ++i)
if (tolower(s[ls - i]) != tolower(tail[lt - i]))
return FALSE;
return TRUE;
}
void heliLowercase(char *x)
{ while(*x) { *x = tolower(*x); ++x; } }
static unsigned int colorToInt(double c) {
if (!(c > 0)) c = 0;
if (!(c < 1)) c = 1;
return (unsigned int)floor(c*255.99);
}
void heliColorToDouble(unsigned int code, double *rgba) {
rgba[0] = ( code >> 24 )/255.0;
rgba[1] = ((code >> 16) & 0xFFu)/255.0;
rgba[2] = ((code >> 8) & 0xFFu)/255.0;
rgba[3] = ( code & 0xFFu)/255.0;
}
unsigned int colorByRGBA(double r, double g, double b, double a) {
return (colorToInt(r) << 24)
| (colorToInt(g) << 16)
| (colorToInt(b) << 8)
| colorToInt(a);
}
unsigned int colorByRGB(double r, double g, double b)
{ return colorByRGBA(r, g, b, 1); }
unsigned int colorByName(const char *colorName) {
unsigned int code = 0;
const char *x = colorName;
if (*x == '#') {
++x;
int hex[8] = { 0, 0, 0, 0, 0, 0, 15, 15 };
for(int i = 0; *x && i < 8; ++i, ++x) {
char c = tolower(*x);
if (c >= '0' && c <= '9') hex[i] = c - '0';
if (c >= 'a' && c <= 'f') hex[i] = c - 'a' + 10;
}
for(int i = 0; i < 8; ++i)
code |= ( hex[i] << ((7-i)*4) );
} else
if (isalpha(*x)) {
int count = (int)(sizeof(colors)/sizeof(*colors));
for(int i = 0; i < count; ++i) {
const char *a = x, *b = colors[i][0];
do {
if (tolower(*a) != tolower(*b)) break;
++a, ++b;
if (!*a && !*b) return colorByName(colors[i][1]);
} while (*a && *b);
}
} else {
double r = 0, g = 0, b = 0, a = 1;
sscanf(x, "%lf %lf %lf %lf", &r, &g, &b, &a);
code = colorByRGBA(r, g, b, a);
}
return code;
}
static int objectsCompare(const void *a, const void *b)
{ return a < b ? -1 : b < a ? 1 : 0; }
static void* objectsKeyClone(void *k)
{ return k; }
void heliObjectRegister(void *o, HeliFreeCallback fo)
{ heliMapAdd(&heliObjectsSet, o, &objectsCompare, (HeliCloneCallback)objectsKeyClone, fo, NULL, NULL); }
void heliObjectUnregister(void *o) {
int i;
HeliPair *item = heliMapFind(&heliObjectsSet, o, &objectsCompare, &i);
if (item) {
item->freeKey = NULL;
heliArrayRemove(&heliObjectsSet, i);
}
}