diff options
-rw-r--r-- | include/Input.h | 32 | ||||
-rw-r--r-- | lib/Handle.cc | 48 | ||||
-rw-r--r-- | lib/Input.cc | 160 |
3 files changed, 228 insertions, 12 deletions
diff --git a/include/Input.h b/include/Input.h index bb740b0..9395687 100644 --- a/include/Input.h +++ b/include/Input.h @@ -35,4 +35,36 @@ class Stdin_t : public Input { extern Stdin_t Stdin; +enum ArchiveType { + ARCHIVE_BUILTIN = 0 +} + +class Archive : public Base { + public: + Archive(const String &, ArchiveType = 0) throw (GeneralException); + virtual ~Archive(); + static bool inarchive(const String &); + static Input & open(const String &) throw (GeneralException); + private: + bool inarchivein(const String &); + Input & openin(const String &) throw (GeneralException); + class FileTree : public Base { + public: + FileTree(const String & = "", size_t = 0, FileTree * = 0, int = 0); + virtual ~FileTree(); + int compute_ptrs(size_t = 0); + String name; + int type; + size_t size; + size_t ptr; + private: + void touched(); + FileTree * next, * prev, * father, * child; + } filetree; + String name; + Input archive; + Archive * next, * prev; + static Archive * header; +}; + #endif diff --git a/lib/Handle.cc b/lib/Handle.cc index 50e7bee..70683b1 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -15,20 +15,26 @@ Handle::Handle(const Handle & nh) : itell(0), h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(nh.closed), nonblock(nh.closed), zfile(0), z(0) { -// cerr << "Duplication of handle " << nh.h << " to " << h << endl; +#ifdef DEBUG + std::cerr << "Duplication of handle " << nh.h << " to " << h << std::endl; +#endif if ((h >= 0) && (nh.z)) { SetZ(nh.z); } } Handle::~Handle() { -// cerr << "Destroying handle " << h << endl; +#ifdef DEBUG + std::cerr << "Destroying handle " << h << std::endl; +#endif close(); } Handle::Handle(int nh) : h(nh), closed(false), nonblock(false), zfile(0), z(0) { -// cerr << "Initialising handle " << h << endl; +#ifdef DEBUG + std::cerr << "Initialising handle " << h << std::endl; +#endif } int Handle::GetHandle() { @@ -61,7 +67,9 @@ ssize_t Handle::write(const void *cbuf, size_t count) throw (GeneralException) { done = false; full = true; if (nonblock) { -// cerr << "write: throwing IOAgain for handle " << GetName() << endl; +#ifdef DEBUG + std::cerr << "write: throwing IOAgain for handle " << GetName() << std::endl; +#endif throw IOAgain(); } else { #ifdef HAVE_SLEEP @@ -94,7 +102,9 @@ ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) { // Avant de déclarer une erreur, on vérifie si ce n'est pas un // problème lié au fait qu'il n'y a plus d'octets. if (nonblock) { -// cerr << "read: throwing IOAgain for handle " << GetName() << endl; +#ifdef DEBUG + std::cerr << "read: throwing IOAgain for handle " << GetName() << std::endl; +#endif throw IOAgain(); } } else { @@ -165,9 +175,13 @@ void Handle::close() throw (GeneralException) { if (h >= 0) { if (z) { -// cerr << "Performing gzclose on handle " << h << endl; +#ifdef DEBUG + std::cerr << "Performing gzclose on handle " << h << std::endl; +#endif int err = gzclose(zfile); -// cerr << "gzclose returned " << err << endl; +#ifdef DEBUG + std::cerr << "gzclose returned " << err << std::endl; +#endif if (err) { if (err == Z_ERRNO) { throw GeneralException(String(_("Error during close: ")) + strerror(errno)); @@ -237,7 +251,9 @@ void Handle::SetZ(int az) throw (GeneralException) { } format[index++] = (char) (az + '0'); format[index] = 0; -// cerr << "Performing gzdopen on handle " << h << " with mode \"" << format << "\"\n"; +#ifdef DEBUG + std::cerr << "Performing gzdopen on handle " << h << " with mode \"" << format << "\"\n"; +#endif if (!(zfile = gzdopen(h, format))) { throw GeneralException(_("Was not able to gzdopen.")); } @@ -248,13 +264,17 @@ void Handle::SetZ(int az) throw (GeneralException) { ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) { if (z) { itell += count; -// cerr << "Performing gzwrite of " << count << " byte for handle " << h << endl; +#ifdef DEBUG + std::cerr << "Performing gzwrite of " << count << " byte for handle " << h << std::endl; +#endif #ifdef HAVE_WD_ZLIB int err = gzwrite(zfile, buf, count); #else int err = gzwrite(zfile, (char *) buf, count); #endif -// cerr << "gzwrite returned " << err << endl; +#ifdef DEBUG + std::cerr << "gzwrite returned " << err << std::endl; +#endif if (err == 0) { const char * m = gzerror(zfile, &err); if (err == Z_ERRNO) { @@ -273,9 +293,13 @@ ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) ssize_t Handle::uread(void * buf, size_t count) { if (z) { itell += count; -// cerr << "Performing gzread of " << count << " byte for handle " << h << endl; +#ifdef DEBUG + std::cerr << "Performing gzread of " << count << " byte for handle " << h << std::endl; +#endif int err = gzread(zfile, buf, count); -// cerr << "gzwrite returned " << err << endl; +#ifdef DEBUG + std::cerr << "gzwrite returned " << err << std::endl; +#endif if (err == -1) { gzerror(zfile, &err); if (err == Z_ERRNO) { diff --git a/lib/Input.cc b/lib/Input.cc index 999ebab..c720f9d 100644 --- a/lib/Input.cc +++ b/lib/Input.cc @@ -98,3 +98,163 @@ String Stdin_t::GetName() const { } Stdin_t Stdin; + +Archive * Archive::header = 0; + +Archive::Archive(const String & fname, ArchiveType type) : name(fname), archive(fname) throw (GeneralException) { + switch(type) { + case ARCHIVE_BUILTIN: + + break; + default: + throw GeneralException("Archive: unsupported archive format."); + } + + next = header; + prev = 0; + header = this; + if (next) + next->prev = this; + +} + +Archive::~Archive() { + if (prev) + prev->next = next; + if (next) + next->prev = prev; + if (header == this) + header = next; +} + +bool Archive::inarchive(const String & fname) { + Archive * p; + for (p = header; p; p = p->next) { + if (p->inarchive(fname)) + return true; + } + return false; +} + +Input & Archive::open(const String & fname) throw (GeneralException) { + Archive * p; + + for (p = header; p; p = p->next) { + if (p->inarchive(fname)) + return p->open(fname); + } + throw IOGeneral("File `" + fname + "' not found in archive collection."); +} + +bool Archive::inarchivein(const String & fname) { + Archive::FileTree * p = filetree->child; + ssize_t pos; + String name = fname; + String reste; + + while((name != "") && p) { + ssize_t pos = name.strchr('/'); + if (pos >= 0) { + reste = name.extract(0, pos - 1); + name = name.extract(pos + 1); + } else { + reste = name; + name = ""; + } + + while (p) { + if (p->name == reste) { + p = p->child; + break; + } else { + p = p->next; + } + } + } + + return p; +} + +Input & Archive::openin(const String & fname) throw (GeneralException) { + Archive::FileTree * p = filetree->child; + ssize_t pos; + String name = fname; + String reste; + + while((name != "") && p) { + ssize_t pos = name.strchr('/'); + if (pos >= 0) { + reste = name.extract(0, pos - 1); + name = name.extract(pos + 1); + } else { + reste = name; + name = ""; + } + + while (p) { + if (p->name == reste) { + p = p->child; + break; + } else { + p = p->next; + } + } + } + + if (!p) + throw IOGeneral("File `" + fname + "' not in archive " + name); + + if (p->child) + throw IOGeneral("File `" + fname + "' in archive " + name + " is a directory - can't open."); + + Input file(archive); + file->seek(p->ptr); + return file; +} + +Archive::FileTree::FileTree(const String & fname, size_t fsize, Archive::FileTree * fFather, int ftype) : + name(fname), type(ftype), size(fsize), next(0), prev(0), father(fFather), child(0) { + if (father) { + if (father->child) { + FileTree * p; + for (p = father->child; p->next; p = p->next); + p->next = this; + prev = p; + } + } +} + +Archive::FileTree::~FileTree() { + if (child) + delete child; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + if (father) { + if (father->child == this) + father->child = next; + father->touched(); + } +} + +void Archive::FileTree::touched() { + if (father) + father->touched() + else + compute_ptrs(ptr); +} + +int Archive::FileTree::compute_ptrs(int cptr) { + ptr = cptr; + + if (child) { + FileTree * p; + size = 0; + for (p = child; p; p = p->next) { + size += p->compute_ptrs(ptr + size) - ptr; + } + } + + return size + ptr; +} |