📄 ilibparsers.c
字号:
/*! \fn ILibCreateStack(void **TheStack)
\brief Creates an empty Stack
\para
This module uses a void* that is preinitialized to NULL, eg:<br>
<i>
void *stack = NULL;<br>
ILibCreateStack(&stack);<br>
</i>
\param TheStack A void* to use for the stack. Simply pass in a void* by reference
*/
void ILibCreateStack(void **TheStack)
{
*TheStack = NULL;
}
/*! \fn ILibPushStack(void **TheStack, void *data)
\brief Push an item onto the stack
\param TheStack The stack to push to
\param data The data to push onto the stack
*/
void ILibPushStack(void **TheStack, void *data)
{
struct ILibStackNode *RetVal = (struct ILibStackNode*)malloc(sizeof(struct ILibStackNode));
RetVal->Data = data;
RetVal->Next = *TheStack;
*TheStack = RetVal;
}
/*! \fn ILibPopStack(void **TheStack)
\brief Pop an item from the stack
\param TheStack The stack to pop from
\returns The item that was popped from the stack
*/
void *ILibPopStack(void **TheStack)
{
void *RetVal = NULL;
void *Temp;
if(*TheStack!=NULL)
{
RetVal = ((struct ILibStackNode*)*TheStack)->Data;
Temp = *TheStack;
*TheStack = ((struct ILibStackNode*)*TheStack)->Next;
free(Temp);
}
return(RetVal);
}
/*! \fn ILibPeekStack(void **TheStack)
\brief Peek at an item from the stack
\param TheStack The stack to peek from
\returns The item that is currently on the top of the stack
*/
void *ILibPeekStack(void **TheStack)
{
void *RetVal = NULL;
if(*TheStack!=NULL)
{
RetVal = ((struct ILibStackNode*)*TheStack)->Data;
}
return(RetVal);
}
/*! \fn ILibClearStack(void **TheStack)
\brief Clears all the items from the stack
\param TheStack The stack to clear
*/
void ILibClearStack(void **TheStack)
{
void *Temp = *TheStack;
do
{
ILibPopStack(&Temp);
}while(Temp!=NULL);
*TheStack = NULL;
}
/*! \fn ILibHashTree_Lock(void *hashtree)
\brief Locks a HashTree
\param hashtree The HashTree to lock
*/
void ILibHashTree_Lock(void *hashtree)
{
struct HashNode_Root *r = (struct HashNode_Root*)hashtree;
sem_wait(&(r->LOCK));
}
/*! \fn ILibHashTree_UnLock(void *hashtree)
\brief Unlocks a HashTree
\param hashtree The HashTree to unlock
*/
void ILibHashTree_UnLock(void *hashtree)
{
struct HashNode_Root *r = (struct HashNode_Root*)hashtree;
sem_post(&(r->LOCK));
}
/*! \fn ILibDestroyHashTree(void *tree)
\brief Frees resources associated with a HashTree
\param hashtree The HashTree to free
*/
void ILibDestroyHashTree(void *tree)
{
struct HashNode_Root *r = (struct HashNode_Root*)tree;
struct HashNode *c = r->Root;
struct HashNode *n;
sem_destroy(&(r->LOCK));
while(c!=NULL)
{
//
// Iterate through each node, and free all the resources
//
n = c->Next;
if(c->KeyValue!=NULL) {free(c->KeyValue);}
if(c->Data!=NULL) {free(c->Data);}
free(c);
c = n;
}
free(r);
}
/*! \fn ILibHashTree_GetEnumerator(void *tree)
\brief Returns an Enumerator for a HashTree
\para
Functionally identicle to an IDictionaryEnumerator in .NET
\param tree The HashTree to get an enumerator for
\returns An enumerator
*/
void *ILibHashTree_GetEnumerator(void *tree)
{
//
// The enumerator is basically a state machine that keeps track of which node we are at
// in the tree. So initialize it to the root.
//
struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)malloc(sizeof(struct HashNodeEnumerator));
en->node = ((struct HashNode_Root*)tree)->Root;
return(en);
}
/*! \fn ILibHashTree_DestroyEnumerator(void *tree_enumerator)
\brief Frees resources associated with an Enumerator created by ILibHashTree_GetEnumerator
\param tree_enumerator The enumerator to free
*/
void ILibHashTree_DestroyEnumerator(void *tree_enumerator)
{
//
// The enumerator just contains a pointer, so we can just free the enumerator
//
free(tree_enumerator);
}
/*! \fn ILibHashTree_MoveNext(void *tree_enumerator)
\brief Advances an enumerator to the next item
\param tree_enumerator The enumerator to advance
\returns A zero value if successful, nonzero if no more items
*/
int ILibHashTree_MoveNext(void *tree_enumerator)
{
struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)tree_enumerator;
if(en->node!=NULL)
{
//
// Advance the enumerator to point to the next node. If there is a node
// return 0, else return 1
//
en->node = en->node->Next;
return(en->node!=NULL?0:1);
}
else
{
//
// There are no more nodes, so just return 1
//
return(1);
}
}
/*! \fn ILibHashTree_GetValue(void *tree_enumerator, char **key, int *keyLength, void **data)
\brief Reads from the current item of an enumerator
\param tree_enumerator The enumerator to read from
\param key The key of the current item
\param keyLength The length of the key of the current item
\param data The data of the current item
*/
void ILibHashTree_GetValue(void *tree_enumerator, char **key, int *keyLength, void **data)
{
struct HashNodeEnumerator *en = (struct HashNodeEnumerator*)tree_enumerator;
//
// All we do, is just assign the pointers.
//
if(key!=NULL){*key = en->node->KeyValue;}
if(keyLength!=NULL){*keyLength = en->node->KeyLength;}
if(data!=NULL){*data = en->node->Data;}
}
/*! \fn ILibInitHashTree()
\brief Creates an empty ILibHashTree
\returns An empty ILibHashTree
*/
void* ILibInitHashTree()
{
struct HashNode_Root *Root = (struct HashNode_Root*)malloc(sizeof(struct HashNode_Root));
struct HashNode *RetVal = (struct HashNode*)malloc(sizeof(struct HashNode));
memset(RetVal,0,sizeof(struct HashNode));
Root->Root = RetVal;
sem_init(&(Root->LOCK),0,1);
return(Root);
}
/*! \fn ILibGetHashValue(void *key, int keylength)
\brief Calculates a numeric Hash from a given string
\para
Used by ILibHashTree methods
\param key The string to hash
\param keylength The length of the string to hash
\returns A hash value
*/
int ILibGetHashValue(void *key, int keylength)
{
int HashValue=0;
char TempValue[4];
if(keylength<=4)
{
//
// If the key length is <= 4, the hash is just the key expressed as an integer
//
memset(TempValue,0,4);
memcpy(TempValue,key,keylength);
MEMCHECK(assert(keylength<=4);)
HashValue = *((int*)TempValue);
}
else
{
//
// If the key length is >4, the hash is the first 4 bytes XOR with the last 4
//
memcpy(TempValue,key,4);
HashValue = *((int*)TempValue);
memcpy(TempValue,(char*)key+(keylength-4),4);
HashValue = HashValue^(*((int*)TempValue));
//
// If the key length is >= 10, the hash is also XOR with the middle 4 bytes
//
if(keylength>=10)
{
memcpy(TempValue,(char*)key+(keylength/2),4);
HashValue = HashValue^(*((int*)TempValue));
}
}
return(HashValue);
}
//
// Determines if a key entry exists in a HashTree, and creates it if requested
//
struct HashNode* ILibFindEntry(void *hashtree, void *key, int keylength, int create)
{
struct HashNode *current = ((struct HashNode_Root*)hashtree)->Root;
int HashValue = ILibGetHashValue(key,keylength);
int done = 0;
if(keylength==0){return(NULL);}
//
// Iterate through our tree to see if we can find this key entry
//
while(done==0)
{
//
// Integer compares are very fast, this will weed out most non-matches
//
if(current->KeyHash==HashValue)
{
//
// Verify this is really a match
//
if(current->KeyLength==keylength && memcmp(current->KeyValue,key,keylength)==0)
{
return(current);
}
}
if(current->Next!=NULL)
{
current = current->Next;
}
else if(create!=0)
{
//
// If there is no match, and the create flag is set, we need to create an entry
//
current->Next = (struct HashNode*)malloc(sizeof(struct HashNode));
memset(current->Next,0,sizeof(struct HashNode));
current->Next->Prev = current;
current->Next->KeyHash = HashValue;
current->Next->KeyValue = (void*)malloc(keylength+1);
memcpy(current->Next->KeyValue,key,keylength);
current->Next->KeyValue[keylength]=0;
current->Next->KeyLength = keylength;
return(current->Next);
}
else
{
return(NULL);
}
}
return(NULL);
}
/*! \fn ILibHasEntry(void *hashtree, char* key, int keylength)
\brief Determines if a key entry exists in a HashTree
\param hashtree The HashTree to operate on
\param key The key
\param keylength The length of the key
\returns 0 if does not exist, nonzero otherwise
*/
int ILibHasEntry(void *hashtree, char* key, int keylength)
{
//
// This can be duplicated by calling Find entry, but setting the create flag to false
//
return(ILibFindEntry(hashtree,key,keylength,0)!=NULL?1:0);
}
/*! \fn ILibAddEntry(void* hashtree, char* key, int keylength, void *value, int valueLen)
\brief Adds an item to the HashTree
\param hashtree The HashTree to operate on
\param key The key
\param keylength The length of the key
\param value The data to add into the HashTree
\param valueLen The length of the value
*/
void ILibAddEntry(void* hashtree, char* key, int keylength, void *value, int valueLen)
{
//
// This can be duplicated by calling FindEntry, and setting create to true
//
struct HashNode* n = ILibFindEntry(hashtree,key,keylength,1);
n->Data = (char *)malloc(sizeof(char) * valueLen + 1);
if(n->Data)
{
strncpy(n->Data, value, valueLen);
n->Data[valueLen] = '\0';
}
}
/*! \fn ILibGetEntry(void *hashtree, char* key, int keylength)
\brief Gets an item from a HashTree
\param hashtree The HashTree to operate on
\param key The key
\param keylength The length of the key
\returns The data in the HashTree. NULL if key does not exist
*/
void* ILibGetEntry(void *hashtree, char* key, int keylength)
{
//
// This can be duplicated by calling FindEntry and setting create to false.
// If a match is found, just return the data
//
struct HashNode* n = ILibFindEntry(hashtree,key,keylength,0);
if(n==NULL)
{
return(NULL);
}
else
{
return(n->Data);
}
}
/*! \fn ILibDeleteEntry(void *hashtree, char* key, int keylength)
\brief Deletes a keyed item from the HashTree
\param hashtree The HashTree to operate on
\param key The key
\param keylength The length of the key
*/
void ILibDeleteEntry(void *hashtree, char* key, int keylength)
{
//
// First find the entry
//
struct HashNode* n = ILibFindEntry(hashtree,key,keylength,0);
if(n!=NULL)
{
//
// Then remove it from the tree
//
n->Prev->Next = n->Next;
if(n->Next!=NULL)
{
n->Next->Prev = n->Prev;
}
free(n->KeyValue);
if(n->Data)
{
free(n->Data);
}
free(n);
}
}
/*! \fn ILibGetLong(char *TestValue, int TestValueLength, long* NumericValue)
\brief Reads a long value from a string, in a validating fashion
\param TestValue The string to read from
\param TestValueLength The length of the string
\param NumericValue The long value extracted from the string
\returns 0 if succesful, nonzero if there was an error
*/
int ILibGetLong(char *TestValue, int TestValueLength, long* NumericValue)
{
char* StopString;
char* TempBuffer2 = (char*)malloc(1+sizeof(char)*19);
char* TempBuffer = (char*)malloc(1+sizeof(char)*TestValueLength);
memcpy(TempBuffer,TestValue,TestValueLength);
TempBuffer[TestValueLength] = '\0';
*NumericValue = strtol(TempBuffer,&StopString,10);
if(*StopString!='\0')
{
//
// If strtol stopped somewhere other than the end, there was an error
//
free(TempBuffer);
free(TempBuffer2);
return(-1);
}
else
{
//
// Now just check errno to see if there was an error reported
//
free(TempBuffer);
free(TempBuffer2);
if(errno!=ERANGE)
{
return(0);
}
else
{
return(-1);
}
}
}
/*! \fn ILibGetULong(char *TestValue, int TestValueLength, long* NumericValue)
\brief Reads an unsigned long value from a string, in a validating fashion
\param TestValue The string to read from
\param TestValueLength The length of the string
\param NumericValue The long value extracted from the string
\returns 0 if succesful, nonzero if there was an error
*/
int ILibGetULong(const char *TestValue, const int TestValueLength, unsigned long* NumericValue){
char* StopString;
char* TempBuffer2 = (char*)malloc(1+sizeof(char)*19);
char* TempBuffer = (char*)malloc(1+sizeof(char)*TestValueLength);
memcpy(TempBuffer,TestValue,TestValueLength);
TempBuffer[TestValueLength] = '\0';
*NumericValue = strtoul(TempBuffer,&StopString,10);
if(*StopString!='\0')
{
free(TempBuffer);
free(TempBuffer2);
return(-1);
}
else
{
free(TempBuffer);
free(TempBuffer2);
#ifdef _WIN32_WCE
// Not Supported on PPC
return(0);
#else
if(errno!=ERANGE)
{
if(memcmp(TestValue,"-",1)==0)
{
return(-1);
}
return(0);
}
else
{
return(-1);
}
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -