📄 antlr3collections.c
字号:
/** \file * Provides a number of useful functions that are roughly equivalent * to java HashTable and List for the purposes of Antlr 3 C runtime. * Also useable by the C programmer for things like symbol tables pointers * and so on. * */#include <antlr3.h>/* Interface functions for hash table */static void antlr3HashDelete (pANTLR3_HASH_TABLE table, void * key);static void * antlr3HashGet (pANTLR3_HASH_TABLE table, void * key);static pANTLR3_HASH_ENTRY antlr3HashRemove (pANTLR3_HASH_TABLE table, void * key);static ANTLR3_INT32 antlr3HashPut (pANTLR3_HASH_TABLE table, void * key, void * element, void (*freeptr)(void *));static void antlr3HashFree (pANTLR3_HASH_TABLE table);static ANTLR3_UINT64 antlr3HashSize (pANTLR3_HASH_TABLE table);/* Interface functions for enumeration */static int antlr3EnumNext (pANTLR3_HASH_ENUM en, void ** key, void ** data);static void antlr3EnumFree (pANTLR3_HASH_ENUM en);/* Interface functions for List */static void antlr3ListFree (pANTLR3_LIST list);static void antlr3ListDelete(pANTLR3_LIST list, ANTLR3_UINT64 key);static void * antlr3ListGet (pANTLR3_LIST list, ANTLR3_UINT64 key);static ANTLR3_INT32 antlr3ListPut (pANTLR3_LIST list, ANTLR3_UINT64 key, void * element, void (*freeptr)(void *));static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (*freeptr)(void *));static void * antlr3ListRemove(pANTLR3_LIST list, ANTLR3_UINT64 key);static ANTLR3_UINT64 antlr3ListSize (pANTLR3_LIST list);/* Interface functions for Stack */static void antlr3StackFree (pANTLR3_STACK stack);static void antlr3StackPop (pANTLR3_STACK stack);static void * antlr3StackGet (pANTLR3_STACK stack, ANTLR3_UINT64 key);static ANTLR3_BOOLEAN antlr3StackPush (pANTLR3_STACK stack, void * element, void (*freeptr)(void *));static ANTLR3_UINT64 antlr3StackSize (pANTLR3_STACK stack);static void * antlr3StackPeek (pANTLR3_STACK stack);/* Interface functions for vectors */static void antlr3VectorFree (pANTLR3_VECTOR vector);static void antlr3VectorDel (pANTLR3_VECTOR vector, ANTLR3_UINT64 entry);static void * antlr3VectorGet (pANTLR3_VECTOR vector, ANTLR3_UINT64 entry);static void * antrl3VectorRemove (pANTLR3_VECTOR vector, ANTLR3_UINT64 entry);static ANTLR3_INT32 antlr3VectorAdd (pANTLR3_VECTOR vector, void * element, void (*freeptr)(void *));static ANTLR3_INT32 antlr3VectorPut (pANTLR3_VECTOR vector, ANTLR3_UINT64 entry, void * element, void (*freeptr)(void *));static ANTLR3_UINT64 antlr3VectorSize (pANTLR3_VECTOR vector);static void closeVectorFactory (pANTLR3_VECTOR_FACTORY factory);static pANTLR3_VECTOR newVector (pANTLR3_VECTOR_FACTORY factory);/* Local function to advance enumeration structure pointers */static void antlr3EnumNextEntry(pANTLR3_HASH_ENUM en);pANTLR3_HASH_TABLEantlr3HashTableNew(ANTLR3_UINT32 sizeHint){ /* All we have to do is create the hashtable tracking structure * and allocate memory for the requested number of buckets. */ pANTLR3_HASH_TABLE table; ANTLR3_UINT32 bucket; /* Used to traverse the buckets */ table = ANTLR3_MALLOC(sizeof(ANTLR3_HASH_TABLE)); /* Error out if no memory left */ if (table == NULL) { return (pANTLR3_HASH_TABLE) ANTLR3_ERR_NOMEM; } /* Allocate memory for the buckets */ table->buckets = (pANTLR3_HASH_BUCKET) ANTLR3_MALLOC((size_t) (sizeof(ANTLR3_HASH_BUCKET) * sizeHint)); if (table->buckets == NULL) { ANTLR3_FREE((void *)table); return (pANTLR3_HASH_TABLE) ANTLR3_ERR_NOMEM; } /* Modulo of the table, (bucket count). */ table->modulo = sizeHint; table->count = 0; /* Nothing in there yet ( I hope) */ /* Initialize the buckets to empty */ for (bucket = 0; bucket < sizeHint; bucket++) { table->buckets[bucket].entries = NULL; } /* Exclude duplicate entries by default */ table->allowDups = ANTLR3_FALSE; /* Install the interface */ table->free = antlr3HashFree; table->get = antlr3HashGet; table->put = antlr3HashPut; table->del = antlr3HashDelete; table->size = antlr3HashSize; table->remove = antlr3HashRemove; return table;}static voidantlr3HashFree(pANTLR3_HASH_TABLE table){ ANTLR3_UINT32 bucket; /* Used to traverse the buckets */ pANTLR3_HASH_BUCKET thisBucket; pANTLR3_HASH_ENTRY entry; pANTLR3_HASH_ENTRY nextEntry; /* Free the table, all buckets and all entries, and all the * keys and data (if the table exists) */ if (table != NULL) { for (bucket = 0; bucket < table->modulo; bucket++) { thisBucket = &(table->buckets[bucket]); /* Allow sparse tables, though we don't create them as such at present */ if ( thisBucket != NULL) { entry = thisBucket->entries; /* Search all entries in the bucket and free them up */ while (entry != NULL) { /* Save next entry - we do not want to access memory in entry after we * have freed it. */ nextEntry = entry->nextEntry; /* Free any data pointer, this only happens if the user supplied * a pointer to a routine that knwos how to free the structure they * added to the table. */ if (entry->free != NULL) { entry->free(entry->data); } /* Free the key memory - we know that we allocated this */ if (entry->key != NULL) { ANTLR3_FREE(entry->key); } /* Free this entry */ ANTLR3_FREE(entry); entry = nextEntry; /* Load next pointer to see if we shoud free it */ } /* Invalidate the current pointer */ thisBucket->entries = NULL; } } /* Now we can free the bucket memory */ ANTLR3_FREE(table->buckets); } /* Now we free teh memory for the table itself */ ANTLR3_FREE(table);}/** return the current size of the hash table */static ANTLR3_UINT64 antlr3HashSize (pANTLR3_HASH_TABLE table){ return table->count;}/** Remove the element in the hash table for a particular * key value, if it exists - no error if it does not. */static pANTLR3_HASH_ENTRYantlr3HashRemove(pANTLR3_HASH_TABLE table, void * key){ ANTLR3_UINT32 hash; pANTLR3_HASH_BUCKET bucket; pANTLR3_HASH_ENTRY entry; pANTLR3_HASH_ENTRY * nextPointer; /* First we need to know the hash of the provided key */ hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key)); /* Knowing the hash, we can find the bucket */ bucket = table->buckets + (hash % table->modulo); /* Now, we traverse the entries in the bucket until * we find the key or the end of the entires in the bucket. * We track the element prior to the one we are exmaining * as we need to set its next pointer to the next pointer * of the entry we are deleting (if we find it). */ entry = bucket->entries; /* Entry to examine */ nextPointer = & bucket->entries; /* Where to put the next pointer of the deleted entry */ while (entry != NULL) { /* See if this is the entry we wish to delete */ if (strcmp((const char *)key, (const char *)entry->key) == 0) { /* It was the correct entry, so we set the next pointer * of the previous entry to the next pointer of this * located one, which takes it out of the chain. */ (*nextPointer) = entry->nextEntry; /* Release the key - we allocated that */ ANTLR3_FREE(entry->key); entry->key = NULL; table->count--; return entry; } else { /* We found an entry but it wasn't the one that was wanted, so * move to the next one, if any. */ nextPointer = & (entry->nextEntry); /* Address of the next pointer in the current entry */ entry = entry->nextEntry; /* Address of the next element in the bucket (if any) */ } } return NULL; /* Not found */}/** Takes the element with the supplied key out of the list, and deletes the data * calling the supplied free() routine if any. */static voidantlr3HashDelete (pANTLR3_HASH_TABLE table, void * key){ pANTLR3_HASH_ENTRY entry; entry = antlr3HashRemove(table, key); /* Now we can free the elements and the entry in order */ if (entry != NULL && entry->free != NULL) { /* Call programmer supplied function to release this entry data */ entry->free(entry->data); entry->data = NULL; } /* Finally release the space for this entry block. */ ANTLR3_FREE(entry);}/** Return the element pointer in the hash table for a particular * key value, or NULL if it don't exist (or was itself NULL). */static void *antlr3HashGet(pANTLR3_HASH_TABLE table, void * key){ ANTLR3_UINT32 hash; pANTLR3_HASH_BUCKET bucket; pANTLR3_HASH_ENTRY entry; /* First we need to know the hash of the provided key */ hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key)); /* Knowing the hash, we can find the bucket */ bucket = table->buckets + (hash % table->modulo); /* Now we can inspect the key at each entry in the bucket * and see if we have a match. */ entry = bucket->entries; while (entry != NULL) { if (strcmp((const char *)key, (const char *)entry->key) == 0) { /* Match was found, return the data pointer for this entry */ return entry->data; } entry = entry->nextEntry; } /* If we got here, then we did not find the key */ return NULL;}/** Add the element pointer in to the table, based upon the * hash of the provided key. */static ANTLR3_INT32antlr3HashPut(pANTLR3_HASH_TABLE table, void * key, void * element, void (*freeptr)(void *)){ ANTLR3_UINT32 hash; pANTLR3_HASH_BUCKET bucket; pANTLR3_HASH_ENTRY entry; pANTLR3_HASH_ENTRY * newPointer; /* First we need to know the hash of the provided key */ hash = antlr3Hash(key, (ANTLR3_UINT32)strlen((const char *)key)); /* Knowing the hash, we can find the bucket */ bucket = table->buckets + (hash % table->modulo); /* Knowign the bucket, we can traverse the entries until we * we find a NULL pointer ofr we find that this is already * in the table and duplicates were not allowed. */ newPointer = &bucket->entries; while (*newPointer != NULL) { /* The value at new pointer is pointing to an existing entry. * If duplicates are allowed then we don't care what it is, but * must reject this add if the key is the same as the one we are * supplied with. */ if (table->allowDups == ANTLR3_FALSE) { if (strcmp((const char*) key, (const char *)(*newPointer)->key) == 0) { return ANTLR3_ERR_HASHDUP; } } /* Point to the next entry pointer of the current entry we * are traversing, if it is NULL we will create our new * structure and point this to it. */ newPointer = &((*newPointer)->nextEntry); } /* newPointer is now poiting at the pointer where we need to * add our new entry, so let's crate the entry and add it in. */ entry = (pANTLR3_HASH_ENTRY)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENTRY)); if (entry == NULL) { return ANTLR3_ERR_NOMEM; } entry->data = element; /* Install the data element supplied */ entry->free = freeptr; /* Function that knows how to release the entry */ entry->key = ANTLR3_STRDUP(key); /* Record the key value */ entry->nextEntry = NULL; /* Ensure that the forward pointer ends the chain */ *newPointer = entry; /* Install the next entry in this bucket */ table->count++; return ANTLR3_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -