summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Input.h32
-rw-r--r--lib/Handle.cc48
-rw-r--r--lib/Input.cc160
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;
+}