commit fb86ba15a8c01bb5ba1c726ecc41766211abd259
parent 74488c63a586f4c4e2ab6c5b7a3b0fde8afeb021
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 17 Nov 2017 14:38:30 +0000
[lib/scc] Add lpack and lunpack
These are generic functions to pack/unpack little endian strings.
Diffstat:
4 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/inc/scc.h b/inc/scc.h
@@ -45,3 +45,5 @@ extern void dealloc(Alloc *allocp);
extern void *new(Alloc *allocp);
extern void delete(Alloc *allocp, void *p);
extern int casecmp(const char *s1, const char *s2);
+extern int lpack(char *dst, char *fmt, ...);
+extern int lunpack(char *src, char *fmt, ...);
diff --git a/lib/scc/libdep.mk b/lib/scc/libdep.mk
@@ -7,3 +7,5 @@ LIB-OBJ = $(LIBDIR)/debug.o \
$(LIBDIR)/xstrdup.o \
$(LIBDIR)/alloc.o \
$(LIBDIR)/casecmp.o \
+ $(LIBDIR)/lunpack.o \
+ $(LIBDIR)/lpack.o \
diff --git a/lib/scc/lpack.c b/lib/scc/lpack.c
@@ -0,0 +1,52 @@
+#include <stdarg.h>
+
+#include "../../inc/scc.h"
+
+int
+lpack(char *dst, char *fmt, ...)
+{
+ char *bp;
+ unsigned s;
+ unsigned long l;
+ unsigned long long q;
+ va_list va;
+
+ bp = dst;
+ va_start(va, fmt);
+ while (*fmt) {
+ switch (*fmt++) {
+ case 'c':
+ *bp++ = va_arg(va, unsigned);
+ break;
+ case 's':
+ s = va_arg(va, unsigned);
+ *bp++ = s >> 8;
+ *bp++ = s;
+ break;
+ case 'l':
+ l = va_arg(va, unsigned long);
+ *bp++ = l >> 24;
+ *bp++ = l >> 16;
+ *bp++ = l >> 8;
+ *bp++ = l;
+ break;
+ case 'q':
+ q = va_arg(va, unsigned long long);
+ *bp++ = q >> 56;
+ *bp++ = q >> 48;
+ *bp++ = q >> 40;
+ *bp++ = q >> 32;
+ *bp++ = q >> 24;
+ *bp++ = q >> 16;
+ *bp++ = q >> 8;
+ *bp++ = q;
+ break;
+ default:
+ va_end(va);
+ return -1;
+ }
+ }
+ va_end(va);
+
+ return dst - bp;
+}
diff --git a/lib/scc/lunpack.c b/lib/scc/lunpack.c
@@ -0,0 +1,57 @@
+#include <stdarg.h>
+
+#include "../../inc/scc.h"
+
+int
+lunpack(char *src, char *fmt, ...)
+{
+ char *bp, *cp;
+ unsigned short *sp;
+ unsigned s;
+ unsigned long *lp, l;
+ unsigned long long *qp, q;
+ va_list va;
+
+ bp = src;
+ va_start(va, fmt);
+ while (*fmt) {
+ switch (*fmt++) {
+ case 'c':
+ cp = va_arg(va, unsigned char *);
+ *cp = *bp++;
+ break;
+ case 's':
+ sp = va_arg(va, unsigned short *);
+ s = (unsigned) *bp++ << 8;
+ s |= (unsigned) *bp++;
+ *sp = s;
+ break;
+ case 'l':
+ lp = va_arg(va, unsigned long *);
+ l = (unsigned long) *bp++ << 24;
+ l |= (unsigned long) *bp++ << 16;
+ l |= (unsigned long) *bp++ << 8;
+ l |= (unsigned long) *bp++;
+ *lp = l;
+ break;
+ case 'q':
+ qp = va_arg(va, unsigned long long *);
+ q = (unsigned long) *bp++ << 56;
+ q |= (unsigned long) *bp++ << 48;
+ q |= (unsigned long) *bp++ << 40;
+ q |= (unsigned long) *bp++ << 32;
+ q |= (unsigned long) *bp++ << 24;
+ q |= (unsigned long) *bp++ << 16;
+ q |= (unsigned long) *bp++ << 8;
+ q |= (unsigned long) *bp++;
+ *qp = q;
+ break;
+ default:
+ va_end(va);
+ return -1;
+ }
+ }
+ va_end(va);
+
+ return src - bp;
+}