📄 varstore.c
字号:
/*//// varstore.c//// Variable store functions (implemented with a simple hash table)//// Copyright (c) 1995-96 Jim Nelson. Permission to distribute// granted by the author. No warranties are made on the fitness of this// source code.//*/#include "htp.h"/* statistics for performance measurement */#if DEBUGuint variableLookups = 0;uint variableCacheHits = 0;uint variableStringCompares = 0;uint variableMissedStringCompares = 0;uint variableHashCalcs = 0;#endif/* !! dont primes contribute to a more evenly distributed hash table? *//* need to check Knuth ... */#define HASH_TABLE_SIZE (53)/*// generates an index into the hash table from the string*/uint StringToHashTableIndex(const char *name){ uint hash; uint ctr; if(name == NULL) { return 0; } #if DEBUG variableHashCalcs++; #endif hash = 0; ctr = 0; while(*name != NUL) { /* uppercase the chars before hashing because names are case-insensitive */ /* shift left to give a broader distribution in the hash table */ hash += (uint) toupper(*name++) << (ctr++ & 0x03); } return (hash % HASH_TABLE_SIZE);}BOOL InitializeVariableStore(VARSTORE *varstore){ assert(varstore != NULL); /* allocate the hash table */ varstore->variableHashTable = AllocMemory(sizeof(VARIABLE *) * HASH_TABLE_SIZE); if(varstore->variableHashTable == NULL) { DEBUG_PRINT(("out of memory trying to allocate variable hash table")); return FALSE; } memset(varstore->variableHashTable, 0, sizeof(VARIABLE *) * HASH_TABLE_SIZE); /* initialize the rest of the store */ varstore->parent = NULL; varstore->child = NULL; varstore->lastVariable = NULL; return TRUE;}void DestroyVariableStore(VARSTORE *varstore){ /* destroy all children as well ... this function doesn't simply "unlink" */ /* the current store from the linked list */ while(varstore != NULL) { /* unlink from parent */ if(varstore->parent != NULL) { varstore->parent->child = NULL; varstore->parent = NULL; } /* destroy all variables in this store */ ClearVariableList(varstore); /* free the hash table memory */ FreeMemory(varstore->variableHashTable); varstore->variableHashTable = NULL; /* destroy all child scopes as well */ varstore = varstore->child; }}BOOL StoreVariable(VARSTORE *varstore, const char *name, const char *value, uint type, uint flag, void *param, VAR_DESTRUCTOR destructor){ VARIABLE *variable; VARIABLE *ptr; uint index; assert(varstore != NULL); assert(name != NULL); /* remove any variable with the same name in the store */ RemoveVariable(varstore, name); /* allocate space for the variable structure */ if((variable = AllocMemory(sizeof(VARIABLE))) == NULL) { DEBUG_PRINT(("unable to allocate memory for new variable")); return FALSE; } /* copy in the variable's name */ StringCopy(variable->name, name, MAX_VARNAME_LEN); /* copy in the variable's value, if any */ if(value != NULL) { StringCopy(variable->value, value, MAX_VARVALUE_LEN); } /* set flags and destructor pointer */ variable->type = type; variable->flag = flag; variable->param = param; variable->destructor = destructor; variable->next = NULL; /* insert into the hash table */ index = StringToHashTableIndex(name); ptr = varstore->variableHashTable[index]; varstore->variableHashTable[index] = variable; if(ptr != NULL) { /* the slot has been previously hashed to a different variable, */ /* inserted new item at beginning of list, add rest to end */ variable->next = ptr; } /* put this new variable into the last-used cache */ varstore->lastVariable = variable; return TRUE;} static VARIABLE *FindVariable(VARSTORE *varstore, const char *name){ VARIABLE *ptr; assert(varstore != NULL); assert(name != NULL); #if DEBUG variableLookups++; #endif /* check the last referenced variable first */ if(varstore->lastVariable != NULL) { #if DEBUG variableStringCompares++; #endif if(stricmp(varstore->lastVariable->name, name) == 0) { #if DEBUG variableCacheHits++; #endif return varstore->lastVariable; } #if DEBUG variableMissedStringCompares++; #endif } ptr = varstore->variableHashTable[StringToHashTableIndex(name)]; while(ptr != NULL) { #if DEBUG variableStringCompares++; #endif if(stricmp(ptr->name, name) == 0) { /* cache this variable for next time */ varstore->lastVariable = ptr; return ptr; } #if DEBUG variableMissedStringCompares++; #endif ptr = ptr->next; } /* check all parent stores as well */ if(varstore->parent != NULL) { return FindVariable(varstore->parent, name); } return NULL;} const char *GetVariableValue(VARSTORE *varstore, const char *name){ VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->value; } } return NULL;} uint GetVariableType(VARSTORE *varstore, const char *name){ VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->type; } } return VAR_TYPE_UNKNOWN;}uint GetVariableFlag(VARSTORE *varstore, const char *name){ VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->flag; } } return VAR_FLAG_UNKNOWN;} static void DestroyVariable(VARSTORE *varstore, VARIABLE *variable){ /* if the variable has a destructor callback, do it */ if(variable->destructor != NULL) { variable->destructor(variable->name, variable->value, variable->type, variable->flag, variable->param); } /* if this is the last referenced variable, uncache it */ if(varstore->lastVariable == variable) { varstore->lastVariable = NULL; } /* free the structure */ FreeMemory(variable);}void ClearVariableList(VARSTORE *varstore){ VARIABLE *ptr; VARIABLE *next; uint ctr; assert(varstore != NULL); /* have to walk the entire hash table to destroy each item */ for(ctr = 0; ctr < HASH_TABLE_SIZE; ctr++) { ptr = varstore->variableHashTable[ctr]; while(ptr != NULL) { next = ptr->next; DestroyVariable(varstore, ptr); ptr = next; } varstore->variableHashTable[ctr] = NULL; }} BOOL RemoveVariable(VARSTORE *varstore, const char *name){ VARIABLE *ptr; VARIABLE *prev; uint index; assert(varstore != NULL); if(name == NULL) { return FALSE; } index = StringToHashTableIndex(name); prev = NULL; ptr = varstore->variableHashTable[index]; while(ptr != NULL) { #if DEBUG variableStringCompares++; #endif if(stricmp(ptr->name, name) == 0) { /* found the variable */ /* unlink from the list */ if(prev != NULL) { prev->next = ptr->next; } else { varstore->variableHashTable[index] = ptr->next; } /* destroy the variable structure */ DestroyVariable(varstore, ptr); return TRUE; } prev = ptr; ptr = ptr->next; } return FALSE;}BOOL VariableExists(VARSTORE *varstore, const char *name){ return (FindVariable(varstore, name) != NULL) ? TRUE : FALSE;}void *GetVariableParam(VARSTORE *varstore, const char *name){ VARIABLE *var; if(name != NULL) { if((var = FindVariable(varstore, name)) != NULL) { return var->param; } } return NULL;}static VARSTORE *FindTopmostContext(VARSTORE *varstore){ VARSTORE *ptr; assert(varstore != NULL); ptr = varstore; while(ptr->child != NULL) { assert(ptr->child->parent == ptr); ptr = ptr->child; } return ptr;}void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore){ VARSTORE *ptr; assert(parent != NULL); assert(varstore != NULL); assert(varstore->parent == NULL); ptr = FindTopmostContext(parent); ptr->child = varstore; varstore->parent = ptr; varstore->child = NULL;}VARSTORE *PopVariableStoreContext(VARSTORE *varstore){ VARSTORE *ptr; assert(varstore != NULL); ptr = FindTopmostContext(varstore); /* unlink from parent and return current context */ ptr->parent->child = NULL; ptr->parent = NULL; return ptr;}VARSTORE *PeekVariableStoreContext(VARSTORE *varstore){ return FindTopmostContext(varstore);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -