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