Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

PrefixTbl.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Fri Apr 22 18:24:53 EDT 2005 by ken@xorian.net         
00020 //      modified on Sat Feb 12 12:02:12 PST 2000 by mann  
00021 //      modified on Wed May 13 16:29:15 PDT 1998 by heydon
00022 //      modified on Wed Mar 18 12:08:30 PST 1998 by yuanyu
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 // Expected number of arcs in an FV2::T
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         // Algorithm for picking our new size without overflowing:
00058         // Double if possible.  Otherwise increse by 1/2, or 1/4, or
00059         // 1/8th...  If we can't increase without overflowing, we'll
00060         // die with an assertion failure.
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         // If we couldn't increase our size without overflowing, throw
00069         // an exception.
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 /*INOUT*/ &tbl) throw (PrefixTbl::Overflow)
00091 {
00092     int resIdx;
00093     if (!tbl.Get(Text(path, /*copy=*/ (void*)1), /*OUT*/ resIdx)) {
00094         // local buffer so allocation can be avoided in most cases
00095         const int BuffSz = 100;
00096         char buff[BuffSz + 1];
00097 
00098         // make a mutable copy of "path" in "str"
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);    // copy '\0' too
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, /*copy=*/ (void*)1), /*OUT*/ currIdx)) {
00115                 this->indexArray[lastIdx] = currIdx;
00116                 return resIdx;
00117             } else {
00118                 while (--curr >= str && *curr != '/') /*SKIP*/;
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 /*INOUT*/ &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, /*copy=*/ (void*)1), /*OUT*/ 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] != '/') /*SKIP*/;
00144             str[strPos] = '\0';
00145             int currIdx;
00146             if (tbl.Get(Text(str, /*copy=*/ (void*)1), /*OUT*/ 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 /* This method constructs the string "backwards", starting at the end of the
00176    buffer and prepending arcs (just as the "Get" method above uses "addlo" to 
00177    prepend each arc). */
00178 {
00179     // first, build list of arc indices
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             // slow path -- copy to dynamically-allocated buffer
00190             buffSz <<= 1; // double buffer size
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     // second, write arcs into "buff"
00202     register char *curr = buff;
00203     buff_len--; // subtract one for required null terminator
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; // not enough space
00210         (void) memcpy(curr, txt->cchars(), arcLen);
00211         curr += arcLen;
00212         *curr++ = '/';
00213         buff_len -= (arcLen + 1);
00214     }
00215 
00216     // replace final '/' by null and return
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, /*OUT*/ 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, /*OUT*/ 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(/*OUT*/ 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(/*OUT*/ 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 }

Generated on Mon May 8 00:48:32 2006 for Vesta by  doxygen 1.4.2