/************************************************************************** * * FText.cpp -- File structures for text compression * Copyright (C) 1999 Rodger McNab * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************************/ #include "FText.h" #include "netorder.h" /* [RPAP - Jan 97: Endian Ordering] */ BitAddr::BitAddr () { Clear (); } void BitAddr::Clear () { byte = 0; bit = 0; } bool BitAddr::Read (FILE *f) { return (ReadUL (f, byte) && ReadUC (f, bit)); } bool BitAddr::Write (FILE *f) const { return (WriteUL (f, byte) && WriteUC (f, bit)); } #define BITADDRLEN (sizeof(unsigned long) + sizeof(unsigned char)) TextLevelInfo::TextLevelInfo () { Clear(); } void TextLevelInfo::Clear () { levelTag.erase (levelTag.begin(), levelTag.end()); textIdxPtr = 0; numEntries = 0; } bool TextLevelInfo::Read (FILE *f) { return (ReadUCArray (f, levelTag) && ReadUL (f, textIdxPtr) && ReadUL (f, numEntries)); } bool TextLevelInfo::Write (FILE *f) const { return (WriteUCArray (f, levelTag) && WriteUL (f, textIdxPtr) && WriteUL (f, numEntries)); } ostream &operator<<(ostream &s, const TextLevelInfo &l) { s << " Tag: \"" << l.levelTag << "\"\n" << " textIdxPtr: " << l.textIdxPtr << "\n" << " numEntries: " << l.numEntries << "\n\n"; return s; } FTextLevel::FTextLevel () { Clear(); } void FTextLevel::Clear () { levelInfo.erase (levelInfo.begin(), levelInfo.end()); } bool FTextLevel::Read (FILE *f) { // read in the array size unsigned long arrSize = 0; if (!ReadVarLenUL (f, arrSize)) return false; TextLevelInfo thisLevel; while (arrSize > 0) { // read and insert the next level information if (!thisLevel.Read (f)) return false; levelInfo[thisLevel.levelTag] = thisLevel; arrSize--; } return true; } bool FTextLevel::Write (FILE *f) const { // write out the array size if (!WriteVarLenUL (f, levelInfo.size())) return false; // write out each level info TextLevelInfoMap::const_iterator here = levelInfo.begin(); TextLevelInfoMap::const_iterator end = levelInfo.end(); while (here != end) { if (!(*here).second.Write (f)) return false; here++; } return true; } ostream &operator<<(ostream &s, const FTextLevel &l) { TextLevelInfoMap::const_iterator here = l.levelInfo.begin (); TextLevelInfoMap::const_iterator end = l.levelInfo.end (); while (here != end) { s << (*here).second; here++; } return s; } TextIdx::TextIdx () { Clear (); } void TextIdx::Clear () { start.Clear(); end.Clear(); which = 0; } #define TEXTIDXLEN (BITADDRLEN*2 + sizeof(char)) bool TextIdx::Read (FILE *f, const TextLevelInfo &levelInfo, unsigned long docNum) { if (!SeekTextIdx (f, levelInfo, docNum)) return false; return Read (f); } bool TextIdx::Read (FILE *f) { return (start.Read (f) && end.Read (f) && ReadUC (f, which)); } bool TextIdx::Write (FILE *f) const { return (start.Write (f) && end.Write (f) && WriteUC (f, which)); } ostream &operator<<(ostream &s, const TextIdx &t) { s << "start byte: " << t.start.byte << "\n"; s << "start bit: " << (int)t.start.bit << "\n"; s << "end byte: " << t.end.byte << "\n"; s << "end bit: " << (int)t.end.bit << "\n"; s << "which: " << (int)t.which << "\n\n"; return s; } bool SeekTextIdx (FILE *f, const TextLevelInfo &levelInfo, unsigned long docNum) { if (docNum == 0 || docNum > levelInfo.numEntries) return false; unsigned long seekPos = levelInfo.textIdxPtr + (docNum-1) * TEXTIDXLEN; if (fseek (f, seekPos, SEEK_SET) != 0) return false; return true; } bool ReadTextIdxArray (FILE *f, TextIdxArray &a, unsigned long arrSize) { // clear the array a.erase (a.begin(), a.end()); // read in each element TextIdx idx; while (arrSize > 0) { if (!idx.Read(f)) return false; a.push_back (idx); arrSize --; } return true; } bool WriteTextIdxArray (FILE *f, const TextIdxArray &a) { TextIdxArray::const_iterator here = a.begin(); TextIdxArray::const_iterator end = a.end(); while (here != end) { if (!(*here).Write(f)) return false; here++; } return true; } CompressTextInfo::CompressTextInfo () { Clear(); } void CompressTextInfo::Clear () { ResetStart(); docPtrs.erase (docPtrs.begin(), docPtrs.end()); } void CompressTextInfo::ResetStart () { inDoc = false; start.Clear(); which = 0; } void CompressTextInfo::SetStart (unsigned long startPos, unsigned char startBit, unsigned char startWhich) { // place an imaginary end tag if needed // note: the document tag always needs a closing tag if (inDoc) SetEnd (startPos, startBit); // remember start of level inDoc = true; start.byte = startPos; start.bit = startBit; which = startWhich; } void CompressTextInfo::SetEnd (unsigned long endPos, unsigned char endBit) { if (inDoc) { // add completed entry to list of ptrs TextIdx textIdx; textIdx.start = start; textIdx.end.byte = endPos; textIdx.end.bit = endBit; textIdx.which = which; docPtrs.push_back (textIdx); // reset this entry ResetStart(); } }