shithub: scc

Download patch

ref: 9b0b7035bdc207bebd8cb011544d29d26b8c8a1d
parent: 544097136c80b4754ac5905f948b802fdb9e090e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Nov 17 09:38:30 EST 2017

[lib/scc] Add lpack and lunpack

These are generic functions to pack/unpack little endian strings.

--- a/inc/scc.h
+++ b/inc/scc.h
@@ -45,3 +45,5 @@
 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, ...);
--- a/lib/scc/libdep.mk
+++ b/lib/scc/libdep.mk
@@ -7,3 +7,5 @@
           $(LIBDIR)/xstrdup.o \
           $(LIBDIR)/alloc.o \
           $(LIBDIR)/casecmp.o \
+          $(LIBDIR)/lunpack.o \
+          $(LIBDIR)/lpack.o \
--- /dev/null
+++ b/lib/scc/lpack.c
@@ -1,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;
+}
--- /dev/null
+++ b/lib/scc/lunpack.c
@@ -1,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;
+}