📄 antlr3collections.c
字号:
* must reject this add if the key is the same as the one we are * supplied with. */ if (table->allowDups == ANTLR3_FALSE) { if ((*newPointer)->keybase.key.iKey == key) { 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 pointing 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->keybase.type = ANTLR3_HASH_TYPE_INT; /* Indicate the key type stored here for when we free */ entry->keybase.key.iKey = 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;}/** 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 (ANTLR3_CDECL *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)->keybase.key.sKey) == 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->keybase.type = ANTLR3_HASH_TYPE_STR; /* Indicate the key type stored here for free() */ entry->keybase.key.sKey = 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;}/** \brief Creates an enumeration structure to traverse the hash table. * * \param table Table to enumerate * \return Pointer to enumeration structure. */pANTLR3_HASH_ENUMantlr3EnumNew (pANTLR3_HASH_TABLE table){ pANTLR3_HASH_ENUM en; /* Allocate structure memory */ en = (pANTLR3_HASH_ENUM) ANTLR3_MALLOC((size_t)sizeof(ANTLR3_HASH_ENUM)); /* Check that the allocation was good */ if (en == NULL) { return (pANTLR3_HASH_ENUM) ANTLR3_ERR_NOMEM; } /* Initialize the start pointers */ en->table = table; en->bucket = 0; /* First bucket */ en->entry = en->table->buckets->entries; /* First entry to return */ /* Special case in that the first bucket may not have anything in it * but the antlr3EnumNext() function expects that the en->entry is * set to the next valid pointer. Hence if it is not a valid element * pointer, attempt to find the next one that is, (table may be empty * of course. */ if (en->entry == NULL) { antlr3EnumNextEntry(en); } /* Install the interface */ en->free = antlr3EnumFree; en->next = antlr3EnumNext; /* All is good */ return en;}/** \brief Return the next entry in the hashtable beign traversed by the supplied * enumeration. * * \param[in] en Pointer to the enumeration tracking structure * \param key Pointer to void pointer, where the key pointer is returned. * \param data Pointer to void pointer where the data poitner is returned. * \return * - ANTLR3_SUCCESS if there was a next key * - ANTLR3_FAIL if there were no more keys * * \remark * No checking of input structure is performed! */static intantlr3EnumNext (pANTLR3_HASH_ENUM en, pANTLR3_HASH_KEY * key, void ** data){ /* If the current entry is valid, then use it */ if (en->bucket >= en->table->modulo) { /* Already exhausted the table */ return ANTLR3_FAIL; } /* Pointers are already set to the current entry to return, or * we would not be at this point in the logic flow. */ *key = &(en->entry->keybase); *data = en->entry->data; /* Return pointers are set up, so now we move the element * pointer to the next in the table (if any). */ antlr3EnumNextEntry(en); return ANTLR3_SUCCESS;}/** \brief Local function to avance the entry pointer of an enumeration * structure to the next vlaid entry (if there is one). * * \param[in] enum Pointer to ANTLR3 enumeratio structure returned by antlr3EnumNew() * * \remark * - The function always leaves the pointers pointing at a valid enrty if there * is one, so if the entry pointer is NULL when this function exits, there were * no more entries in the table. */static voidantlr3EnumNextEntry(pANTLR3_HASH_ENUM en){ pANTLR3_HASH_BUCKET bucket; /* See if the current entry pointer is valid fisrt of all */ if (en->entry != NULL) { /* Current entry was a vlaid point, see if ther eis another * one in the chain. */ if (en->entry->nextEntry != NULL) { /* Next entry in the enumeration is just the next entry * in the chain. */ en->entry = en->entry->nextEntry; return; } } /* There were no more entries in the current bucket, if there are * more buckets then chase them until we find an entry. */ en->bucket++; while (en->bucket < en->table->modulo) { /* There was one more bucket, see if it has any elements in it */ bucket = en->table->buckets + en->bucket; if (bucket->entries != NULL) { /* There was an entry in this bucket, so we can use it * for the next entry in the enumeration. */ en->entry = bucket->entries; return; } /* There was nothing in the bucket we just examined, move to the * next one. */ en->bucket++; } /* Here we have exhausted all buckets and the enumeration pointer will * have its bucket count = table->modulo whicih signifies that we are done. */}/** \brief Frees up the memory structures that represent a hash table * enumeration. * \param[in] enum Pointer to ANTLR3 enumeratio structure returned by antlr3EnumNew() */static voidantlr3EnumFree (pANTLR3_HASH_ENUM en){ /* Nothing to check, we just free it. */ ANTLR3_FREE(en);}/** Given an input key of arbitrary length, return a hash value of * it. This can then be used (with suitable modulo) to index other * structures. */ANTLR3_API ANTLR3_UINT32antlr3Hash(void * key, ANTLR3_UINT32 keylen){ /* Accumulate the hash value of the key */ ANTLR3_UINT32 hash; pANTLR3_UINT8 keyPtr; ANTLR3_UINT32 i1; hash = 0; keyPtr = (pANTLR3_UINT8) key; /* Iterate the key and accumulate the hash */ while(keylen > 0) { hash = (hash << 4) + (*(keyPtr++)); if ((i1=hash&0xf0000000) != 0) { hash = hash ^ (i1 >> 24); hash = hash ^ i1; } keylen--; } return hash;}ANTLR3_API pANTLR3_LISTantlr3ListNew (ANTLR3_UINT32 sizeHint){ pANTLR3_LIST list; /* Allocate memory */ list = (pANTLR3_LIST)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_LIST)); if (list == NULL) { return (pANTLR3_LIST)ANTLR3_ERR_NOMEM; } /* Now we need to add a new table */ list->table = antlr3HashTableNew(sizeHint); if (list->table == (pANTLR3_HASH_TABLE)ANTLR3_ERR_NOMEM) { return (pANTLR3_LIST)ANTLR3_ERR_NOMEM; } /* Allocation was good, install interface */ list->free = antlr3ListFree; list->del = antlr3ListDelete; list->get = antlr3ListGet; list->add = antlr3ListAdd; list->remove = antlr3ListRemove; list->put = antlr3ListPut; list->size = antlr3ListSize; return list;}static ANTLR3_UINT64 antlr3ListSize (pANTLR3_LIST list){ return list->table->size(list->table);}static voidantlr3ListFree (pANTLR3_LIST list){ /* Free the hashtable that stores the list */ list->table->free(list->table); /* Free the allocation for the list itself */ ANTLR3_FREE(list);}static voidantlr3ListDelete (pANTLR3_LIST list, ANTLR3_UINT64 key){ list->table->delI(list->table, key);}static void *antlr3ListGet (pANTLR3_LIST list, ANTLR3_UINT64 key){ return list->table->getI(list->table, key);}/** Add the supplied element to the list, at the next available key */static ANTLR3_INT32 antlr3ListAdd (pANTLR3_LIST list, void * element, void (ANTLR3_CDECL *freeptr)(void *)){ ANTLR3_UINT64 key; key = list->table->size(list->table) + 1; return list->put(list, key, element, freeptr);}/** Remove from the list, but don't free the element, just send it back to the * caller. */static void *antlr3ListRemove (pANTLR3_LIST list, ANTLR3_UINT64 key){ pANTLR3_HASH_ENTRY entry; entry = list->table->removeI(list->table, key); if (entry != NULL) { return entry->data; } else { return NULL; }}static ANTLR3_INT32antlr3ListPut (pANTLR3_LIST list, ANTLR3_UINT64 key, void * element, void (ANTLR3_CDECL *freeptr)(void *)){ return list->table->putI(list->table, key, element, freeptr);}ANTLR3_API pANTLR3_STACKantlr3StackNew (ANTLR3_UINT32 sizeHint){ pANTLR3_STACK stack; /* Allocate memory */ stack = (pANTLR3_STACK)ANTLR3_MALLOC((size_t)sizeof(ANTLR3_STACK)); if (stack == NULL) { return (pANTLR3_STACK)ANTLR3_ERR_NOMEM; } /* Now we need to add a new table */ stack->vector = antlr3VectorNew(sizeHint); stack->top = NULL; if (stack->vector == (pANTLR3_VECTOR)ANTLR3_ERR_NOMEM) { return (pANTLR3_STACK)ANTLR3_ERR_NOMEM; } /* Looks good, now add the interface */ stack->get = antlr3StackGet; stack->free = antlr3StackFree; stack->pop = antlr3StackPop; stack->push = antlr3StackPush; stack->size = antlr3StackSize; stack->peek = antlr3StackPeek; return stack;}static ANTLR3_UINT64 antlr3StackSize (pANTLR3_STACK stack){ return stack->vector->count;}static voidantlr3StackFree (pANTLR3_STACK stack){ /* Free the list that supports the stack */ stack->vector->free(stack->vector); stack->vector = NULL; stack->top = NULL; ANTLR3_FREE(stack);}static void *antlr3StackPop (pANTLR3_STACK stack){ stack->vector->del(stack->vector, stack->vector->count); stack->top = stack->vector->get(stack->vector, stack->vector->count); return stack->top;}static void *antlr3StackGet (pANTLR3_STACK stack, ANTLR3_UINT64 key){ return stack->vector->get(stack->vector, key);}static void *antlr3StackPeek (pANTLR3_STACK stack){ return stack->top;}static ANTLR3_BOOLEAN antlr3StackPush (pANTLR3_STACK stack, void * element, void (ANTLR3_CDECL *freeptr)(void *)){ stack->top = element; return stack->vector->add(stack->vector, element, freeptr);}ANTLR3_API pANTLR3_VECTORantlr3VectorNew (ANTLR3_UINT32 sizeHint){ ANTLR3_UINT32 initialSize; pANTLR3_VECTOR vector;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -