summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMakefile2
-rw-r--r--generic/Buffer.cpp106
-rw-r--r--generic/Exceptions.cpp152
-rw-r--r--generic/Handle.cpp269
-rw-r--r--generic/Image.cpp86
-rw-r--r--generic/Input.cpp70
-rw-r--r--generic/Output.cpp68
-rw-r--r--generic/String.cpp358
-rw-r--r--includes/Buffer.h37
-rw-r--r--includes/Exceptions.h137
-rw-r--r--includes/General.h7
-rw-r--r--includes/Handle.h50
-rw-r--r--includes/Image.h61
-rw-r--r--includes/Input.h41
-rw-r--r--includes/Output.h45
-rw-r--r--includes/String.h67
16 files changed, 1555 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 1d95ce6..b68b79b 100755
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ CPPFLAGS=-Wall -g -O3 -mcpu=i686 -pedantic -pedantic-errors -Werror -Iincludes `
LDFLAGS=`sdl-config --libs`
CXX=g++
-SUBDIRS = psxdev lib Xenogears VP MegamanX5
+SUBDIRS = psxdev generic lib Xenogears VP MegamanX5
TARGET = lzss dlzss cd-tool str-player crypto-search bgrep dte-tool
all: subdirs ${TARGET}
diff --git a/generic/Buffer.cpp b/generic/Buffer.cpp
new file mode 100644
index 0000000..edd70bc
--- /dev/null
+++ b/generic/Buffer.cpp
@@ -0,0 +1,106 @@
+#include <string.h>
+#include "Buffer.h"
+#include "General.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+Buffer::Buffer() : Handle(-1), buffer(0), zero(0), realsiz(0), bufsiz(0), ptr(0) { }
+
+Buffer::~Buffer() {
+ free(buffer);
+}
+
+Buffer::Buffer(const Buffer & b) : Handle(-1), buffer(0), zero(b.zero), realsiz(b.realsiz), bufsiz(b.bufsiz), ptr(b.ptr) {
+ buffer = (char *) malloc(bufsiz);
+ memcpy(buffer, b.buffer, bufsiz);
+}
+
+ssize_t Buffer::write(const void *buf, size_t count) throw (GeneralException) {
+ if (!count) {
+ return 0;
+ }
+ if (count + realsiz > bufsiz) {
+ int numblocks = (count + realsiz) / realloc_threshold;
+ int remains = (count + realsiz) % realloc_threshold;
+ buffer = (char *) realloc(buffer, bufsiz = ((numblocks + (remains ? 1 : 0)) * realloc_threshold));
+ }
+ memcpy(buffer + realsiz, buf, count);
+ realsiz += count;
+
+ return count;
+}
+
+ssize_t Buffer::read(void *buf, size_t count) throw (GeneralException) {
+ count = MIN(count, realsiz - ptr);
+
+ if (!count) {
+ return 0;
+ }
+
+ memcpy(buf, buffer + ptr, count);
+ ptr += count;
+
+ if (ptr >= realloc_threshold) {
+ int numblocks = (bufsiz / realloc_threshold) - (ptr / realloc_threshold);
+ memmove(buffer, buffer + (bufsiz - numblocks * realloc_threshold), numblocks * realloc_threshold);
+ ptr -= (bufsiz - numblocks * realloc_threshold);
+ realsiz -= (bufsiz - numblocks * realloc_threshold);
+ buffer = (char *) realloc(buffer, bufsiz = (numblocks * realloc_threshold));
+ }
+
+ return count;
+}
+
+bool Buffer::CanRead() {
+ return true;
+}
+
+bool Buffer::CanWrite() {
+ return true;
+}
+
+String Buffer::GetName() {
+ return "Buffer";
+}
+
+Buffer Buffer::operator=(const Buffer & b) {
+ if (b.buffer != buffer) {
+ free(buffer);
+ realsiz = b.realsiz;
+ ptr = b.ptr;
+ if ((bufsiz = b.bufsiz)) {
+ buffer = (char *) malloc(bufsiz);
+ memcpy(buffer, b.buffer, realsiz);
+ } else {
+ buffer = 0;
+ }
+ }
+ return *this;
+}
+
+bool Buffer::CanWatch() {
+ return false;
+}
+
+ssize_t Buffer::GetSize() {
+ return realsiz;
+}
+
+char Buffer::operator[](size_t p) const {
+ if (p >= realsiz) {
+ return 0;
+ } else {
+ return buffer[ptr + p];
+ }
+}
+
+char & Buffer::operator[](size_t p) {
+ if (p >= realsiz) {
+ return zero;
+ } else {
+ return buffer[ptr + p];
+ }
+}
diff --git a/generic/Exceptions.cpp b/generic/Exceptions.cpp
new file mode 100644
index 0000000..b541235
--- /dev/null
+++ b/generic/Exceptions.cpp
@@ -0,0 +1,152 @@
+#include <malloc.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stddef.h>
+#include "String.h"
+#include "Exceptions.h"
+#include "General.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+char GeneralException::t[BUFSIZ];
+
+GeneralException::GeneralException(String emsg) : msg(emsg.strdup()) {
+#ifdef DEBUG
+ cerr << _("Generating a General Exception error: '") << msg << "'.\n";
+#endif
+}
+GeneralException::GeneralException() : msg(0) {
+#ifdef DEBUG
+ cerr << _("Generating a General Exception error: '") << msg << "'.\n";
+#endif
+}
+GeneralException::GeneralException(const GeneralException & e) : msg(strdup(e.msg)) {
+#ifdef DEBUG
+ cerr << _("Generating a General Exception error: '") << msg << "'.\n";
+#endif
+}
+
+GeneralException::~GeneralException() {
+ free(msg);
+}
+
+TaskNotFound::TaskNotFound() : GeneralException("Task not found") { }
+
+char * GeneralException::GetMsg() {
+ return msg;
+}
+
+MemoryException::MemoryException(ssize_t s) {
+ sprintf(t, _("Failed allocating %u bytes."), s);
+ msg = strdup(t);
+}
+
+IOException::IOException(String fn, op_t op, ssize_t s) {
+ sprintf(t, _("An error has occured while %s %u bytes on %s: %s"), op == IO_WRITE ? _("writing") : _("reading"),
+ s, fn.to_charp(), strerror(errno));
+ msg = strdup(t);
+}
+
+IOGeneral::IOGeneral(String fn) : GeneralException(fn) { }
+
+IOGeneral::IOGeneral() { }
+
+IOAgain::IOAgain() : IOGeneral(_("No more bytes for reading or writing.")) {
+#ifdef DEBUG
+ cerr << "Generating an IOAgain exception: '" << GetMsg() << "'.\n";
+#endif
+}
+
+TaskSwitch::TaskSwitch() : GeneralException(_("Switching task in a non-tasked environnement")) {
+#ifdef DEBUG
+ cerr << "Generating a TaskSwitch exception: '" << GetMsg() << "'.\n";
+#endif
+}
+
+char * xstrdup(const char * s) {
+ char * r;
+
+ r = (char *) xmalloc(strlen(s) + 1);
+ strcpy(r, s);
+ return r;
+}
+
+void * xmalloc(size_t s) throw (GeneralException) {
+ char * r;
+
+ if (!s) {
+ return 0;
+ }
+
+ if (!(r = (char *) ::malloc(s + sizeof(size_t)))) {
+ throw MemoryException(s + sizeof(size_t));
+ }
+
+ memset(r, 0, s + sizeof(size_t));
+
+ *((size_t *)r) = s;
+
+ return (void *)(r + sizeof(size_t));
+}
+
+void * xrealloc(void * ptr, size_t s) {
+ char * r;
+ size_t os;
+
+ if (!ptr) {
+ return xmalloc(s);
+ }
+
+ os = *(((size_t *) ptr) - 1);
+
+ r = (char *) xmalloc(s);
+
+ if (s) {
+ memcpy(r, ptr, MIN(s, os));
+ }
+
+ xfree(ptr);
+ return r;
+}
+
+#ifdef OVER_FREE
+#undef free
+#endif
+
+void xfree(void *& p) {
+ if (p) {
+ ::free(((char *)p) - sizeof(size_t));
+ p = 0;
+ }
+}
+
+void xfree(char *& p) {
+ if (p) {
+ ::free(p - sizeof(size_t));
+ p = 0;
+ }
+}
+
+int xpipe(int * p, int flag) throw (GeneralException) {
+ if (pipe(p)) {
+ throw GeneralException(String(_("Error creating pipe: ")) + strerror(errno));
+ }
+
+ return p[flag];
+}
+
+pid_t xfork() throw (GeneralException) {
+ pid_t p;
+
+ p = fork();
+
+ if (p == -1) {
+ throw GeneralException(_("Was not able to fork().\n"));
+ }
+
+ return p;
+}
diff --git a/generic/Handle.cpp b/generic/Handle.cpp
new file mode 100644
index 0000000..8b7a278
--- /dev/null
+++ b/generic/Handle.cpp
@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "Handle.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+Handle::Handle(const Handle & nh) : 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;
+ if ((h >= 0) && (nh.z)) {
+ SetZ(nh.z);
+ }
+}
+
+Handle::~Handle() {
+// cerr << "Destroying handle " << h << endl;
+ close();
+}
+
+Handle::Handle(int nh) : h(nh), closed(false), nonblock(false), zfile(0), z(0) {
+// cerr << "Initialising handle " << h << endl;
+}
+
+int Handle::GetHandle() {
+ return h;
+}
+
+ssize_t Handle::write(const void *buf, size_t count) throw (GeneralException) {
+ ssize_t r, tr = 0;
+ bool done, full = false;
+
+ do {
+ done = true;
+ errno = 0;
+ if ((r = uwrite(buf, count)) < 0) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
+ // 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 de place libre. Cela peut
+ // arriver si l'on agit sur un pipe ou un handle. Nous
+ // attendons encore une fois avant de déclarer l'erreur,
+ // grace au drapeau full.
+ if (full) {
+ throw IOException(GetName(), IO_WRITE, count);
+ } else {
+ done = false;
+ full = true;
+ if (nonblock) {
+// cerr << "write: throwing IOAgain for handle " << GetName() << endl;
+ throw IOAgain();
+ } else {
+ sleep(1);
+ }
+ }
+ } else {
+ throw IOException(GetName(), IO_WRITE, count);
+ }
+ } else if (((size_t) r) != count) {
+ if (nonblock) {
+ return r;
+ }
+ full = done = false;
+ ((char *)buf) += r;
+ tr += r;
+ }
+ } while (!done);
+
+ return r + tr;
+}
+
+ssize_t Handle::read(void *buf, size_t count) throw (GeneralException) {
+ ssize_t r;
+
+ errno = 0;
+ while ((r = uread(buf, count)) < 0) {
+ if ((!errno) || (errno == EAGAIN) || (errno == EINTR)) {
+ // 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;
+ throw IOAgain();
+ }
+ } else {
+ throw IOException(GetName(), IO_READ, count);
+ }
+ }
+
+ if (!r) {
+ close();
+ }
+
+ return r;
+}
+
+bool Handle::IsClosed(void) {
+ return closed;
+}
+
+bool Handle::IsNonBlock(void) {
+ return nonblock;
+}
+
+void Handle::SetNonBlock(void) {
+ if ((h >= 0) || !nonblock) {
+ fcntl(h, F_SETFL, O_NONBLOCK);
+ }
+ nonblock = true;
+}
+
+Handle & operator<<(Handle & h, const String & s) {
+ const char * p;
+
+ p = s.to_charp();
+ h.write(p, strlen(p));
+
+ return h;
+}
+
+Handle & operator>>(Handle & h, String & s) {
+ char t[BUFSIZ];
+ int i = 0, r;
+
+ while ((r = h.read(&(t[i]), 1)) && (i != (BUFSIZ - 1))) {
+ // Il y a souvent des \r\n dans les sockets par exemple,
+ // ou bien en lisant des fichiers au format MS-DOS. On
+ // ignore le \r pour ne garder que le \n, standard sous Unix.
+ if (t[i] == '\r') {
+ continue;
+ }
+ if (t[i] == '\n') {
+ break;
+ } else {
+ i++;
+ }
+ }
+
+ t[i] = '\0';
+ s = t;
+ return h;
+}
+
+void Handle::close() throw (GeneralException) {
+ if (IsClosed()) {
+ return;
+ }
+
+ if (h >= 0) {
+ if (z) {
+// cerr << "Performing gzclose on handle " << h << endl;
+ int err = gzclose(zfile);
+// cerr << "gzclose returned " << err << endl;
+ if (err) {
+ if (err == Z_ERRNO) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ } else {
+ throw GeneralException(_("Error in zlib during gzclose."));
+ }
+ }
+ } else {
+ int err = ::close(h);
+ if (err) {
+ throw GeneralException(String(_("Error during close: ")) + strerror(errno));
+ }
+ }
+ }
+
+ h = -1;
+
+ closed = 1;
+}
+
+bool Handle::CanRead(void) {
+ return false;
+}
+
+bool Handle::CanWrite(void) {
+ return false;
+}
+
+String Handle::GetName(void) {
+ return _("Bare Handle - should not happend");
+}
+
+ssize_t Handle::GetSize(void) {
+ return -1;
+}
+
+time_t Handle::GetModif(void) {
+ return -1;
+}
+
+bool Handle::CanWatch(void) {
+ return true;
+}
+
+void Handle::Dup(const Handle & H) {
+ close();
+ if (H.h >= 0) {
+ h = dup(H.h);
+ }
+}
+
+void Handle::SetZ(int az) throw (GeneralException) {
+ if (z) {
+ throw GeneralException(_("Can't SetZ a Handle twice."));
+ }
+ if (h < 0) {
+ throw GeneralException(_("Can't SetZ a virtual Handle."));
+ }
+ if (az) {
+ char format[4];
+ int index = 0;
+ if (CanRead()) {
+ format[index++] = 'r';
+ }
+ if (CanWrite()) {
+ format[index++] = 'w';
+ }
+ format[index++] = (char) (az + '0');
+ format[index] = 0;
+// cerr << "Performing gzdopen on handle " << h << " with mode \"" << format << "\"\n";
+ if (!(zfile = gzdopen(h, format))) {
+ throw GeneralException(_("Was not able to gzdopen."));
+ }
+ z = az;
+ }
+}
+
+ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) {
+ if (z) {
+// cerr << "Performing gzwrite of " << count << " byte for handle " << h << endl;
+ int err = gzwrite(zfile, buf, count);
+// cerr << "gzwrite returned " << err << endl;
+ if (err == 0) {
+ const char * m = gzerror(zfile, &err);
+ if (err == Z_ERRNO) {
+ return -1;
+ } else {
+ throw GeneralException(String(_("Error in zlib during gzwrite: ")) + m);
+ }
+ }
+ return err;
+ } else {
+ return ::write(h, buf, count);
+ }
+}
+
+ssize_t Handle::uread(void * buf, size_t count) {
+ if (z) {
+// cerr << "Performing gzread of " << count << " byte for handle " << h << endl;
+ int err = gzread(zfile, buf, count);
+// cerr << "gzwrite returned " << err << endl;
+ if (err == -1) {
+ gzerror(zfile, &err);
+ if (err == Z_ERRNO) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ return err;
+ } else {
+ return ::read(h, buf, count);
+ }
+}
diff --git a/generic/Image.cpp b/generic/Image.cpp
new file mode 100644
index 0000000..1270a6a
--- /dev/null
+++ b/generic/Image.cpp
@@ -0,0 +1,86 @@
+#include "Image.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+Image::Image(unsigned int ax, unsigned int ay) : x(ax), y(ay), img((Color *) malloc(x * y * sizeof(Color))) {
+ Fill();
+}
+
+Image::~Image() {
+ free((void *)img);
+}
+
+bool Image::CanWrite() {
+ return false;
+}
+
+String Image::GetName() {
+ return String(_("Image ")) + x + "x" + y;
+}
+
+void Image::Fill(Color c) {
+ for (unsigned int i = 0; i < x * y; i++) {
+ img[i] = c;
+ }
+}
+
+Color Image::GetPixel(unsigned int px, unsigned int py) {
+ if ((px >= x) || (py >= y)) {
+ return Color(0, 0, 0, 0);
+ }
+
+ return img[x * py + px];
+}
+
+void Image::SetPixel(unsigned int px, unsigned int py, Color c) {
+ if ((px >= x) || (py >= y)) {
+ return;
+ }
+
+ img[x * py + px] = c;
+}
+
+#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN 0
+#endif
+
+bool Image::Prepare(unsigned int f) {
+ if (GetSize()) return false;
+
+ switch (f) {
+ case FORMAT_TGA_BASIC:
+ TGAHeader Header;
+ TGAFooter Footer;
+
+ Header.IDLength = 0;
+ Header.ColorMapType = 0;
+ Header.ImageType = 2;
+ Header.CM_FirstEntry = 0;
+ Header.CM_Length = 0;
+ Header.CM_EntrySize = 0;
+ Header.IS_XOrigin = 0;
+ Header.IS_YOrigin = 0;
+ Header.IS_Width = WORDS_BIGENDIAN ? ((x & 0xff) << 8) | ((x & 0xff00) >> 8) : x;
+ Header.IS_Height = WORDS_BIGENDIAN ? ((y & 0xff) << 8) | ((y & 0xff00) >> 8) : y;
+ Header.IS_Depth = 32;
+ Header.IS_Descriptor = 0x20;
+
+ Footer.ExtOffset = 0;
+ Footer.DevOffset = 0;
+ strcpy(Footer.Sig, "TRUEVISION-XFILE.");
+
+ write(&Header, sizeof(Header));
+ write(img, x * y * sizeof(Color));
+ write(&Footer, sizeof(Footer));
+
+ return true;
+
+ break;
+ default:
+ return false;
+ }
+}
+
diff --git a/generic/Input.cpp b/generic/Input.cpp
new file mode 100644
index 0000000..7106c8d
--- /dev/null
+++ b/generic/Input.cpp
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "Input.h"
+#include "Exceptions.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+Input::Input(String no) throw (GeneralException) :
+ Handle(no.strlen() ? open(no.to_charp(), O_RDONLY) : dup(0)),
+ n(no) {
+ if (GetHandle() < 0) {
+ throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno));
+ }
+
+ size = lseek(GetHandle(), 0, SEEK_END);
+ lseek(GetHandle(), 0, SEEK_SET);
+
+ struct stat s;
+
+ fstat(GetHandle(), &s);
+
+ date_modif = s.st_mtime;
+}
+
+Input::Input(const Input & i) : Handle(i), n(i.n), size(i.size), date_modif(i.date_modif) {
+}
+
+bool Input::CanWrite() {
+ return 0;
+}
+
+bool Input::CanRead() {
+ return 1;
+}
+
+String Input::GetName() {
+ return n;
+}
+
+ssize_t Input::GetSize() {
+ return size;
+}
+
+time_t Input::GetModif() {
+ return date_modif;
+}
+
+Stdin_t::Stdin_t() : Handle(dup(0)) { }
+
+bool Stdin_t::CanWrite() {
+ return 0;
+}
+
+bool Stdin_t::CanRead() {
+ return 1;
+}
+
+String Stdin_t::GetName() {
+ return "Stdin";
+}
+
+Stdin_t Stdin;
diff --git a/generic/Output.cpp b/generic/Output.cpp
new file mode 100644
index 0000000..dbc1892
--- /dev/null
+++ b/generic/Output.cpp
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "Output.h"
+#include "Exceptions.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+Output::Output(String no, int trunc) throw (GeneralException) :
+ Handle(no.strlen() ? open(no.to_charp(), O_WRONLY | O_CREAT | (trunc ? O_TRUNC : O_APPEND), 00666) : dup(1)),
+ n(no) {
+ if (GetHandle() < 0) {
+ throw IOGeneral(String(_("Error opening file ")) + no + _(" for writing: ") + strerror(errno));
+ }
+}
+
+Output::Output(const Output & o) : Handle(o), n(o.n) {
+}
+
+bool Output::CanWrite() {
+ return 1;
+}
+
+bool Output::CanRead() {
+ return 0;
+}
+
+String Output::GetName() {
+ return n;
+}
+
+Stdout_t::Stdout_t() : Handle(dup(1)) {}
+
+bool Stdout_t::CanWrite() {
+ return 1;
+}
+
+bool Stdout_t::CanRead() {
+ return 0;
+}
+
+String Stdout_t::GetName() {
+ return "Stdout";
+}
+
+Stderr_t::Stderr_t() : Handle(dup(2)) {}
+
+bool Stderr_t::CanWrite() {
+ return 1;
+}
+
+bool Stderr_t::CanRead() {
+ return 0;
+}
+
+String Stderr_t::GetName() {
+ return "Stderr";
+}
+
+Stdout_t Stdout;
+Stderr_t Stderr;
diff --git a/generic/String.cpp b/generic/String.cpp
new file mode 100644
index 0000000..d6a1e01
--- /dev/null
+++ b/generic/String.cpp
@@ -0,0 +1,358 @@
+#include <iostream.h>
+#include <string.h>
+#include <stdarg.h>
+#include "String.h"
+#include "Exceptions.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+extern "C" {
+ double dateCalc(char *, char *);
+ int isDateArgument(char *);
+}
+
+char String::t[BUFSIZ + 1];
+
+String::String(const String & s) : str(Base::strdup(s.str)), siz(s.siz) { }
+
+String::String(char c) : siz(1) {
+ char * t = (char *) malloc(2);
+
+ sprintf(t, "%c", c);
+ str = t;
+}
+
+String::String(const char * s) : str(s ? Base::strdup(s) : Base::strdup("")) {
+ siz = ::strlen(str);
+}
+
+String::String(int hs, const char * s) : str(s ? Base::strdup(s) : Base::strdup("")), siz(hs) { }
+
+String::String(int i) {
+ char t[20];
+
+ sprintf(t, "%i", i);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned int i) {
+ char t[20];
+
+ sprintf(t, "%u", i);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+#ifdef USE_LONGLONG
+String::String(long long l) {
+ char t[40];
+
+ sprintf(t, "%lld", l);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned long long l) {
+ char t[40];
+
+ sprintf(t, "%llu", l);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+#endif
+
+String::String(double d) {
+ char t[30];
+
+ sprintf(t, "%g", d);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::~String() {
+ free(str);
+}
+
+const char * String::set(const char * s, ...) {
+ va_list ap;
+
+/* This causes a warning: cannot pass objects of type `const String' through `...'
+ but it is not really a problem. */
+ va_start(ap, s);
+ vsnprintf(t, BUFSIZ, s, ap);
+ free(str);
+ str = Base::strdup(t);
+ va_end(ap);
+ siz = ::strlen(str);
+ return t;
+}
+
+const char * String::set(const String & s, ...) {
+ va_list ap;
+
+ va_start(ap, s);
+ vsnprintf(t, BUFSIZ, s.str, ap);
+ free(str);
+ str = Base::strdup(t);
+ va_end(ap);
+ siz = ::strlen(str);
+ return t;
+}
+
+const char * String::to_charp(size_t from, ssize_t to) const {
+ if (to < 0) {
+ strncpy(t, &(str[from]), BUFSIZ);
+ } else {
+ if (((size_t) to) >= siz) {
+ to = siz - 1;
+ }
+
+ if ((((size_t) to) - from) > BUFSIZ) {
+ from -= (to - from) - BUFSIZ;
+ }
+
+ if (((size_t) to) >= from) {
+ size_t i;
+ for (i = 0; i <= ((size_t) to) - from; i++) {
+ t[i] = str[i + from];
+ }
+ t[i] = '\0';
+ } else {
+ t[0] = '\0';
+ }
+ }
+ return t;
+}
+
+String String::extract(size_t from, ssize_t to) const {
+ return String(to_charp(from, to));
+}
+
+char * String::strdup(size_t from, ssize_t to) const {
+ return Base::strdup(to_charp(from, to));
+}
+
+int String::to_int(void) const {
+ int r;
+
+ sscanf(str, "%i", &r);
+ return r;
+}
+
+double String::to_double(void) const {
+ double r;
+
+ sscanf(str, "%lf", &r);
+ return r;
+}
+
+String & String::operator=(const String & s) {
+ if (str != s.str) {
+ // On évite l'autodestruction...
+ free(str);
+ str = s.strdup();
+ siz = s.siz;
+ }
+ return *this;
+}
+
+String String::operator+(const String & s) const {
+ char * t = (char *) malloc(s.siz + siz + 1), * u;
+ String o;
+
+ strcpy((u = t), str);
+ u += siz;
+ strcpy(u, s.str);
+ o = String(siz + s.siz, t);
+ free(t);
+ return o;
+}
+
+String & String::operator+=(const String & s) {
+ char * t = (char *) malloc(s.siz + siz + 1), * u;
+
+ strcpy((u = t), str);
+ u += siz;
+ strcat(u, s.str);
+ free(str);
+ str = t;
+ siz += s.siz;
+ return (*this);
+}
+
+ostream & operator<<(ostream & os, const String & s) {
+ return (os << s.to_charp());
+}
+
+istream & operator>>(istream & is, String & s) {
+ char c = 0;
+
+ s.set("");
+
+ while (!is.eof()) {
+ c = is.get();
+ if (c == '\n') return is;
+ if (c == '\r') continue;
+ s += c;
+ }
+
+ return is;
+}
+
+bool String::operator!=(const String & s) const {
+ return (strcmp(str, s.str) != 0);
+}
+
+bool String::operator==(const String & s) const {
+ return (strcmp(str, s.str) == 0);
+}
+
+bool String::operator<=(const String & s) const {
+ return (strcmp(str, s.str) <= 0);
+}
+
+bool String::operator>=(const String & s) const {
+ return (strcmp(str, s.str) >= 0);
+}
+
+bool String::operator<(const String & s) const {
+ return (strcmp(str, s.str) < 0);
+}
+
+bool String::operator>(const String & s) const {
+ return (strcmp(str, s.str) > 0);
+}
+
+size_t String::strlen() const {
+ return (siz);
+}
+
+char String::operator[](size_t i) const {
+ if (i >= siz) {
+ return 0;
+ } else {
+ return str[i];
+ }
+}
+
+ssize_t String::strchr(char c, size_t from) const {
+ for (size_t i = from; i < siz; i++) {
+ if (str[i] == c) return i;
+ }
+
+ return -1;
+}
+
+ssize_t String::strrchr(char c) const {
+ for (size_t i = siz - 1; i >= 0; i--) {
+ if (str[i] == c) return i;
+ }
+
+ return -1;
+}
+
+ssize_t String::strstr(const String & s) const {
+ char * p = ::strstr(str, s.str);
+
+ if (p) {
+ return p - str;
+ } else {
+ return -1;
+ }
+}
+
+int String::strchrcnt(char c) const {
+ size_t i, cnt = 0;
+ for (i = 0; i < siz; i++) {
+ if (str[i] == c) cnt++;
+ }
+
+ return cnt;
+}
+
+String String::to_sqldate(void) const {
+/* DD/MM/YYYY ==> YYYYMMMDD */
+ return (is_date() ? extract(6, 9) + extract(3, 4) + extract(0, 1) : "");
+}
+
+String String::to_sqltime(void) const {
+/* h:m ==> h * 60 + m */
+ int p = strchr(':');
+ return (is_time() ? String(extract(0, p - 1).to_int() * 60 + extract(p + 1).to_int()) : "");
+}
+
+String String::from_sqldate(void) const {
+/* YYYYMMDD ==> DD/MM/YYYY */
+ return ((strlen() == 8) && is_number() ? extract(6, 7) + '/' + extract(4, 5) + '/' + extract(0, 3) : "");
+}
+
+String String::from_sqltime(void) const {
+/* t ==> (t / 60):(t % 60) */
+ int t = to_int();
+ return (is_number() ? String((int) (t / 60)) + ':' + (t % 60) : "");
+}
+
+bool String::is_date(void) const {
+/* 'DD/MM/YYYY'
+ 0123456789 */
+
+ if (strlen() != 10) return false;
+ if ((str[2] != '/') || (str[5] != '/') ||
+ (!extract(0, 1).is_number()) ||
+ (!extract(3, 4).is_number()) ||
+ (!extract(6, 9).is_number())) {
+ return (isDateArgument(to_sqldate().str));
+ }
+
+ return true;
+}
+
+double String::datedif(const String & s) const {
+ double r;
+ if (is_date() && s.is_date()) {
+ r = dateCalc(str, s.str);
+ return r < 0 ? -r : r;
+ }
+
+ return -1;
+}
+
+bool String::is_number(void) const {
+ for (size_t i = ((str[0] == '-') ? 1 : 0); i < siz; i++) {
+ if ((str[i] > '9') || (str[i] < '0')) return false;
+ }
+ return true;
+}
+
+bool String::is_float(void) const {
+ bool seendot = false;
+
+ for (size_t i = ((str[0] == '-') ? 1 : 0); i < siz; i++) {
+ if ((str[i] > '9') || (str[i] < '0')) {
+ if ((str[i] == '.') && !seendot) {
+ seendot = true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool String::is_time(void) const {
+ int p = strchr(':');
+
+ if (p == -1) return false;
+
+ // On accepte les heures sous le format xxxxxx:yy pour pouvoir indiquer des durées.
+
+ if ((!extract(0, p - 1).is_number()) || (!extract(p + 1).is_number()))
+ return false;
+
+ return (extract(p + 1).to_int() < 60) ? true : false;
+}
diff --git a/includes/Buffer.h b/includes/Buffer.h
new file mode 100644
index 0000000..79d0e02
--- /dev/null
+++ b/includes/Buffer.h
@@ -0,0 +1,37 @@
+#ifndef __BUFFER_H__
+#define __BUFFER_H__
+#ifdef __cplusplus
+
+#include <zlib.h>
+#include <Exceptions.h>
+#include <Handle.h>
+
+#ifndef realloc_threshold
+#define realloc_threshold 256
+#endif
+
+class Buffer : public Handle {
+ public:
+ Buffer();
+ Buffer(const Buffer &);
+ virtual ~Buffer();
+ virtual ssize_t write(const void *buf, size_t count) throw(GeneralException);
+ virtual ssize_t read(void *buf, size_t count) throw (GeneralException);
+ virtual bool CanRead();
+ virtual bool CanWrite();
+ virtual String GetName();
+ virtual Buffer operator=(const Buffer &);
+ virtual bool CanWatch();
+ virtual ssize_t GetSize();
+ char operator[](size_t) const;
+ char & operator[](size_t);
+
+ private:
+ char * buffer, zero;
+ size_t realsiz, bufsiz, ptr;
+};
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/Exceptions.h b/includes/Exceptions.h
new file mode 100644
index 0000000..ef697e7
--- /dev/null
+++ b/includes/Exceptions.h
@@ -0,0 +1,137 @@
+#ifndef __EXCEPTIONS_H__
+#define __EXCEPTIONS_H__
+#ifdef __cplusplus
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define INLINE __inline__
+
+class Base {
+ public:
+ static char * strdup(const char * s);
+ static void * malloc(ssize_t s);
+ static void * realloc(void * p, size_t s);
+ static void * calloc(size_t n, size_t s);
+ void * operator new(size_t s);
+ void * operator new(size_t s, void * p);
+ void operator delete(void * p);
+ static void free(void *& p);
+ static void free(char *& p);
+ static int pipe(int * p, int flag = 0);
+ static pid_t fork();
+};
+
+class String;
+
+class GeneralException : public Base {
+ public:
+ GeneralException(String);
+ GeneralException(const GeneralException &);
+ ~GeneralException();
+ char * GetMsg();
+
+ protected:
+ GeneralException();
+ char * msg;
+ static char t[BUFSIZ];
+};
+
+char * xstrdup(const char *);
+void * xmalloc(size_t) throw (GeneralException);
+void xfree(void *&);
+void xfree(char *&);
+void * xrealloc(void *, size_t);
+int xpipe(int *, int = 0) throw (GeneralException);
+pid_t xfork() throw (GeneralException);
+
+INLINE char * Base::strdup(const char * s) {
+ return xstrdup(s);
+}
+
+INLINE void * Base::malloc(ssize_t s) {
+ return xmalloc(s);
+}
+
+INLINE void * Base::realloc(void * p, size_t s) {
+ return xrealloc(p, s);
+}
+
+INLINE void * Base::calloc(size_t n, size_t s) {
+ return xmalloc(n * s);
+}
+
+INLINE void * Base::operator new(size_t s) {
+ return xmalloc(s);
+}
+
+INLINE void * Base::operator new(size_t s, void * p) {
+ return memset(p, 0, s);
+}
+
+INLINE void Base::operator delete(void * p) {
+ xfree(p);
+}
+
+INLINE void Base::free(void *& p) {
+ xfree(p);
+}
+
+INLINE void Base::free(char *& p) {
+ xfree(p);
+}
+
+INLINE int Base::pipe(int * p, int flag) {
+ return xpipe(p, flag);
+}
+
+INLINE pid_t Base::fork() {
+ return xfork();
+}
+
+class MemoryException : public GeneralException {
+ public:
+ MemoryException(ssize_t);
+};
+
+class TaskNotFound : public GeneralException {
+ public:
+ TaskNotFound();
+};
+
+enum op_t {
+ IO_WRITE = 1,
+ IO_READ
+};
+
+class IOGeneral : public GeneralException {
+ public:
+ IOGeneral(String);
+ protected:
+ IOGeneral();
+};
+
+class IOException : public IOGeneral {
+ public:
+ IOException(String, op_t, ssize_t);
+};
+
+class IOAgain : public IOGeneral {
+ public:
+ IOAgain();
+};
+
+class TaskSwitch : public GeneralException {
+ public:
+ TaskSwitch();
+};
+
+#include <String.h>
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/General.h b/includes/General.h
new file mode 100644
index 0000000..6f423ed
--- /dev/null
+++ b/includes/General.h
@@ -0,0 +1,7 @@
+#ifndef __GENERAL_H__
+#define __GENERAL_H__
+
+#define MAX(__a,__b) ((__a)<(__b)?(__b):(__a))
+#define MIN(__a,__b) ((__a)>(__b)?(__b):(__a))
+
+#endif
diff --git a/includes/Handle.h b/includes/Handle.h
new file mode 100644
index 0000000..3b9c9dc
--- /dev/null
+++ b/includes/Handle.h
@@ -0,0 +1,50 @@
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+#ifdef __cplusplus
+
+#include <zlib.h>
+#include <unistd.h>
+#include <iostream.h>
+#include <String.h>
+#include <Exceptions.h>
+
+#include <sys/types.h>
+#include <time.h>
+
+class Handle : public Base {
+ public:
+ Handle(const Handle &);
+ virtual ~Handle();
+ virtual ssize_t read(void *buf, size_t count) throw (GeneralException);
+ virtual ssize_t write(const void *buf, size_t count) throw (GeneralException);
+ bool IsClosed(void);
+ bool IsNonBlock(void);
+ void SetNonBlock(void);
+ virtual bool CanRead();
+ virtual bool CanWrite();
+ virtual String GetName();
+ virtual ssize_t GetSize();
+ virtual time_t GetModif();
+ void close() throw (GeneralException);
+ int GetHandle();
+ virtual bool CanWatch();
+ virtual void Dup(const Handle &);
+ virtual void SetZ(int) throw (GeneralException);
+ protected:
+ Handle(int h);
+ private:
+ ssize_t uwrite(const void *, size_t) throw (GeneralException);
+ ssize_t uread(void *, size_t);
+ int h;
+ bool closed, nonblock;
+ gzFile zfile;
+ int z;
+};
+
+Handle & operator<<(Handle &, const String &);
+Handle & operator>>(Handle &, String &);
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/Image.h b/includes/Image.h
new file mode 100644
index 0000000..8dc6788
--- /dev/null
+++ b/includes/Image.h
@@ -0,0 +1,61 @@
+#ifndef __IMAGE_H__
+#define __IMAGE_H__
+#ifdef __cplusplus
+
+#include <Buffer.h>
+
+enum {
+ FORMAT_TGA_BASIC
+} format_t;
+
+struct Color {
+ Color(unsigned char aR, unsigned char aG, unsigned char aB, unsigned char aA = 255) :
+ R(aR), G(aG), B(aB), A(aA) { }
+ unsigned char R, G, B, A;
+};
+
+class Image : public Buffer {
+ public:
+ Image(unsigned int, unsigned int);
+ virtual ~Image();
+ Color GetPixel(unsigned int, unsigned int);
+ void SetPixel(unsigned int, unsigned int, Color);
+ bool Prepare(unsigned int = FORMAT_TGA_BASIC);
+ void Fill(Color = Color(0, 0, 0));
+ virtual String GetName();
+ virtual bool CanWrite();
+
+ private:
+ typedef unsigned char Byte;
+ typedef unsigned short int Word;
+ typedef unsigned long int DWord;
+ struct TGAHeader {
+ Byte IDLength;
+ Byte ColorMapType;
+ Byte ImageType;
+ Word CM_FirstEntry;
+ Word CM_Length;
+ Byte CM_EntrySize;
+ Word IS_XOrigin;
+ Word IS_YOrigin;
+ Word IS_Width;
+ Word IS_Height;
+ Byte IS_Depth;
+ Byte IS_Descriptor;
+ } __attribute__((packed));
+
+ struct TGAFooter {
+ DWord ExtOffset;
+ DWord DevOffset;
+ char Sig[18];
+ } __attribute__((packed));
+
+ unsigned int x, y;
+ bool r;
+ Color * img;
+};
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/Input.h b/includes/Input.h
new file mode 100644
index 0000000..7091258
--- /dev/null
+++ b/includes/Input.h
@@ -0,0 +1,41 @@
+#ifndef __INPUT_H__
+#define __INPUT_H__
+#ifdef __cplusplus
+
+#include <sys/types.h>
+#include <time.h>
+#include <String.h>
+#include <Handle.h>
+
+class Input : public Handle {
+ public:
+ Input(String = "") throw (GeneralException);
+ Input(const Input &);
+ virtual ~Input() {}
+ virtual bool CanWrite();
+ virtual bool CanRead();
+ virtual String GetName();
+ virtual ssize_t GetSize();
+ virtual time_t GetModif();
+
+ protected:
+ String n;
+ off_t size;
+ time_t date_modif;
+};
+
+class Stdin_t : public Handle {
+ public:
+ Stdin_t();
+ virtual ~Stdin_t() {}
+ virtual bool CanWrite();
+ virtual bool CanRead();
+ virtual String GetName();
+};
+
+extern Stdin_t Stdin;
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/Output.h b/includes/Output.h
new file mode 100644
index 0000000..32d4e66
--- /dev/null
+++ b/includes/Output.h
@@ -0,0 +1,45 @@
+#ifndef __OUTPUT_H__
+#define __OUTPUT_H__
+#ifdef __cplusplus
+
+#include <String.h>
+#include <Handle.h>
+
+class Output : public Handle {
+ public:
+ Output(String = "", int trunc = 1) throw (GeneralException);
+ Output(const Output &);
+ virtual ~Output() {}
+ virtual bool CanWrite();
+ virtual bool CanRead();
+ virtual String GetName();
+
+ protected:
+ String n;
+};
+
+class Stdout_t : public Handle {
+ public:
+ Stdout_t();
+ virtual ~Stdout_t() {}
+ virtual bool CanWrite();
+ virtual bool CanRead();
+ virtual String GetName();
+};
+
+class Stderr_t : public Handle {
+ public:
+ Stderr_t();
+ virtual ~Stderr_t() {}
+ virtual bool CanWrite();
+ virtual bool CanRead();
+ virtual String GetName();
+};
+
+extern Stdout_t Stdout;
+extern Stderr_t Stderr;
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif
diff --git a/includes/String.h b/includes/String.h
new file mode 100644
index 0000000..b53936f
--- /dev/null
+++ b/includes/String.h
@@ -0,0 +1,67 @@
+#ifndef __STRING_H__
+#define __STRING_H__
+#ifdef __cplusplus
+
+#include <iostream.h>
+#include <string.h>
+#include <Exceptions.h>
+
+class String : public Base {
+ public:
+ String(const String &);
+ String(const char * = "");
+ String(char);
+ String(int);
+ String(unsigned int);
+#ifdef USE_LONGLONG
+ String(long long);
+ String(unsigned long long);
+#endif
+ String(double);
+ ~String();
+ const char * set(const char *, ...);
+ const char * set(const String &, ...);
+ const char * to_charp(size_t = 0, ssize_t = -1) const;
+ String extract(size_t = 0, ssize_t = -1) const;
+ char * strdup(size_t = 0, ssize_t = -1) const;
+ int to_int() const;
+ double to_double() const;
+ String to_sqldate() const;
+ String to_sqltime() const;
+ String from_sqldate() const;
+ String from_sqltime() const;
+ double datedif(const String &) const;
+ bool is_date() const;
+ bool is_number() const;
+ bool is_float() const;
+ bool is_time() const;
+ size_t strlen() const;
+ ssize_t strchr(char, size_t = 0) const;
+ ssize_t strrchr(char) const;
+ ssize_t strstr(const String &) const;
+ int strchrcnt(char) const;
+ String & operator=(const String &);
+ String operator+(const String &) const;
+ String & operator+=(const String &);
+ bool operator!=(const String &) const;
+ bool operator==(const String &) const;
+ bool operator<=(const String &) const;
+ bool operator>=(const String &) const;
+ bool operator<(const String &) const;
+ bool operator>(const String &) const;
+ char operator[](size_t i) const;
+
+ private:
+ String(int hs, const char *);
+ static char t[];
+ char * str;
+ size_t siz;
+};
+
+ostream & operator<<(ostream &, const String &);
+istream & operator>>(istream &, String &);
+
+#else
+#error This only works with a C++ compiler
+#endif
+#endif