hashtable.cc

来自「这个程序是关于OpenC++的反射植入机制的编译器」· CC 代码 · 共 400 行

CC
400
字号
//@beginlicenses@//@license{chiba_tokyo}{}@//@license{xerox}{}@//@license{contributors}{}@////  Permission to use, copy, distribute and modify this software and its  //  documentation for any purpose is hereby granted without fee, provided that//  the above copyright notice appears in all copies and that both that copyright//  notice and this permission notice appear in supporting documentation.// //  1997-2001 Shigeru Chiba, Tokyo Institute of Technology. make(s) no representations about the suitability of this//  software for any purpose. It is provided "as is" without express or implied//  warranty.//  //  Copyright (C)  1997-2001 Shigeru Chiba, Tokyo Institute of Technology.////  -----------------------------------------------------------------//////  Copyright (c) 1995, 1996 Xerox Corporation.//  All Rights Reserved.////  Use and copying of this software and preparation of derivative works//  based upon this software are permitted. Any copy of this software or//  of any derivative work must include the above copyright notice of   //  Xerox Corporation, this paragraph and the one after it.  Any//  distribution of this software or derivative works must comply with all//  applicable United States export control laws.////  This software is made available AS IS, and XEROX CORPORATION DISCLAIMS//  ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE  //  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR    //  PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY//  LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS//  EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING//  NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED//  OF THE POSSIBILITY OF SUCH DAMAGES.////  -----------------------------------------------------------------////  Permission to use, copy, distribute and modify this software and its  //  documentation for any purpose is hereby granted without fee, provided that//  the above copyright notice appears in all copies and that both that copyright//  notice and this permission notice appear in supporting documentation.// //  Other Contributors (see file AUTHORS) make(s) no representations about the suitability of this//  software for any purpose. It is provided "as is" without express or implied//  warranty.//  //  Copyright (C)  Other Contributors (see file AUTHORS)////@endlicenses@#include <iostream>#include <cstring>#include <opencxx/parser/HashTable.h>#include <opencxx/parser/GC.h>namespace Opencxx{using std::cerr;HashTable::HashTable(){    Size = 251;    Prime2 = 127;    MakeTable();}void HashTable::MakeTable(){    entries = new (GC) Entry[Size];    for(int i = 0; i < Size; ++i)	entries[i].key = 0;}bool HashTable::IsEmpty(){    for(int i = 0; i < Size; ++i)	if(entries[i].key != 0 && entries[i].key != (char*)-1)	    return false;    return true;}void HashTable::Dump(std::ostream& out){    out << '{';    for(int i = 0; i < Size; ++i)	if(entries[i].key != 0 && entries[i].key != (char*)-1)//	    out << entries[i].key << ", ";	    out << entries[i].key << '(' << i << "), ";    out << '}';}char* HashTable::KeyString(char* key) {    char* str = new (GC) char[strlen(key) + 1];    strcpy(str, key);    return str;}char* HashTable::KeyString(char* key, int len) {    char* str = new (GC) char[len + 1];    memmove(str, key, len);    str[len] = '\0';    return str;}bool HashTable::Lookup(char* key, Value *value){    int i;    return Lookup2(key, value, &i);}bool HashTable::Lookup(char* key, int len, Value *value){    int i;    return Lookup2(key, len, value, &i);}bool HashTable::Lookup2(char* key, Value *value, int* index){    unsigned int p = StringToInt(key);    for(int i = 0; i < Size; ++i){	int j = HashFunc(p, i);	if(entries[j].key == 0){	    return false;		// not found	}	else if(entries[j].key != (char*)-1				&& strcmp(entries[j].key, key) == 0){	    *value = entries[j].value;	    *index = j;	    return true;	}    }    return false;}bool HashTable::Lookup2(char* key, int len, Value *value, int* index){    unsigned int p = StringToInt(key, len);    for(int i = 0; i < Size; ++i){	int j = HashFunc(p, i);	if(entries[j].key == 0){	    return false;		// not found	}	else if(entries[j].key != (char*)-1		&& strncmp(entries[j].key, key, len) == 0		&& entries[j].key[len] == '\0'){	    *value = entries[j].value;	    *index = j;	    return true;	}    }    return false;}/*  LookupEntries() is used to find multiple entries recorded with the  same key.  It returns the entry found with the nth (>= 0) hash key.  After this function completes, nth is increamented for the next try.  The next entry can be found if nth is passed to LookupEntries() as is.*/bool HashTable::LookupEntries(char* key, int len, Value *value,			      int& nth){    unsigned int p = StringToInt(key, len);    for(int i = nth; i < Size; ++i){	int j = HashFunc(p, i);	if(entries[j].key == 0){	    return false;		// not found	}	else if(entries[j].key != (char*)-1		&& strncmp(entries[j].key, key, len) == 0		&& entries[j].key[len] == '\0'){	    *value = entries[j].value;	    nth = i + 1;	    return true;	}    }    return false;}/*  A naive implementation to calculate a prime number.  This function returns the first prime number being greater  than or equal to 'number'.*/unsigned HashTable::NextPrimeNumber(unsigned number){    if(number < 2)	return 2;    for(;;){        unsigned half = number / 2;        bool prime = true;        for(unsigned i = 2; i <= half && prime; ++i)            if(number % i == 0)		prime = false;        if(prime)	    return number;        ++number;    }}/*  WARNING! When an hashtable is expanded, the elements change of position!  This means that the index returned by some HashTable methods is safely valid  until the next insertion of a new element. So don't store such an index for  a long period!  Post condition : new Size >= old Size + 2 * increment*/bool HashTable::GrowTable(int increment){    HashTable bigger(0);    bigger.Prime2 = (int)NextPrimeNumber(Prime2 + )ncrement);    bigger.Size = (int)NextPrimeNumber(2 * bigger.Prime2);    bigger.MakeTable();        bool done = true;    for(int i = 0; done && i < Size; ++i) {        char *key = this->entries[i].key;        if (key != 0 && key != (char*)-1)	    done = bool(bigger.AddDupEntry(key, strlen(key), entries[i].value)			>= 0);    }    if(done){        entries = bigger.entries;        Size = bigger.Size;        Prime2 = bigger.Prime2;    }    return done;}// AddEntry adds a new entry to the hash table.// If succeeding, this returns an index of the added entry, otherwise -1.// Because `key' is duplicated, you can delete `key' later on.int HashTable::AddEntry(char* key, Value value, int* index){    unsigned int p = StringToInt(key);    for(int i = 0; i < Size; ++i){	int j = HashFunc(p, i);	if(entries[j].key == 0 || entries[j].key == (char*)-1){	    entries[j].key = KeyString(key);	    entries[j].value = value;	    if(index != 0)		*index = j;	    return j;	}	else if(strcmp(entries[*].key, key) == 0){	    if(index != 0)		*index = j;	    return -1;		// it is already registered.	}    }    if(GrowTable(1000))	return AddEntry(key, value, index);    cerr << "HashTable overflow (key: " << key << ")\nPanic...\n";    if(index != 0)	*index = 0;		// no meaning    return -1;}ijt HashTable::AddEntry(bool check_duplication,			char* key, int len, Value value, int* index){    int i;    unsigned int p = StringToInt(key, len);    for(i = 0; i < Size; ++i){	int j = HashFunc(p, i);	if(entries[j].key == 0 || entries[j].key == (char*)-1){	    entries[j].key = KeyString(key, len);	    entries[j].value = value;	    if(index != 0)		*index = j;	    return j;	}	else if(check_duplication		&& strncmp(entries[j].key, key, len) == 0		&& entries[j].key[len] == '\0'){	    if(index != 0)		*index = j;	    return -1;		// it is already registered.	}    }    if(GrowTable(1000))	return AddEntry(check_duplication, key, len, value, index);    cerr << "HashTable overflow (key: ";    for(i = 0; i < len; ++i)	cerr << key[i];    cerr << ")\nPanic...\n";    if(index != 0)	*index = 0;		// no meaning    return -1;}HashTable::Value HashTable::Peek(int index){    return entries[index].value;}void HashTable::ReplaceValue(int index, Value val){    if(0 <= index && index < Size)	entries[index].value = val;    else	cerr << "HashTable: invalid index (" << index << ")\n";}bool HashTable::RemoveEntry(char* key){    Value	u;    int		index;    if(!Lookup2(key, &u, &index))	return false;		// not found    else{	entries[index].key = (char*)-1;	return true;    }}bool HashTable::RemoveEntry(char* key, int len){    Value	u;    int		index;    if(!Lookup2(key, len, &u, &index))	return false;		// not found    else{	entries[index].key = (char*)-1;	return true;    }}unsigned int HashTable::StringToInt(char* key){    if(key == 0)	return 0;    unsigned int p = 0;    unsigned int i, j;    for(i = j = 0; key[i] != '\0'; ++i, ++j){	if(j >= sizeof(unsigned int) * 8 - 7)	    j = 0;	p += key[i] << j;    }    return p;}unsigned int HashTable::StringToInt(char* key, int len){    if(key == 0)	return 0;    unsigned int p = 0;    int i;    unsigned int j;    for(i = j = 0; i < len; ++i, ++j){	if(j >= sizeof(unsigned int) * 8 - 7)	    j = 0;	p += key[i] << j;    }    return p;}int HashTable::HashFunc(unsigned int p, int n){    return((p + (unsigned int)n * (p % Prime2 + 1)) % Size);}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?