diff options
Diffstat (limited to 'lib/Input.cc')
-rw-r--r-- | lib/Input.cc | 160 |
1 files changed, 160 insertions, 0 deletions
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; +} |