diff options
Diffstat (limited to 'lib/Handle.cc')
-rw-r--r-- | lib/Handle.cc | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/Handle.cc b/lib/Handle.cc new file mode 100644 index 0000000..8108285 --- /dev/null +++ b/lib/Handle.cc @@ -0,0 +1,110 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include "Handle.h" +#include "config.h" + +Handle::Handle(const Handle & nh) : h(dup(nh.h)), closed(false) { } + +Handle::~Handle() { + if (h != -1) { + ::close(h); + } +} + +Handle::Handle(int nh) : h(nh), closed(false) { } + +int Handle::GetHandle() { + return h; +} + +ssize_t Handle::write(const void *buf, size_t count) throw (IOException) { + ssize_t r, tr = 0; + bool done, full = false; + + do { + done = true; + if ((r = ::write(h, buf, count)) < 0) { + if ((!errno) || (errno = EAGAIN)) { + // 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 { + sleep(1); + done = false; + full = true; + tr += r; + } + } else { + throw IOException(GetName(), IO_WRITE, count); + } + } else if (r != count) { + full = done = false; + ((char *)buf) += r; + tr += r; + } + } while (!done); + + return r + tr; +} + +ssize_t Handle::read(void *buf, size_t count) throw (IOException) { + ssize_t r; + + if ((r = ::read(h, buf, count)) < 0) { + if ((!errno) || (errno = EAGAIN)) { + // 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. + return 0; + } else { + throw IOException(GetName(), IO_READ, count); + } + } + + if (!r) { + closed = true; + } + + return r; +} + +bool Handle::IsClosed(void) { + return closed; +} + +Handle & operator<<(Handle & h, const String & s) { + 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. + // 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.set("%s", t); + return h; +} |