📄 jim.c
字号:
*doublePtr = strtod(str, &endptr);
if (str[0] == '\0' || endptr[0] != '\0')
return JIM_ERR;
return JIM_OK;
}
static jim_wide JimPowWide(jim_wide b, jim_wide e)
{
jim_wide i, res = 1;
if ((b==0 && e!=0) || (e<0)) return 0;
for(i=0; i<e; i++) {res *= b;}
return res;
}
/* -----------------------------------------------------------------------------
* Special functions
* ---------------------------------------------------------------------------*/
/* Note that 'interp' may be NULL if not available in the
* context of the panic. It's only useful to get the error
* file descriptor, it will default to stderr otherwise. */
void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
{
va_list ap;
FILE *fp = interp ? interp->stderr : stderr;
va_start(ap, fmt);
fprintf(fp, JIM_NL "JIM INTERPRETER PANIC: ");
vfprintf(fp, fmt, ap);
fprintf(fp, JIM_NL JIM_NL);
va_end(ap);
#ifdef HAVE_BACKTRACE
{
void *array[40];
int size, i;
char **strings;
size = backtrace(array, 40);
strings = backtrace_symbols(array, size);
for (i = 0; i < size; i++)
fprintf(fp,"[backtrace] %s" JIM_NL, strings[i]);
fprintf(fp,"[backtrace] Include the above lines and the output" JIM_NL);
fprintf(fp,"[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
}
#endif
abort();
}
/* -----------------------------------------------------------------------------
* Memory allocation
* ---------------------------------------------------------------------------*/
/* Macro used for memory debugging.
* In order for they to work you have to rename Jim_Alloc into _Jim_Alloc
* and similary for Jim_Realloc and Jim_Free */
#if 0
#define Jim_Alloc(s) (printf("%s %d: Jim_Alloc(%d)\n",__FILE__,__LINE__,s),_Jim_Alloc(s))
#define Jim_Free(p) (printf("%s %d: Jim_Free(%p)\n",__FILE__,__LINE__,p),_Jim_Free(p))
#define Jim_Realloc(p,s) (printf("%s %d: Jim_Realloc(%p,%d)\n",__FILE__,__LINE__,p,s),_Jim_Realloc(p,s))
#endif
void *Jim_Alloc(int size)
{
void *p = malloc(size);
if (p == NULL)
Jim_Panic(NULL,"Out of memory");
return p;
}
void Jim_Free(void *ptr) {
free(ptr);
}
void *Jim_Realloc(void *ptr, int size)
{
void *p = realloc(ptr, size);
if (p == NULL)
Jim_Panic(NULL,"Out of memory");
return p;
}
char *Jim_StrDup(const char *s)
{
int l = strlen(s);
char *copy = Jim_Alloc(l+1);
memcpy(copy, s, l+1);
return copy;
}
char *Jim_StrDupLen(const char *s, int l)
{
char *copy = Jim_Alloc(l+1);
memcpy(copy, s, l+1);
copy[l] = 0; /* Just to be sure, original could be substring */
return copy;
}
/* -----------------------------------------------------------------------------
* Time related functions
* ---------------------------------------------------------------------------*/
/* Returns microseconds of CPU used since start. */
static jim_wide JimClock(void)
{
#if (defined WIN32) && !(defined JIM_ANSIC)
LARGE_INTEGER t, f;
QueryPerformanceFrequency(&f);
QueryPerformanceCounter(&t);
return (long)((t.QuadPart * 1000000) / f.QuadPart);
#else /* !WIN32 */
clock_t clocks = clock();
return (long)(clocks*(1000000/CLOCKS_PER_SEC));
#endif /* WIN32 */
}
/* -----------------------------------------------------------------------------
* Hash Tables
* ---------------------------------------------------------------------------*/
/* -------------------------- private prototypes ---------------------------- */
static int JimExpandHashTableIfNeeded(Jim_HashTable *ht);
static unsigned int JimHashTableNextPower(unsigned int size);
static int JimInsertHashEntry(Jim_HashTable *ht, const void *key);
/* -------------------------- hash functions -------------------------------- */
/* Thomas Wang's 32 bit Mix Function */
unsigned int Jim_IntHashFunction(unsigned int key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
/* Identity hash function for integer keys */
unsigned int Jim_IdentityHashFunction(unsigned int key)
{
return key;
}
/* Generic hash function (we are using to multiply by 9 and add the byte
* as Tcl) */
unsigned int Jim_GenHashFunction(const unsigned char *buf, int len)
{
unsigned int h = 0;
while(len--)
h += (h<<3)+*buf++;
return h;
}
/* ----------------------------- API implementation ------------------------- */
/* reset an hashtable already initialized with ht_init().
* NOTE: This function should only called by ht_destroy(). */
static void JimResetHashTable(Jim_HashTable *ht)
{
ht->table = NULL;
ht->size = 0;
ht->sizemask = 0;
ht->used = 0;
ht->collisions = 0;
}
/* Initialize the hash table */
int Jim_InitHashTable(Jim_HashTable *ht, Jim_HashTableType *type,
void *privDataPtr)
{
JimResetHashTable(ht);
ht->type = type;
ht->privdata = privDataPtr;
return JIM_OK;
}
/* Resize the table to the minimal size that contains all the elements,
* but with the invariant of a USER/BUCKETS ration near to <= 1 */
int Jim_ResizeHashTable(Jim_HashTable *ht)
{
int minimal = ht->used;
if (minimal < JIM_HT_INITIAL_SIZE)
minimal = JIM_HT_INITIAL_SIZE;
return Jim_ExpandHashTable(ht, minimal);
}
/* Expand or create the hashtable */
int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size)
{
Jim_HashTable n; /* the new hashtable */
unsigned int realsize = JimHashTableNextPower(size), i;
/* the size is invalid if it is smaller than the number of
* elements already inside the hashtable */
if (ht->used >= size)
return JIM_ERR;
Jim_InitHashTable(&n, ht->type, ht->privdata);
n.size = realsize;
n.sizemask = realsize-1;
n.table = Jim_Alloc(realsize*sizeof(Jim_HashEntry*));
/* Initialize all the pointers to NULL */
memset(n.table, 0, realsize*sizeof(Jim_HashEntry*));
/* Copy all the elements from the old to the new table:
* note that if the old hash table is empty ht->size is zero,
* so Jim_ExpandHashTable just creates an hash table. */
n.used = ht->used;
for (i = 0; i < ht->size && ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
if (ht->table[i] == NULL) continue;
/* For each hash entry on this slot... */
he = ht->table[i];
while(he) {
unsigned int h;
nextHe = he->next;
/* Get the new element index */
h = Jim_HashKey(ht, he->key) & n.sizemask;
he->next = n.table[h];
n.table[h] = he;
ht->used--;
/* Pass to the next element */
he = nextHe;
}
}
assert(ht->used == 0);
Jim_Free(ht->table);
/* Remap the new hashtable in the old */
*ht = n;
return JIM_OK;
}
/* Add an element to the target hash table */
int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
int index;
Jim_HashEntry *entry;
/* Get the index of the new element, or -1 if
* the element already exists. */
if ((index = JimInsertHashEntry(ht, key)) == -1)
return JIM_ERR;
/* Allocates the memory and stores key */
entry = Jim_Alloc(sizeof(*entry));
entry->next = ht->table[index];
ht->table[index] = entry;
/* Set the hash entry fields. */
Jim_SetHashKey(ht, entry, key);
Jim_SetHashVal(ht, entry, val);
ht->used++;
return JIM_OK;
}
/* Add an element, discarding the old if the key already exists */
int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val)
{
Jim_HashEntry *entry;
/* Try to add the element. If the key
* does not exists Jim_AddHashEntry will suceed. */
if (Jim_AddHashEntry(ht, key, val) == JIM_OK)
return JIM_OK;
/* It already exists, get the entry */
entry = Jim_FindHashEntry(ht, key);
/* Free the old value and set the new one */
Jim_FreeEntryVal(ht, entry);
Jim_SetHashVal(ht, entry, val);
return JIM_OK;
}
/* Search and remove an element */
int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key)
{
unsigned int h;
Jim_HashEntry *he, *prevHe;
if (ht->size == 0)
return JIM_ERR;
h = Jim_HashKey(ht, key) & ht->sizemask;
he = ht->table[h];
prevHe = NULL;
while(he) {
if (Jim_CompareHashKeys(ht, key, he->key)) {
/* Unlink the element from the list */
if (prevHe)
prevHe->next = he->next;
else
ht->table[h] = he->next;
Jim_FreeEntryKey(ht, he);
Jim_FreeEntryVal(ht, he);
Jim_Free(he);
ht->used--;
return JIM_OK;
}
prevHe = he;
he = he->next;
}
return JIM_ERR; /* not found */
}
/* Destroy an entire hash table */
int Jim_FreeHashTable(Jim_HashTable *ht)
{
unsigned int i;
/* Free all the elements */
for (i = 0; i < ht->size && ht->used > 0; i++) {
Jim_HashEntry *he, *nextHe;
if ((he = ht->table[i]) == NULL) continue;
while(he) {
nextHe = he->next;
Jim_FreeEntryKey(ht, he);
Jim_FreeEntryVal(ht, he);
Jim_Free(he);
ht->used--;
he = nextHe;
}
}
/* Free the table and the allocated cache structure */
Jim_Free(ht->table);
/* Re-initialize the table */
JimResetHashTable(ht);
return JIM_OK; /* never fails */
}
Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key)
{
Jim_HashEntry *he;
unsigned int h;
if (ht->size == 0) return NULL;
h = Jim_HashKey(ht, key) & ht->sizemask;
he = ht->table[h];
while(he) {
if (Jim_CompareHashKeys(ht, key, he->key))
return he;
he = he->next;
}
return NULL;
}
Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
{
Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
iter->ht = ht;
iter->index = -1;
iter->entry = NULL;
iter->nextEntry = NULL;
return iter;
}
Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
{
while (1) {
if (iter->entry == NULL) {
iter->index++;
if (iter->index >=
(signed)iter->ht->size) break;
iter->entry = iter->ht->table[iter->index];
} else {
iter->entry = iter->nextEntry;
}
if (iter->entry) {
/* We need to save the 'next' here, the iterator user
* may delete the entry we are returning. */
iter->nextEntry = iter->entry->next;
return iter->entry;
}
}
return NULL;
}
/* ------------------------- private functions ------------------------------ */
/* Expand the hash table if needed */
static int JimExpandHashTableIfNeeded(Jim_HashTable *ht)
{
/* If the hash table is empty expand it to the intial size,
* if the table is "full" dobule its size. */
if (ht->size == 0)
return Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE);
if (ht->size == ht->used)
return Jim_ExpandHashTable(ht, ht->size*2);
return JIM_OK;
}
/* Our hash table capability is a power of two */
static unsigned int JimHashTableNextPower(unsigned int size)
{
unsigned int i = JIM_HT_INITIAL_SIZE;
if (size >= 2147483648U)
return 2147483648U;
while(1) {
if (i >= size)
return i;
i *= 2;
}
}
/* Returns the index of a free slot that can be populated with
* an hash entry for the given 'key'.
* If the key already exists, -1 is returned. */
static int JimInsertHashEntry(Jim_HashTable *ht, const void *key)
{
unsigned int h;
Jim_HashEntry *he;
/* Expand the hashtable if needed */
if (JimExpandHashTableIfNeeded(ht) == JIM_ERR)
return -1;
/* Compute the key hash value */
h = Jim_HashKey(ht, key) & ht->sizemask;
/* Search if this slot does not already contain the given key */
he = ht->table[h];
while(he) {
if (Jim_CompareHashKeys(ht, key, he->key))
return -1;
he = he->next;
}
return h;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -