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; +}  | 
