summaryrefslogtreecommitdiff
path: root/lib/Input.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Input.cc')
-rw-r--r--lib/Input.cc160
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;
+}