torrentd

simple torrent daemon
git clone git://git.2f30.org/torrentd
Log | Files | Refs | LICENSE

commit d143e24f86f4e99fd78b22706c2d7354d4b73bc6
parent f6916ef2743377b69e380ef464740609d2d5a2ad
Author: sin <sin@2f30.org>
Date:   Sun, 27 Dec 2015 10:40:30 +0000

Add pack/unpack functions

Diffstat:
Mstorrent.h | 2++
Mutil.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+), 0 deletions(-)

diff --git a/storrent.h b/storrent.h @@ -111,3 +111,5 @@ size_t strlcat(char *, const char *, size_t); void initbuf(struct buf *); void freebuf(struct buf *); size_t fillbuf(struct buf *, void *, size_t); +int unpack(uint8_t *, size_t, char *, ...); +int pack(uint8_t *, size_t, char *, ...); diff --git a/util.c b/util.c @@ -5,6 +5,7 @@ #include <ctype.h> #include <err.h> #include <fcntl.h> +#include <stdarg.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -245,3 +246,125 @@ fillbuf(struct buf *b, void *ptr, size_t n) b->n += n; return b->n; } + +int +unpack(uint8_t *s, size_t n, char *fmt, ...) +{ + va_list arg; + uint8_t *b, *e; + + b = s; + e = b + n; + va_start(arg, fmt); + for (; *fmt; fmt++) { + switch (*fmt) { + case '_': + s++; + break; + case 'b': + if (s + 1 > e) + goto err; + *va_arg(arg, int *) = *s++; + break; + case 'w': + if (s + 2 > e) + goto err; + *va_arg(arg, int *) = s[0] << 8 | s[1]; + s += 2; + break; + case 'l': + if (s + 4 > e) + goto err; + *va_arg(arg, int *) = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; + s += 4; + break; + case 'v': + if (s + 4 > e) + goto err; + *va_arg(arg, long long *) = + (long long)s[0] << 56 | + (long long)s[1] << 48 | + (long long)s[2] << 40 | + (long long)s[3] << 32 | + (long long)s[4] << 24 | + (long long)s[5] << 16 | + (long long)s[6] << 8 | + (long long)s[7]; + s += 8; + break; + } + } + va_end(arg); + return s - b; +err: + va_end(arg); + return -1; +} + +int +pack(uint8_t *s, size_t n, char *fmt, ...) +{ + va_list arg; + uint8_t *b, *e; + long long v; + int i; + + b = s; + e = b + n; + va_start(arg, fmt); + for (; *fmt; fmt++) { + switch (*fmt) { + case '_': + i = 0; + if (0) { + case 'b': + i = va_arg(arg, int); + } + if (s + 1 > e) + goto err; + *s++ = i & 0xff; + break; + case 'w': + i = va_arg(arg, int); + if (s + 2 > e) + goto err; + *s++ = (i >> 8) & 0xff; + *s++ = i & 0xff; + break; + case 'l': + i = va_arg(arg, int); + if (s + 4 > e) + goto err; + *s++ = (i >> 24) & 0xff; + *s++ = (i >> 16) & 0xff; + *s++ = (i >> 8) & 0xff; + *s++ = i & 0xff; + break; + case 'v': + v = va_arg(arg, long long); + if (s + 8 > e) + goto err; + *s++ = (v >> 56) & 0xff; + *s++ = (v >> 48) & 0xff; + *s++ = (v >> 40) & 0xff; + *s++ = (v >> 32) & 0xff; + *s++ = (v >> 24) & 0xff; + *s++ = (v >> 16) & 0xff; + *s++ = (v >> 8) & 0xff; + *s++ = v & 0xff; + break; + case '*': + i = va_arg(arg, int); + if (s + i > e) + goto err; + memmove(s, va_arg(arg, void *), i); + s += i; + break; + } + } + va_end(arg); + return s - b; +err: + va_end(arg); + return -1; +}