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