various fixes:

add stb_intcmprev
  add stb_uidict
  fixes to stb__dirtree_scandir
  change rand functions from unsigned long to unsigned int so they're 32-bit on Linux as well
This commit is contained in:
Sean Barrett 2019-02-07 04:33:18 -08:00
parent e5254a7fde
commit d85e594654

137
stb.h
View File

@ -791,7 +791,7 @@ STB_EXTERN __declspec(dllimport) int __stdcall SetConsoleTextAttribute(void *, u
static void stb__print_one(void *handle, char *s, int len) static void stb__print_one(void *handle, char *s, int len)
{ {
if (len) if (len)
if (WriteConsoleA(handle, s, len, NULL,NULL)) if (0==WriteConsoleA(handle, s, len, NULL,NULL))
fwrite(s, 1, len, stdout); // if it fails, maybe redirected, so do normal fwrite(s, 1, len, stdout); // if it fails, maybe redirected, so do normal
} }
@ -1543,6 +1543,7 @@ int stb_lowbit8(unsigned int n)
STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b); STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b);
STB_EXTERN int (*stb_intcmprev(int offset))(const void *a, const void *b);
STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b); STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b);
STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b); STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b);
STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b); STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b);
@ -1560,6 +1561,13 @@ int stb__intcmp(const void *a, const void *b)
return p < q ? -1 : p > q; return p < q ? -1 : p > q;
} }
int stb__intcmprev(const void *a, const void *b)
{
const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
return q < p ? -1 : q > p;
}
int stb__ucharcmp(const void *a, const void *b) int stb__ucharcmp(const void *a, const void *b)
{ {
const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset); const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset);
@ -1601,6 +1609,12 @@ int (*stb_intcmp(int offset))(const void *, const void *)
return &stb__intcmp; return &stb__intcmp;
} }
int (*stb_intcmprev(int offset))(const void *, const void *)
{
stb__intcmpoffset = offset;
return &stb__intcmprev;
}
int (*stb_ucharcmp(int offset))(const void *, const void *) int (*stb_ucharcmp(int offset))(const void *, const void *)
{ {
stb__ucharcmpoffset = offset; stb__ucharcmpoffset = offset;
@ -4101,12 +4115,14 @@ static void STB_(N, rehash)(TYPE *a, int count) \
stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *) stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *)
stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32) stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32)
stb_declare_hash(STB_EXTERN, stb_uidict, stbi_uidict_, stb_uint32, stb_uint32)
STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *)); STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *));
STB_EXTERN stb_ptrmap *stb_ptrmap_new(void); STB_EXTERN stb_ptrmap *stb_ptrmap_new(void);
STB_EXTERN stb_idict * stb_idict_new_size(int size); STB_EXTERN stb_idict * stb_idict_new_size(int size);
STB_EXTERN void stb_idict_remove_all(stb_idict *e); STB_EXTERN void stb_idict_remove_all(stb_idict *e);
STB_EXTERN void stb_uidict_reset(stb_uidict *e);
#ifdef STB_DEFINE #ifdef STB_DEFINE
@ -4163,6 +4179,23 @@ void stb_idict_remove_all(stb_idict *e)
for (n=0; n < e->limit; ++n) for (n=0; n < e->limit; ++n)
e->table[n].k = STB_IEMPTY; e->table[n].k = STB_IEMPTY;
e->has_empty = e->has_del = 0; e->has_empty = e->has_del = 0;
e->count = 0;
e->deleted = 0;
}
stb_define_hash_base(STB_noprefix, stb_uidict, STB_nofields, stb_uidict_,stb_uidict_,0.85f,
stb_int32,0xffffffff,0xfffffffe,STB_nocopy,STB_nodelete,STB_nosafe,
STB_equal,STB_equal,
return stb_rehash_improved(k);,stb_uint32,STB_nonullvalue,0)
void stb_uidict_reset(stb_uidict *e)
{
int n;
for (n=0; n < e->limit; ++n)
e->table[n].k = 0xffffffff;
e->has_empty = e->has_del = 0;
e->count = 0;
e->deleted = 0;
} }
#endif #endif
@ -5934,6 +5967,9 @@ char **stb_getopt_param(int *argc, char **argv, char *param)
while (i < *argc) while (i < *argc)
argv[j++] = argv[i++]; argv[j++] = argv[i++];
break; break;
} else if (argv[i][1] == '-') {
// copy argument through including initial '-' for clarity
stb_arr_push(opts, strdup(argv[i]));
} else { } else {
int k; int k;
char *q = argv[i]; // traverse options list char *q = argv[i]; // traverse options list
@ -6595,15 +6631,23 @@ STB_EXTERN __declspec(dllimport) long __stdcall RegOpenKeyExA ( HKEY hKey, cons
#define STB__REG_KEY_ALL_ACCESS 0x000f003f #define STB__REG_KEY_ALL_ACCESS 0x000f003f
#define STB__REG_KEY_READ 0x00020019 #define STB__REG_KEY_READ 0x00020019
#ifdef _M_AMD64
#define STB__HKEY_CURRENT_USER 0x80000001ull
#define STB__HKEY_LOCAL_MACHINE 0x80000002ull
#else
#define STB__HKEY_CURRENT_USER 0x80000001
#define STB__HKEY_LOCAL_MACHINE 0x80000002
#endif
void *stb_reg_open(char *mode, char *where) void *stb_reg_open(char *mode, char *where)
{ {
long res; long res;
HKEY base; HKEY base;
HKEY zreg; HKEY zreg;
if (!stb_stricmp(mode+1, "cu") || !stb_stricmp(mode+1, "hkcu")) if (!stb_stricmp(mode+1, "cu") || !stb_stricmp(mode+1, "hkcu"))
base = (HKEY) 0x80000001; // HKCU base = (HKEY) STB__HKEY_CURRENT_USER;
else if (!stb_stricmp(mode+1, "lm") || !stb_stricmp(mode+1, "hklm")) else if (!stb_stricmp(mode+1, "lm") || !stb_stricmp(mode+1, "hklm"))
base = (HKEY) 0x80000002; // HKLM base = (HKEY) STB__HKEY_LOCAL_MACHINE;
else else
return NULL; return NULL;
@ -7011,6 +7055,8 @@ static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir)
fclose(f); fclose(f);
} }
FILE *hlog;
static int stb__dircount, stb__dircount_mask, stb__showfile; static int stb__dircount, stb__dircount_mask, stb__showfile;
static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active) static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active)
{ {
@ -7036,9 +7082,9 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti
swprintf(full_path, L"%s/*", stb__from_utf8(path)); swprintf(full_path, L"%s/*", stb__from_utf8(path));
#else #else
if (has_slash) if (has_slash)
swprintf(full_path, 1024, L"%s*", stb__from_utf8(path)); swprintf((wchar_t *) full_path, (size_t) 1024, L"%s*", (wchar_t *) stb__from_utf8(path));
else else
swprintf(full_path, 1024, L"%s/*", stb__from_utf8(path)); swprintf((wchar_t *) full_path, (size_t) 1024, L"%s/*", (wchar_t *) stb__from_utf8(path));
#endif #endif
// it's possible this directory is already present: that means it was in the // it's possible this directory is already present: that means it was in the
@ -7056,14 +7102,14 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti
n = stb_arr_lastn(active->dirs); n = stb_arr_lastn(active->dirs);
if (stb__showfile) printf("["); if (stb__showfile) printf("[");
if( (hFile = _wfindfirsti64( full_path, &c_file )) != -1L ) { if( (hFile = _wfindfirsti64( (wchar_t *) full_path, &c_file )) != -1L ) {
do { do {
if (stb__showfile) printf(")"); if (stb__showfile) printf(")");
if (c_file.attrib & _A_SUBDIR) { if (c_file.attrib & _A_SUBDIR) {
// ignore subdirectories starting with '.', e.g. "." and ".." // ignore subdirectories starting with '.', e.g. "." and ".."
if (c_file.name[0] != '.') { if (c_file.name[0] != '.') {
char *new_path = (char *) full_path; char *new_path = (char *) full_path;
char *temp = stb__to_utf8(c_file.name); char *temp = stb__to_utf8((stb__wchar *) c_file.name);
if (has_slash) if (has_slash)
sprintf(new_path, "%s%s", path, temp); sprintf(new_path, "%s%s", path, temp);
@ -7073,14 +7119,30 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti
if (stb__dircount_mask) { if (stb__dircount_mask) {
++stb__dircount; ++stb__dircount;
if (!(stb__dircount & stb__dircount_mask)) { if (!(stb__dircount & stb__dircount_mask)) {
printf("%s\r", new_path); char dummy_path[128], *pad;
stb_strncpy(dummy_path, new_path, sizeof(dummy_path)-1);
if (strlen(dummy_path) > 96) {
strcpy(dummy_path+96/2-1, "...");
strcpy(dummy_path+96/2+2, new_path + strlen(new_path)-96/2+2);
}
pad = dummy_path + strlen(dummy_path);
while (pad < dummy_path+98)
*pad++ = ' ';
*pad = 0;
printf("%s\r", dummy_path);
#if 0
if (hlog == 0) {
hlog = fopen("c:/x/temp.log", "w");
fprintf(hlog, "%s\n", dummy_path);
}
#endif
} }
} }
stb__dirtree_scandir(new_path, c_file.time_write, active); stb__dirtree_scandir(new_path, c_file.time_write, active);
} }
} else { } else {
char *temp = stb__to_utf8(c_file.name); char *temp = stb__to_utf8((stb__wchar *) c_file.name);
stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active); stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active);
} }
if (stb__showfile) printf("("); if (stb__showfile) printf("(");
@ -7113,12 +7175,12 @@ static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active)
if (0 == _stat(db->dirs[i].path, &info)) { if (0 == _stat(db->dirs[i].path, &info)) {
if (info.st_mode & _S_IFDIR) { if (info.st_mode & _S_IFDIR) {
// it's still a directory, as expected // it's still a directory, as expected
int n = abs(info.st_mtime - db->dirs[i].last_modified); int n = abs((int) (info.st_mtime - db->dirs[i].last_modified));
if (n > 1 && n != 3600) { // the 3600 is a hack because sometimes this jumps for no apparent reason, even when no time zone or DST issues are at play if (n > 1 && n != 3600) { // the 3600 is a hack because sometimes this jumps for no apparent reason, even when no time zone or DST issues are at play
// it's changed! force a rescan // it's changed! force a rescan
// we don't want to scan it until we've stat()d its // we don't want to scan it until we've stat()d its
// subdirs, though, so we queue it // subdirs, though, so we queue it
if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, db->dirs[i].last_modified, info.st_mtime); if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, (unsigned int) db->dirs[i].last_modified, (unsigned int) info.st_mtime);
stb_arr_push(rescan, i); stb_arr_push(rescan, i);
// update the last_mod time // update the last_mod time
db->dirs[i].last_modified = info.st_mtime; db->dirs[i].last_modified = info.st_mtime;
@ -7259,7 +7321,7 @@ stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir)
stb_dirtree *stb_dirtree_get(char *dir) stb_dirtree *stb_dirtree_get(char *dir)
{ {
char cache_dir[256]; char cache_dir[256];
strcpy(cache_dir, "c:/stb"); strcpy(cache_dir, "c:/bindata");
#ifdef STB_HAS_REGISTRY #ifdef STB_HAS_REGISTRY
{ {
void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb"); void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
@ -8206,44 +8268,44 @@ int stb_ps_eq(stb_ps *p0, stb_ps *p1)
// Random Numbers via Meresenne Twister or LCG // Random Numbers via Meresenne Twister or LCG
// //
STB_EXTERN unsigned long stb_srandLCG(unsigned long seed); STB_EXTERN unsigned int stb_srandLCG(unsigned long seed);
STB_EXTERN unsigned long stb_randLCG(void); STB_EXTERN unsigned int stb_randLCG(void);
STB_EXTERN double stb_frandLCG(void); STB_EXTERN double stb_frandLCG(void);
STB_EXTERN void stb_srand(unsigned long seed); STB_EXTERN void stb_srand(unsigned int seed);
STB_EXTERN unsigned long stb_rand(void); STB_EXTERN unsigned int stb_rand(void);
STB_EXTERN double stb_frand(void); STB_EXTERN double stb_frand(void);
STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz, STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz,
unsigned long seed); unsigned long seed);
STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz); STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz);
STB_EXTERN unsigned long stb_randLCG_explicit(unsigned long seed); STB_EXTERN unsigned int stb_randLCG_explicit(unsigned int seed);
#define stb_rand_define(x,y) \ #define stb_rand_define(x,y) \
\ \
unsigned long x(void) \ unsigned int x(void) \
{ \ { \
static unsigned long stb__rand = y; \ static unsigned int stb__rand = y; \
stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \ stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \
return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \ return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \
} }
#ifdef STB_DEFINE #ifdef STB_DEFINE
unsigned long stb_randLCG_explicit(unsigned long seed) unsigned int stb_randLCG_explicit(unsigned int seed)
{ {
return seed * 2147001325 + 715136305; return seed * 2147001325 + 715136305;
} }
static unsigned long stb__rand_seed=0; static unsigned int stb__rand_seed=0;
unsigned long stb_srandLCG(unsigned long seed) unsigned int stb_srandLCG(unsigned long seed)
{ {
unsigned long previous = stb__rand_seed; unsigned int previous = stb__rand_seed;
stb__rand_seed = seed; stb__rand_seed = seed;
return previous; return previous;
} }
unsigned long stb_randLCG(void) unsigned int stb_randLCG(void)
{ {
stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator
// shuffle non-random bits to the middle, and xor to decorrelate with seed // shuffle non-random bits to the middle, and xor to decorrelate with seed
@ -8284,17 +8346,17 @@ void stb_reverse(void *p, size_t n, size_t sz)
// public domain Mersenne Twister by Michael Brundage // public domain Mersenne Twister by Michael Brundage
#define STB__MT_LEN 624 #define STB__MT_LEN 624
int stb__mt_index = STB__MT_LEN*sizeof(unsigned long)+1; int stb__mt_index = STB__MT_LEN*sizeof(int)+1;
unsigned long stb__mt_buffer[STB__MT_LEN]; unsigned int stb__mt_buffer[STB__MT_LEN];
void stb_srand(unsigned long seed) void stb_srand(unsigned int seed)
{ {
int i; int i;
unsigned long old = stb_srandLCG(seed); unsigned int old = stb_srandLCG(seed);
for (i = 0; i < STB__MT_LEN; i++) for (i = 0; i < STB__MT_LEN; i++)
stb__mt_buffer[i] = stb_randLCG(); stb__mt_buffer[i] = stb_randLCG();
stb_srandLCG(old); stb_srandLCG(old);
stb__mt_index = STB__MT_LEN*sizeof(unsigned long); stb__mt_index = STB__MT_LEN*sizeof(unsigned int);
} }
#define STB__MT_IA 397 #define STB__MT_IA 397
@ -8305,15 +8367,15 @@ void stb_srand(unsigned long seed)
#define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK) #define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK)
#define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A) #define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A)
unsigned long stb_rand() unsigned int stb_rand()
{ {
unsigned long * b = stb__mt_buffer; unsigned int * b = stb__mt_buffer;
int idx = stb__mt_index; int idx = stb__mt_index;
unsigned long s,r; unsigned int s,r;
int i; int i;
if (idx >= STB__MT_LEN*sizeof(unsigned long)) { if (idx >= STB__MT_LEN*sizeof(unsigned int)) {
if (idx > STB__MT_LEN*sizeof(unsigned long)) if (idx > STB__MT_LEN*sizeof(unsigned int))
stb_srand(0); stb_srand(0);
idx = 0; idx = 0;
i = 0; i = 0;
@ -8329,9 +8391,9 @@ unsigned long stb_rand()
s = STB__TWIST(b, STB__MT_LEN-1, 0); s = STB__TWIST(b, STB__MT_LEN-1, 0);
b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s); b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s);
} }
stb__mt_index = idx + sizeof(unsigned long); stb__mt_index = idx + sizeof(unsigned int);
r = *(unsigned long *)((unsigned char *)b + idx); r = *(unsigned int *)((unsigned char *)b + idx);
r ^= (r >> 11); r ^= (r >> 11);
r ^= (r << 7) & 0x9D2C5680; r ^= (r << 7) & 0x9D2C5680;
@ -12401,7 +12463,7 @@ STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result)
// everywhere is 3MB. (That is, if you allocate 1 object of each size, // everywhere is 3MB. (That is, if you allocate 1 object of each size,
// you'll use 3MB.) // you'll use 3MB.)
#if defined(STB_DEFINE) && (defined(_WIN32) || defined(STB_FASTMALLOC)) #if defined(STB_DEFINE) && ((defined(_WIN32) && !defined(_M_AMD64)) || defined(STB_FASTMALLOC))
#ifdef _WIN32 #ifdef _WIN32
#ifndef _WINDOWS_ #ifndef _WINDOWS_
@ -13012,6 +13074,7 @@ char * stb__string_constant(char *file, int line, char *x)
#ifdef STB_STUA #ifdef STB_STUA
#error "STUA is no longer supported"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //
// stua: little scripting language // stua: little scripting language