00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <Basics.H>
00025 #include <Generics.H>
00026 #include <SRPC.H>
00027 #include "TextIO.H"
00028 #include "FV2.H"
00029 #include "PrefixTbl.H"
00030
00031 #include <iomanip>
00032
00033 using std::ostream;
00034 using std::istream;
00035 using std::setw;
00036 using std::endl;
00037
00038
00039 static const int ArcCountHint = 4;
00040
00041 PrefixTbl::PrefixTbl(int szHint) throw ()
00042 : numArcs(0), maxArcs(szHint)
00043 {
00044 if (szHint > 0) {
00045 this->indexArray = NEW_PTRFREE_ARRAY(Basics::uint16, szHint);
00046 this->arcArray = NEW_ARRAY(Text, szHint);
00047 } else {
00048 this->indexArray = (Basics::uint16 *)NULL;
00049 this->arcArray = (Text *)NULL;
00050 }
00051 }
00052
00053 int PrefixTbl::AddArc(const Text& arc) throw (PrefixTbl::Overflow)
00054 {
00055 int res = this->numArcs;
00056 if (this->numArcs >= this->maxArcs) {
00057
00058
00059
00060
00061 Basics::uint16 size_increment = max(this->maxArcs, 2);
00062 Basics::uint16 new_max;
00063 while(((new_max = (this->maxArcs + size_increment)) <= this->maxArcs) &&
00064 (size_increment > 0))
00065 {
00066 size_increment >>= 1;
00067 }
00068
00069
00070 if(size_increment == 0)
00071 {
00072 throw PrefixTbl::Overflow(this->numArcs);
00073 }
00074 this->maxArcs = new_max;
00075 assert(this->maxArcs > this->numArcs);
00076 Basics::uint16 *newIndexArray =
00077 NEW_PTRFREE_ARRAY(Basics::uint16, this->maxArcs);
00078 Text *newArcArray = NEW_ARRAY(Text, this->maxArcs);
00079 for (int i = 0; i < this->numArcs; i++) {
00080 newIndexArray[i] = this->indexArray[i];
00081 newArcArray[i] = this->arcArray[i];
00082 }
00083 this->indexArray = newIndexArray;
00084 this->arcArray = newArcArray;
00085 }
00086 this->arcArray[this->numArcs++] = arc;
00087 return res;
00088 }
00089
00090 int PrefixTbl::Put(const char *path, TextIntTbl &tbl) throw (PrefixTbl::Overflow)
00091 {
00092 int resIdx;
00093 if (!tbl.Get(Text(path, (void*)1), resIdx)) {
00094
00095 const int BuffSz = 100;
00096 char buff[BuffSz + 1];
00097
00098
00099 int pathLen = strlen(path);
00100 char *str = (pathLen <= BuffSz)
00101 ? buff
00102 : (NEW_PTRFREE_ARRAY(char, pathLen + 1));
00103 memcpy(str, path, pathLen + 1);
00104
00105 char *curr = str + (pathLen - 1);
00106 while (curr >= str && *curr != '/') curr--;
00107 resIdx = this->AddArc(Text(curr + 1));
00108 bool inTbl = tbl.Put(Text(str), resIdx); assert(!inTbl);
00109 int lastIdx = resIdx;
00110 while (curr >= str) {
00111 assert(*curr == '/');
00112 *curr = '\0';
00113 int currIdx;
00114 if (tbl.Get(Text(str, (void*)1), currIdx)) {
00115 this->indexArray[lastIdx] = currIdx;
00116 return resIdx;
00117 } else {
00118 while (--curr >= str && *curr != '/') ;
00119 currIdx = this->AddArc(Text(curr + 1));
00120 inTbl = tbl.Put(Text(str), currIdx); assert(!inTbl);
00121 this->indexArray[lastIdx] = currIdx;
00122 lastIdx = currIdx;
00123 }
00124 }
00125 this->indexArray[lastIdx] = PrefixTbl::endMarker;
00126 }
00127 return resIdx;
00128 }
00129
00130 int PrefixTbl::Put(const FV2::T& ts, TextIntTbl &tbl) throw (PrefixTbl::Overflow)
00131 {
00132 int arcIdx = ts.size() - 1;
00133 if (arcIdx < 0) return -1;
00134
00135 int resIdx;
00136 char *str = ts.ToText().chars();
00137 int strPos = (int) strlen(str);
00138 if (!tbl.Get(Text(str, (void*)1), resIdx)) {
00139 resIdx = this->AddArc(ts.get(arcIdx));
00140 bool inTbl = tbl.Put(Text(str), resIdx); assert(!inTbl);
00141 int lastIdx = resIdx;
00142 while (arcIdx-- > 0) {
00143 while (str[--strPos] != '/') ;
00144 str[strPos] = '\0';
00145 int currIdx;
00146 if (tbl.Get(Text(str, (void*)1), currIdx)) {
00147 this->indexArray[lastIdx] = currIdx;
00148 return resIdx;
00149 } else {
00150 currIdx = this->AddArc(ts.get(arcIdx));
00151 inTbl = tbl.Put(Text(str), currIdx); assert(!inTbl);
00152 this->indexArray[lastIdx] = currIdx;
00153 lastIdx = currIdx;
00154 }
00155 }
00156 this->indexArray[lastIdx] = PrefixTbl::endMarker;
00157 }
00158 return resIdx;
00159 }
00160
00161 FV2::T *PrefixTbl::Get(int idx) const throw ()
00162 {
00163 FV2::T *path = NEW_CONSTR(FV2::T, (ArcCountHint));
00164 register int index = idx;
00165 while ((index != PrefixTbl::endMarker) &&
00166 (index != -1)) {
00167 assert(0 <= index && index < this->numArcs);
00168 path->addlo(this->arcArray[index]);
00169 index = this->indexArray[index];
00170 }
00171 return path;
00172 }
00173
00174 bool PrefixTbl::GetString(int idx, char *buff, int buff_len) const throw ()
00175
00176
00177
00178 {
00179
00180 const int InitBuffSz = 20;
00181 int indexBuff[InitBuffSz];
00182 int buffSz = InitBuffSz;
00183 int *indexList = indexBuff;
00184 register int num_arcs = 0;
00185 register int index = idx;
00186 while ((index != PrefixTbl::endMarker) &&
00187 (index != -1)) {
00188 if (num_arcs >= buffSz) {
00189
00190 buffSz <<= 1;
00191 int *newList = NEW_PTRFREE_ARRAY(int, buffSz);
00192 for (int i = 0; i < num_arcs; i++) {
00193 newList[i] = indexList[i];
00194 }
00195 indexList = newList;
00196 }
00197 indexList[num_arcs++] = index;
00198 index = this->indexArray[index];
00199 }
00200
00201
00202 register char *curr = buff;
00203 buff_len--;
00204 while (--num_arcs >= 0) {
00205 index = indexList[num_arcs];
00206 assert(0 <= index && index < this->numArcs);
00207 Text *txt = &(this->arcArray[index]);
00208 int arcLen = txt->Length();
00209 if (arcLen > buff_len) return false;
00210 (void) memcpy(curr, txt->cchars(), arcLen);
00211 curr += arcLen;
00212 *curr++ = '/';
00213 buff_len -= (arcLen + 1);
00214 }
00215
00216
00217 *(curr - 1) = '\0';
00218 return true;
00219 }
00220
00221 int PrefixTbl::MemorySize() const throw ()
00222 {
00223 register int res = sizeof(this->numArcs) + sizeof(this->maxArcs);
00224 if (this->indexArray != (Basics::uint16 *)NULL) {
00225 res += this->maxArcs * sizeof(this->indexArray[0]);
00226 res += this->maxArcs * sizeof(this->arcArray[0]);
00227 }
00228 for (int i = 0; i < this->numArcs; i++) {
00229 res += this->arcArray[i].Length() + 1;
00230 }
00231 return res;
00232 }
00233
00234 int PrefixTbl::Skip(istream &ifs) throw (FS::EndOfFile, FS::Failure)
00235 {
00236 int res = 0;
00237 Basics::uint16 numArcs;
00238 FS::Read(ifs, (char *)(&numArcs), sizeof(numArcs));
00239 res += sizeof(numArcs);
00240 if (numArcs > 0) {
00241 for (int i = 0; i < numArcs; i++) {
00242 Basics::uint16 idx; FS::Read(ifs, (char *)(&idx), sizeof(idx));
00243 res += sizeof(idx);
00244 res += TextIO::Skip(ifs);
00245 }
00246 }
00247 return res;
00248 }
00249
00250 void PrefixTbl::Write(ostream &ofs) const throw (FS::Failure)
00251 {
00252 FS::Write(ofs, (char *)(&(this->numArcs)), sizeof(this->numArcs));
00253 if (this->numArcs > 0) {
00254 for (int i = 0; i < this->numArcs; i++) {
00255 Basics::uint16 *idx = &(this->indexArray[i]);
00256 FS::Write(ofs, (char *)(idx), sizeof(*idx));
00257 TextIO::Write(ofs, this->arcArray[i]);
00258 }
00259 }
00260 }
00261
00262 void PrefixTbl::Read(istream &ifs) throw (FS::EndOfFile, FS::Failure)
00263 {
00264 FS::Read(ifs, (char *)(&(this->numArcs)), sizeof(this->numArcs));
00265 this->maxArcs = this->numArcs;
00266 if (this->numArcs > 0) {
00267 this->indexArray = NEW_PTRFREE_ARRAY(Basics::uint16, this->numArcs);
00268 this->arcArray = NEW_ARRAY(Text, this->numArcs);
00269 for (int i = 0; i < this->numArcs; i++) {
00270 Basics::uint16 *idx = &(this->indexArray[i]);
00271 FS::Read(ifs, (char *)(idx), sizeof(*idx));
00272 TextIO::Read(ifs, this->arcArray[i]);
00273 }
00274 } else {
00275 this->indexArray = (Basics::uint16 *)NULL;
00276 this->arcArray = (Text *)NULL;
00277 }
00278 }
00279
00280 void PrefixTbl::Log(VestaLog &log) const throw (VestaLog::Error)
00281 {
00282 log.write((char *)(&(this->numArcs)), sizeof(this->numArcs));
00283 if (this->numArcs > 0) {
00284 for (int i = 0; i < this->numArcs; i++) {
00285 Basics::uint16 *idx = &(this->indexArray[i]);
00286 log.write((char *)(idx), sizeof(*idx));
00287 TextIO::Log(log, this->arcArray[i]);
00288 }
00289 }
00290 }
00291
00292 void PrefixTbl::Recover(RecoveryReader &rd)
00293 throw (VestaLog::Error, VestaLog::Eof)
00294 {
00295 rd.readAll((char *)(&(this->numArcs)), sizeof(this->numArcs));
00296 this->maxArcs = this->numArcs;
00297 if (this->numArcs > 0) {
00298 this->indexArray =
00299 NEW_PTRFREE_ARRAY(Basics::uint16, this->numArcs);
00300 this->arcArray = NEW_ARRAY(Text, this->numArcs);
00301 for (int i = 0; i < this->numArcs; i++) {
00302 Basics::uint16 *idx = &(this->indexArray[i]);
00303 rd.readAll((char *)(idx), sizeof(*idx));
00304 TextIO::Recover(rd, this->arcArray[i]);
00305 }
00306 } else {
00307 this->indexArray = (Basics::uint16 *)NULL;
00308 this->arcArray = (Text *)NULL;
00309 }
00310 }
00311
00312 void PrefixTbl::Send(SRPC &srpc) const throw (SRPC::failure)
00313 {
00314 srpc.send_int((int)(this->numArcs));
00315 if (this->numArcs > 0) {
00316 srpc.send_short_array((Basics::int16 *) this->indexArray,
00317 this->numArcs);
00318 for (int i = 0; i < this->numArcs; i++) {
00319 srpc.send_Text(this->arcArray[i]);
00320 }
00321 }
00322 }
00323
00324 void PrefixTbl::Recv(SRPC &srpc) throw (SRPC::failure)
00325 {
00326 this->numArcs = (Basics::uint16) srpc.recv_int();
00327 this->maxArcs = this->numArcs;
00328 if (this->numArcs > 0) {
00329 int dummyLen = 0;
00330 this->indexArray =
00331 (Basics::uint16 *) srpc.recv_short_array( dummyLen);
00332 assert(dummyLen == this->numArcs);
00333 this->arcArray = NEW_ARRAY(Text, this->numArcs);
00334 for (int i = 0; i < this->numArcs; i++) {
00335 srpc.recv_Text( this->arcArray[i]);
00336 }
00337 } else {
00338 this->indexArray = (Basics::uint16 *)NULL;
00339 this->arcArray = (Text *)NULL;
00340 }
00341 }
00342
00343 inline void Indent(ostream &os, int indent) throw ()
00344 {
00345 for (int i = 0; i < indent; i++) os << " ";
00346 }
00347
00348 void PrefixTbl::Print(ostream &os, int indent) const throw ()
00349 {
00350 Indent(os, indent); os << "Index Prefix Arc" << endl;
00351 for (int i = 0; i < this->numArcs; i++) {
00352 Indent(os, indent);
00353 os << setw(4) << i;
00354 os << setw(7);
00355 if(this->indexArray[i] == PrefixTbl::endMarker)
00356 {
00357 os << "<END>";
00358 }
00359 else
00360 {
00361 os << this->indexArray[i];
00362 }
00363 os << " ";
00364 os << this->arcArray[i] << endl;
00365 }
00366 }