static ANODE* find_by_sval( ARRAY A , STRING *sval , int create_flag , int *redo ) { unsigned hval = ahash(sval) ; char *str = sval->str ; DUAL_LINK *table ; unsigned indx ; ANODE *p ; /* walks list */ ANODE *q = (ANODE*) 0 ; /* trails p */ if (! (A->type & AY_STR)) add_string_associations(A) ; table = (DUAL_LINK*) A->ptr ; indx = hval & A->hmask ; p = table[indx].slink ; *redo = 0 ; while(1) { if (!p) { if (create_flag) { { p = ZMALLOC(ANODE) ; p->sval = sval ; sval->ref_cnt++ ; p->ival = NOT_AN_IVALUE ; p->hval = hval ; p->cell.type = C_NOINIT ; if (++A->size > A->limit) { double_the_hash_table(A) ; /* changes table, may change index */ table = (DUAL_LINK*) A->ptr ; indx = hval & A->hmask ; *redo = 1 ; } } break ; } return (ANODE*) 0 ; } else if (p->hval == hval) { if (strcmp(p->sval->str,str) == 0 ) { /* found */ if (!q) /* already at the front */ return p ; else { /* delete for move to the front */ q->slink = p->slink ; break ; } } } q = p ; p = q->slink ; } p->slink = table[indx].slink ; table[indx].slink = p ; return p ; }
ConfigSetting* ConfigFile::GetSetting(const char* Block, const char* Setting) { uint32 block_hash = ahash(Block); uint32 setting_hash = ahash(Setting); /* find it in the big map */ map<uint32, ConfigBlock>::iterator itr = m_settings.find(block_hash); if (itr != m_settings.end()) { ConfigBlock::iterator it2 = itr->second.find(setting_hash); if (it2 != itr->second.end()) return &(it2->second); return 0; } return 0; }
static Dpage* findpage(XDStore *s, u32int addr) { uint h; Dpage *p; assert(addr%s->ds.pagesize == 0); h = ahash(addr, nelem(s->hash)); assert(h < nelem(s->hash)); //print("look for %ud on %ud\n", addr, h); for(p=s->hash[h]; p; p=p->next){ if(p->addr == addr){ p->nref++; return p; } } return nil; }
static Dpage* mkpage(XDStore *s, u32int addr) { uint h; Dpage *p; p = malloc(sizeof(Dpage)+s->ds.pagesize); if(p == nil) return nil; memset(p, 0, sizeof(Dpage)); p->a = (uchar*)&p[1]; p->nref = 1; p->addr = addr; p->s = s; h = ahash(addr, nelem(s->hash)); p->next = s->hash[h]; s->hash[h] = p; //print("mk %ud linked to %d\n", addr, h); return p; }
static void add_string_associations(ARRAY A) { if (A->type == AY_NULL) make_empty_table(A, AY_STR) ; else { DUAL_LINK *table ; int i ; /* walks table */ ANODE *p ; /* walks ilist */ char buff[256] ; if (A->type == AY_SPLIT) convert_split_array_to_table(A) ; table = (DUAL_LINK*) A->ptr ; for(i=0; (unsigned) i <= A->hmask; i++) { p = table[i].ilink ; while(p) { sprintf(buff, INT_FMT, p->ival) ; p->sval = new_STRING(buff) ; p->hval = ahash(p->sval) ; p->slink = table[A->hmask&p->hval].slink ; table[A->hmask&p->hval].slink = p ; p = p->ilink ; } } A->type |= AY_STR ; } }
bool ConfigFile::SetSource(const char* file, bool /*ignorecase*/) { /* wipe any existing settings. */ m_settings.clear(); /* open the file */ if (file != 0) { //the right mode in Windows is "rb" since '\n' is saved as 0x0D,0x0A but fopen(file,"r") reads these 2 chars //as only 1 char, so ftell(f) returns a higher value than the required by fread() to the file to buf. #ifdef WIN32 FILE* f = fopen(file, "rb"); #else FILE* f = fopen(file, "r"); #endif char* buf; int length; if (!f) { sLog.outError("Could not open %s.", file); return false; } /* get the length of the file */ fseek(f, 0, SEEK_END); length = ftell(f); buf = new char[length + 1]; fseek(f, 0, SEEK_SET); fread(buf, length, 1, f); buf[length] = '\0'; string buffer = string(buf); delete[] buf; /* close the file, it is no longer needed */ fclose(f); /* let's parse it. */ string line; string::size_type end; string::size_type offset; bool in_multiline_comment = false; bool in_multiline_quote = false; bool in_block = false; string current_setting = ""; string current_variable = ""; string current_block = ""; ConfigBlock current_block_map; ConfigSetting current_setting_struct; /* oh god this is awful */ try { for (;;) { /* grab a line. */ end = buffer.find(EOL); if (end == string::npos) { if (buffer.size() == 0) break; line = buffer; buffer.clear(); goto parse; } line = buffer.substr(0, end); buffer.erase(0, end + EOL_SIZE); goto parse; parse: if (!line.size()) continue; /* are we a comment? */ if (!in_multiline_comment && is_comment(line, &in_multiline_comment)) { /* our line is a comment. */ if (!in_multiline_comment) { /* the entire line is a comment, skip it. */ continue; } } /* handle our cases */ if (in_multiline_comment) { // we need to find a "*/". offset = line.find("*/", 0); /* skip this entire line, eh? */ if (offset == string::npos) continue; /* remove up to the end of the comment block. */ line.erase(0, offset + 2); in_multiline_comment = false; } if (in_block) { /* handle settings across multiple lines */ if (in_multiline_quote) { /* attempt to find the end of the quote block. */ offset = line.find("\""); if (offset == string::npos) { /* append the whole line to the quote. */ current_setting += line; current_setting += "\n"; continue; } /* only append part of the line to the setting. */ current_setting.append(line.c_str(), offset + 1); line.erase(0, offset + 1); /* append the setting to the config block. */ if (current_block == "" || current_variable == "") { sLog.outError("Quote without variable."); return false; } /* apply the setting */ apply_setting(current_setting, current_setting_struct); /* the setting is done, append it to the current block. */ current_block_map[ahash(current_variable)] = current_setting_struct; #ifdef _CONFIG_DEBUG sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str()); #endif /* no longer doing this setting, or in a quote. */ current_setting = ""; current_variable = ""; in_multiline_quote = false; } /* remove any leading spaces */ remove_spaces(line); if (!line.size()) continue; /* our target is a *setting*. look for an '=' sign, this is our seperator. */ offset = line.find("="); if (offset != string::npos) { ASSERT(current_variable == ""); current_variable = line.substr(0, offset); /* remove any spaces from the end of the setting */ remove_all_spaces(current_variable); /* remove the directive *and* the = from the line */ line.erase(0, offset + 1); } /* look for the opening quote. this signifies the start of a setting. */ offset = line.find("\""); if (offset != string::npos) { ASSERT(current_setting == ""); ASSERT(current_variable != ""); /* try and find the ending quote */ end = line.find("\"", offset + 1); if (end != string::npos) { /* the closing quote is on the same line, oh goody. */ current_setting = line.substr(offset + 1, end - offset - 1); /* erase up to the end */ line.erase(0, end + 1); /* apply the setting */ apply_setting(current_setting, current_setting_struct); /* the setting is done, append it to the current block. */ current_block_map[ahash(current_variable)] = current_setting_struct; #ifdef _CONFIG_DEBUG sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str()); #endif /* no longer doing this setting, or in a quote. */ current_setting = ""; current_variable = ""; in_multiline_quote = false; /* attempt to grab more settings from the same line. */ goto parse; } else { /* the closing quote is not on the same line. means we'll try and find it on the next. */ current_setting.append(line.c_str(), offset); /* skip to the next line. (after setting our condition first, of course :P */ in_multiline_quote = true; continue; } } /* are we at the end of the block yet? */ offset = line.find(">"); if (offset != string::npos) { line.erase(0, offset + 1); // freeeee! in_block = false; /* assign this block to the main "big" map. */ m_settings[ahash(current_block)] = current_block_map; /* erase all data for this so it doesn't seep through */ current_block_map.clear(); current_setting = ""; current_variable = ""; current_block = ""; } } else { /* we're not in a block. look for the start of one. */ offset = line.find("<"); if (offset != string::npos) { in_block = true; /* whee, a block! let's cut the string and re-parse. */ line.erase(0, offset + 1); /* find the name of the block first, though. */ offset = line.find(" "); if (offset != string::npos) { current_block = line.substr(0, offset); line.erase(0, offset + 1); } else { sLog.outError("Block without name."); return false; } /* skip back */ goto parse; } } } } catch (...) { sLog.outError("Exception in config parsing."); return false; } /* handle any errors */ if (in_block) { sLog.outError("Unterminated block."); return false; } if (in_multiline_comment) { sLog.outError("Unterminated comment."); return false; } if (in_multiline_quote) { sLog.outError("Unterminated quote."); return false; } /* we're all good :) */ return true; } return false; }
uint32 ahash(string & str) { return ahash(str.c_str()); }