00001
00002 #include "idep_nameindexmap.h"
00003 #include "idep_namearray.h"
00004
00005 #include <string.h>
00006 #include <memory.h>
00007 #include <iostream>
00008 #include <cassert>
00009
00010
00011
00012 enum { DEFAULT_TABLE_SIZE = 521 };
00013 enum { BAD_INDEX = -1 };
00014
00015 static unsigned hash(register const char* name)
00016 {
00017 register unsigned sum = 1000003;
00018 while (*name) {
00019 sum *= *name++;
00020 }
00021 return sum;
00022 }
00023
00024
00025
00026 struct idep_NameIndexMapLink {
00027 const char *d_name_p;
00028 int d_index;
00029 idep_NameIndexMapLink *d_next_p;
00030
00031 idep_NameIndexMapLink(const char *name, int index,
00032 idep_NameIndexMapLink *d_next_p);
00033 };
00034
00035 idep_NameIndexMapLink::idep_NameIndexMapLink(const char *name, int index,
00036 idep_NameIndexMapLink *next)
00037 : d_name_p(name)
00038 , d_index(index)
00039 , d_next_p(next)
00040 {
00041 }
00042
00043 static const idep_NameIndexMapLink *find(const idep_NameIndexMapLink *p,
00044 const char *name)
00045 {
00046 while (p && 0 != strcmp(p->d_name_p, name)) {
00047 p = p->d_next_p;
00048 }
00049 return p;
00050 }
00051
00052
00053
00054 struct idep_NameIndexMap_i {
00055 idep_NameArray d_array;
00056 idep_NameIndexMapLink **d_table_p;
00057 int d_tableSize;
00058
00059 idep_NameIndexMap_i(int size);
00060
00061
00062 ~idep_NameIndexMap_i();
00063
00064 idep_NameIndexMapLink *& findSlot(const char *name);
00065
00066
00067 int insert(idep_NameIndexMapLink *& slot, const char *name);
00068
00069 };
00070
00071 idep_NameIndexMap_i::idep_NameIndexMap_i(int size)
00072 : d_array(size)
00073 , d_tableSize(size > 0 ? size : DEFAULT_TABLE_SIZE)
00074 {
00075 d_table_p = new idep_NameIndexMapLink *[d_tableSize];
00076 assert(d_table_p);
00077 memset(d_table_p, 0, d_tableSize * sizeof *d_table_p);
00078 }
00079
00080 idep_NameIndexMap_i::~idep_NameIndexMap_i()
00081 {
00082 for (int i = 0; i < d_tableSize; ++i) {
00083 idep_NameIndexMapLink *p = d_table_p[i];
00084 while (p) {
00085 idep_NameIndexMapLink *q = p;
00086 p = p->d_next_p;
00087 delete q;
00088 }
00089 }
00090 delete [] d_table_p;
00091 }
00092
00093 idep_NameIndexMapLink *& idep_NameIndexMap_i::findSlot(const char *name)
00094 {
00095 int index = hash(name) % d_tableSize;
00096 assert(index >= 0 && index < d_tableSize);
00097 return d_table_p[index];
00098 }
00099
00100 int idep_NameIndexMap_i::insert(idep_NameIndexMapLink *& slot, const char *nm)
00101 {
00102 int index = d_array.append(nm);
00103 slot = new idep_NameIndexMapLink(d_array[index], index, slot);
00104 return index;
00105 }
00106
00107
00108
00109 idep_NameIndexMap::idep_NameIndexMap(int maxEntriesHint)
00110 : d_this(new idep_NameIndexMap_i(maxEntriesHint))
00111 {
00112 }
00113
00114 idep_NameIndexMap::~idep_NameIndexMap()
00115 {
00116 delete d_this;
00117 }
00118
00119 int idep_NameIndexMap::add(const char* name)
00120 {
00121 idep_NameIndexMapLink *& slot = d_this->findSlot(name);
00122 return find(slot, name) ? BAD_INDEX : d_this->insert(slot, name);
00123 }
00124
00125 int idep_NameIndexMap::entry(const char* name)
00126 {
00127 idep_NameIndexMapLink *& slot = d_this->findSlot(name);
00128 const idep_NameIndexMapLink *link = find(slot, name);
00129 return link ? link->d_index : d_this->insert(slot, name);
00130 }
00131
00132 const char *idep_NameIndexMap::operator[](int i) const
00133 {
00134 return d_this->d_array[i];
00135 }
00136
00137 int idep_NameIndexMap::length() const
00138 {
00139 return d_this->d_array.length();
00140 }
00141
00142 int idep_NameIndexMap::lookup(const char *name) const
00143 {
00144 idep_NameIndexMapLink *& slot = d_this->findSlot(name);
00145 const idep_NameIndexMapLink *link = find(slot, name);
00146 return link ? link->d_index : BAD_INDEX;
00147 }
00148
00149 std::ostream& operator<<(std::ostream& out, const idep_NameIndexMap& map)
00150 {
00151 int fieldWidth = 10;
00152 int maxIndex = map.length() - 1;
00153 assert (sizeof (long int) >= 4);
00154 long int x = 1000 * 1000 * 1000;
00155 while (fieldWidth > 1 && 0 == maxIndex / x) {
00156 --fieldWidth;
00157 x /= 10;
00158 }
00159
00160 for (int i = 0; i < map.length(); ++i) {
00161 out.width(fieldWidth);
00162 out << i << ". " << map[i] << std::endl;
00163 }
00164
00165 return out;
00166 }
00167