00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <Basics.H>
00020 #include <FS.H>
00021 #include <FP.H>
00022
00023 #include "SPKFileRep.H"
00024 #include "SPKFile.H"
00025 #include "SMultiPKFileRep.H"
00026
00027 using std::ostream;
00028 using std::ifstream;
00029 using std::endl;
00030
00031
00032
00033 void SMultiPKFileRep::HeaderEntry::Read(ifstream &ifs)
00034 throw (FS::EndOfFile, FS::Failure)
00035
00036 {
00037 FS::Read(ifs, (char *)(&(this->pk)), sizeof(this->pk));
00038 this->offsetLoc = FS::Posn(ifs);
00039 FS::Read(ifs, (char *)(&(this->offset)), sizeof(this->offset));
00040 }
00041
00042 void SMultiPKFileRep::HeaderEntry::Write(ostream &ofs)
00043 throw (FS::Failure)
00044
00045 {
00046 FS::Write(ofs, (char *)(&(this->pk)), sizeof(this->pk));
00047 this->offsetLoc = FS::Posn(ofs);
00048 FS::Write(ofs, (char *)(&(this->offset)), sizeof(this->offset));
00049 }
00050
00051 void SMultiPKFileRep::HeaderEntry::Debug(ostream &os, bool verbose) const
00052 throw ()
00053 {
00054 if (!verbose) {
00055 os << "pk = " << pk << ", offset = " << offset << endl;
00056 } else {
00057 os << endl;
00058 os << "// <HeaderEntry>" << endl;
00059 os << "pk = " << pk << endl;
00060 os << "offset = " << offset << endl;
00061 os << "offsetLoc = " << offsetLoc << endl;
00062 os << "pkLen = " << pkLen << endl;
00063 }
00064 }
00065
00066
00067
00068 bool SMultiPKFileRep::Header::AppendNewHeaderEntry(const FP::Tag &pk) throw ()
00069 {
00070 bool res;
00071 HeaderEntry *he;
00072 if (!(res=this->pkTbl.Get(pk, he))) {
00073 he = NEW_CONSTR(HeaderEntry, (pk));
00074 bool inTbl = this->pkTbl.Put(pk, he); assert(!inTbl);
00075 if (this->num >= this->pksLen) {
00076 assert(this->num == this->pksLen);
00077
00078 this->pksLen = max(this->pksLen + 2, 2 * this->pksLen);
00079 assert(this->pksLen > this->num);
00080 FPTagPtr *newPKs = NEW_ARRAY(FPTagPtr, this->pksLen);
00081 for (int i=0; i < this->num; i++) newPKs[i] = this->pkSeq[i];
00082 this->pkSeq = newPKs;
00083 }
00084 this->pkSeq[this->num++] = &(he->pk);
00085 }
00086 return res;
00087 }
00088
00089 void SMultiPKFileRep::Header::RemoveHeaderEntry(const FP::Tag &pk) throw ()
00090 {
00091
00092 int i;
00093 for (i = 0; i < num; i++) {
00094 if (*pkSeq[i] == pk) break;
00095 }
00096 assert(i < num);
00097
00098
00099 for (; i < num-1; i++) {
00100 pkSeq[i] = pkSeq[i+1];
00101 }
00102
00103
00104 pkSeq[--num] = (FP::Tag *)NULL;
00105 }
00106
00107
00108 static const Word MPKFileMagicNumber =
00109 FP::Tag("SMultiPKFileRep magic number - CAH").Hash();
00110
00111 void SMultiPKFileRep::Header::Read(ifstream &ifs)
00112 throw (SMultiPKFileRep::BadMPKFile, FS::EndOfFile, FS::Failure)
00113
00114 {
00115
00116 FS::Read(ifs, (char *)(&(this->version)), sizeof(this->version));
00117 if (this->version < SPKFileRep::FirstVersion ||
00118 this->version > SPKFileRep::LastVersion) {
00119 throw SMultiPKFileRep::BadMPKFile();
00120 }
00121 if (this->version >= SPKFileRep::MPKMagicNumVersion) {
00122 Word magicNumber;
00123 FS::Read(ifs, (char *)(&magicNumber), sizeof(magicNumber));
00124 if (magicNumber != MPKFileMagicNumber) {
00125 throw SMultiPKFileRep::BadMPKFile();
00126 }
00127 }
00128 FS::Read(ifs, (char *)(&(this->num)), sizeof(this->num));
00129 this->lenOffset = FS::Posn(ifs);
00130 FS::Read(ifs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00131 FS::Read(ifs, (char *)(&(this->type)), sizeof(this->type));
00132 }
00133
00134 void SMultiPKFileRep::Header::Write(ostream &ofs) throw (FS::Failure)
00135
00136 {
00137
00138 if (this->num < 8) {
00139 this->type = HT_List;
00140 } else {
00141 this->type = HT_SortedList;
00142 }
00143
00144
00145 this->version = SPKFileRep::LastVersion;
00146
00147
00148 FS::Write(ofs, (char *)(&(this->version)), sizeof(this->version));
00149 if (this->version >= SPKFileRep::MPKMagicNumVersion) {
00150 FS::Write(ofs, (char *)(&MPKFileMagicNumber),
00151 sizeof(MPKFileMagicNumber));
00152 }
00153 FS::Write(ofs, (char *)(&(this->num)), sizeof(this->num));
00154 this->lenOffset = FS::Posn(ofs);
00155
00156 FS::Write(ofs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00157 FS::Write(ofs, (char *)(&(this->type)), sizeof(this->type));
00158 }
00159
00160 void SMultiPKFileRep::Header::ReadEntries(ifstream &ifs)
00161 throw (FS::EndOfFile, FS::Failure)
00162
00163 {
00164
00165 switch (this->type) {
00166 case HT_List:
00167 case HT_SortedList:
00168 if (this->version <= SPKFileRep::SourceFuncVersion) {
00169 ReadListV1(ifs);
00170 } else {
00171
00172 assert(false);
00173 }
00174 break;
00175 case HT_HashTable:
00176
00177 assert(false);
00178 default:
00179
00180 assert(false);
00181 }
00182 }
00183
00184 void SMultiPKFileRep::Header::WriteEntries(ostream &ofs) throw (FS::Failure)
00185
00186 {
00187 switch (this->type) {
00188 case HT_List:
00189 WriteList(ofs);
00190 break;
00191 case HT_SortedList:
00192 WriteSortedList(ofs);
00193 break;
00194 case HT_HashTable:
00195
00196 assert(false);
00197 default:
00198 assert(false);
00199 }
00200 }
00201
00202 void SMultiPKFileRep::Header::ReadListV1(ifstream &ifs)
00203 throw (FS::EndOfFile, FS::Failure)
00204
00205 {
00206 HeaderEntry *prev = (HeaderEntry *)NULL;
00207
00208
00209 this->pksLen = this->num;
00210 this->pkSeq = NEW_ARRAY(FPTagPtr, this->pksLen);
00211
00212
00213 for (int i = 0; i < this->num; i++) {
00214 HeaderEntry *ent = NEW_CONSTR(HeaderEntry, (ifs));
00215 this->pkSeq[i] = &(ent->pk);
00216 if (prev != NULL) {
00217 prev->pkLen = ent->offset - prev->offset;
00218 }
00219 bool inMap = this->pkTbl.Put(ent->pk, ent); assert(!inMap);
00220 prev = ent;
00221 }
00222
00223
00224 if (prev != NULL) {
00225 prev->pkLen = this->totalLen - prev->offset;
00226 }
00227 }
00228
00229 void SMultiPKFileRep::Header::WriteList(ostream &ofs) throw (FS::Failure)
00230
00231 {
00232
00233 for (int i = 0; i < this->num; i++) {
00234 HeaderEntry *ent;
00235 bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), ent);
00236 assert(inTbl);
00237 ent->Write(ofs);
00238 }
00239 }
00240
00241 extern "C"
00242 {
00243 static int SMultiPKFileRep_PKCompare(const void *p1, const void *p2) throw ()
00244 {
00245 FP::Tag *fpPtr1 = *((FP::Tag **)p1);
00246 FP::Tag *fpPtr2 = *((FP::Tag **)p2);
00247 return Compare(*fpPtr1, *fpPtr2);
00248 }
00249 }
00250
00251 void SMultiPKFileRep::Header::WriteSortedList(ostream &ofs)
00252 throw (FS::Failure)
00253
00254 {
00255
00256 qsort((void *)(this->pkSeq), (size_t)(this->num),
00257 (size_t)sizeof(*(this->pkSeq)), SMultiPKFileRep_PKCompare);
00258
00259
00260 WriteList(ofs);
00261 }
00262
00263 void SMultiPKFileRep::Header::ReadPKFiles(ifstream &ifs)
00264 throw (FS::EndOfFile, FS::Failure)
00265
00266 {
00267
00268 for (int i = 0; i < this->num; i++) {
00269 HeaderEntry *ent;
00270 bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), ent); assert(inTbl);
00271 ent->pkfile = NEW_CONSTR(SPKFile,
00272 (ent->pk, ifs, ent->offset,
00273 this->version, ent->pkhdr,
00274 true));
00275 }
00276 }
00277
00278 void SMultiPKFileRep::Header::BackPatch(ostream &ofs)
00279 throw (FS::Failure)
00280 {
00281
00282 totalLen = FS::Posn(ofs);
00283
00284
00285 FS::Seek(ofs, lenOffset);
00286 FS::Write(ofs, (char *)(&(this->totalLen)), sizeof(this->totalLen));
00287
00288
00289 for (int i = 0; i < this->num; i++) {
00290 HeaderEntry *ent;
00291 bool inTbl = this->pkTbl.Get(*(this->pkSeq[i]), ent); assert(inTbl);
00292 FS::Seek(ofs, ent->offsetLoc);
00293 FS::Write(ofs, (char *)(&(ent->offset)), sizeof(ent->offset));
00294 }
00295 }
00296
00297 static const char *HeaderTypeName[SMultiPKFileRep::HT_Last] =
00298 { "List", "SortedList", "HashTable" };
00299
00300 void SMultiPKFileRep::Header::Debug(ostream &os, bool verbose) const throw ()
00301 {
00302
00303 if (!verbose) {
00304 os << endl << "num = " << num << endl;
00305 } else {
00306 os << endl << "// <Header>" << endl;
00307 os << "version = " << version << endl;
00308 os << "num = " << num << endl;
00309 os << "totalLen = " << totalLen << endl;
00310 assert( type < HT_Last);
00311 os << "type = " << HeaderTypeName[type] << endl;
00312 os << "lenOffset = " << lenOffset << endl;
00313 }
00314
00315
00316 for (int i = 0; i < num; i++) {
00317 HeaderEntry *he;
00318 bool inTbl = pkTbl.Get(*(pkSeq[i]), he);
00319 assert(inTbl);
00320 he->Debug(os, verbose);
00321 }
00322 }