commit d143e24f86f4e99fd78b22706c2d7354d4b73bc6
parent f6916ef2743377b69e380ef464740609d2d5a2ad
Author: sin <sin@2f30.org>
Date: Sun, 27 Dec 2015 10:40:30 +0000
Add pack/unpack functions
Diffstat:
M | storrent.h | | | 2 | ++ |
M | util.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;
+}