aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.h12
-rw-r--r--pack.c34
-rw-r--r--unpack.c83
3 files changed, 65 insertions, 64 deletions
diff --git a/common.h b/common.h
index 183392a..f22f588 100644
--- a/common.h
+++ b/common.h
@@ -24,6 +24,18 @@
#endif
#endif
+#define ITYPE_MACROS \
+ T(SCHAR, signed, char, int) \
+ T(UCHAR, unsigned, char, int) \
+ T(SHORT, signed, short, int) \
+ T(USHORT, unsigned, short, int) \
+ T(INT, signed, int, int) \
+ T(UINT, unsigned, int, int) \
+ T(LONG, signed, long, long) \
+ T(ULONG, unsigned, long, long) \
+ T(LLONG, signed, long long, long long) \
+ T(ULLONG, unsigned, long long, long long)
+
size_t getsize(enum pack_type t);
#endif // !PACK_COMMON_H
diff --git a/pack.c b/pack.c
index 9d7046c..f06aafe 100644
--- a/pack.c
+++ b/pack.c
@@ -32,23 +32,19 @@ enum pack_status pack(void *buf_, size_t size, const char *fmt, ...)
for (int i = 0; fmt[i] != '\0'; i++) {
bool sign;
size_t s;
- union { uintmax_t u; intmax_t s; } val;
+ union { uintmax_t unsigned_; intmax_t signed_; } v;
tr_debug("i: %d, fmt[i]: %c", i, fmt[i]);
sign = islower(fmt[i]);
switch (fmt[i]) {
case '>': endianness = PACK_ENDIAN_BIG; continue;
case '<': endianness = PACK_ENDIAN_LITTLE; continue;
- case PACK_TYPE_SCHAR: val.s = va_arg(ap, int); break;
- case PACK_TYPE_UCHAR: val.u = va_arg(ap, unsigned); break;
- case PACK_TYPE_SHORT: val.s = va_arg(ap, int); break;
- case PACK_TYPE_USHORT: val.u = va_arg(ap, unsigned); break;
- case PACK_TYPE_INT: val.s = va_arg(ap, int); break;
- case PACK_TYPE_UINT: val.u = va_arg(ap, unsigned); break;
- case PACK_TYPE_LONG: val.s = va_arg(ap, long); break;
- case PACK_TYPE_ULONG: val.u = va_arg(ap, unsigned long); break;
- case PACK_TYPE_LLONG: val.s = va_arg(ap, long long); break;
- case PACK_TYPE_ULLONG: val.u = va_arg(ap, unsigned long long); break;
- case PACK_TYPE_PADDING: val.u = 0; sign = false; break;
+ #define T(type, sign, c_type, va_type) \
+ case (char)PACK_TYPE_##type: \
+ v.sign##_ = va_arg(ap, sign va_type); \
+ break;
+ ITYPE_MACROS
+ #undef T
+ case 'x': v.unsigned_ = 0; sign = false; break;
default: return PACK_FMTINVAL;
}
tr_debug("i: %d, fmt[i]: %c, sign: %ssigned", i, fmt[i], sign ? "" : "un");
@@ -60,18 +56,18 @@ enum pack_status pack(void *buf_, size_t size, const char *fmt, ...)
if (size - offset < s) return PACK_TOOSMALL;
if (sign) {
- intmax_t n = val.s;
- tr_debug("val.s: %" PRIdMAX, val.s);
- if (val.s >= 0) {
- val.u = n;
+ intmax_t n = v.signed_;
+ tr_debug("val.s: %" PRIdMAX, v.signed_);
+ if (v.signed_ >= 0) {
+ v.unsigned_ = n;
} else {
uintmax_t offt = BITMASK(s * 8);
n += 1;
- val.u = offt + n;
+ v.unsigned_ = offt + n;
}
}
- tr_debug("val.u: %" PRIuMAX, val.u);
- write_val(&buf[offset], s, endianness, val.u);
+ tr_debug("val.u: %" PRIuMAX, v.unsigned_);
+ write_val(&buf[offset], s, endianness, v.unsigned_);
offset += s;
}
diff --git a/unpack.c b/unpack.c
index 467b6bf..c33ff36 100644
--- a/unpack.c
+++ b/unpack.c
@@ -51,20 +51,19 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...)
bool sign;
size_t count = 1, s;
union {
- signed char *b;
- unsigned char *B;
- short *h;
- unsigned short *H;
- int *i;
- unsigned int *I;
- long *l;
- unsigned long *L;
- long long *q;
- unsigned long long *Q;
- float *f;
- double *d;
+ #define T(type, sign, c_type, va_type) \
+ sign c_type *type;
+ ITYPE_MACROS
+ #undef T
+ float *f;
+ double *d;
} arg;
- union { uintmax_t u; intmax_t s; float f; double d; } val;
+ union {
+ uintmax_t unsigned_;
+ intmax_t signed_;
+ float f;
+ double d;
+ } val;
tr_debug("i: %d, fmt[i]: %c", i, fmt[i]);
if (isdigit(fmt[i])) {
unsigned long long c;
@@ -86,19 +85,15 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...)
switch (fmt[i]) {
case '>': endianness = PACK_ENDIAN_BIG; continue;
case '<': endianness = PACK_ENDIAN_LITTLE; continue;
- case PACK_TYPE_UCHAR: arg.b = va_arg(ap, signed char *); break;
- case PACK_TYPE_SCHAR: arg.B = va_arg(ap, unsigned char *); break;
- case PACK_TYPE_SHORT: arg.h = va_arg(ap, short *); break;
- case PACK_TYPE_USHORT: arg.H = va_arg(ap, unsigned short *); break;
- case PACK_TYPE_INT: arg.i = va_arg(ap, int *); break;
- case PACK_TYPE_UINT: arg.I = va_arg(ap, unsigned *); break;
- case PACK_TYPE_LONG: arg.l = va_arg(ap, long *); break;
- case PACK_TYPE_ULONG: arg.L = va_arg(ap, unsigned long *); break;
- case PACK_TYPE_LLONG: arg.q = va_arg(ap, long long *); break;
- case PACK_TYPE_ULLONG: arg.Q = va_arg(ap, unsigned long long *); break;
- case PACK_TYPE_FLOAT: arg.f = va_arg(ap, float *); break;
- case PACK_TYPE_DOUBLE: arg.d = va_arg(ap, double *); break;
- case PACK_TYPE_PADDING: break;
+ #define T(type, sign, c_type, va_type) \
+ case (char)PACK_TYPE_##type: \
+ arg.type = va_arg(ap, sign c_type *); \
+ break;
+ ITYPE_MACROS
+ #undef T
+ case 'f': arg.f = va_arg(ap, float *); break;
+ case 'd': arg.d = va_arg(ap, double *); break;
+ case 'x': break;
default: return PACK_FMTINVAL;
}
@@ -111,40 +106,38 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...)
if (fmt[i] == 'x') goto skip;
for (size_t j = 0; j < count; j++) {
- val.u = read_val(buf + offset + s * j, s, endianness);
- tr_debug("val.u: %" PRIuMAX ", at: %" PRIuSIZE, val.u, offset + s * j);
+ val.unsigned_ =
+ read_val(buf + offset + s * j, s, endianness);
+ tr_debug("val.u: %" PRIuMAX ", at: %" PRIuSIZE,
+ val.unsigned_, offset + s * j);
if (fmt[i] == 'f') {
- float f = ieee754b32_deserialise(val.u);
+ float f = ieee754b32_deserialise(val.unsigned_);
val.f = f;
tr_debug("val.f: %f", val.f);
} else if (fmt[i] == 'd') {
- double d = ieee754b64_deserialise(val.u);
+ double d = ieee754b64_deserialise(val.unsigned_);
val.d = d;
tr_debug("val.d: %f", val.d);
} else if (sign) {
intmax_t vals;
- if (!(val.u & (UINTMAX_C(1) << (s * 8 - 1)))) {
- vals = val.u;
+ if (!(val.unsigned_ & (UINTMAX_C(1) << (s * 8 - 1)))) {
+ vals = val.unsigned_;
} else {
vals = minval(s);
- vals += val.u ^ (UINTMAX_C(1) << (s * 8 - 1));
+ vals += val.unsigned_ ^ (UINTMAX_C(1) << (s * 8 - 1));
}
- val.s = vals;
- tr_debug("val.s: %" PRIdMAX, val.s);
+ val.signed_ = vals;
+ tr_debug("val.s: %" PRIdMAX, val.signed_);
}
switch (fmt[i]) {
- case 'b': arg.b[j] = val.s; break;
- case 'B': arg.B[j] = val.u; break;
- case 'h': arg.h[j] = val.s; break;
- case 'H': arg.H[j] = val.u; break;
- case 'i': arg.i[j] = val.s; break;
- case 'I': arg.I[j] = val.u; break;
- case 'l': arg.l[j] = val.s; break;
- case 'L': arg.L[j] = val.u; break;
- case 'q': arg.q[j] = val.s; break;
- case 'Q': arg.Q[j] = val.u; break;
+ #define T(type, sign, c_type, va_type) \
+ case (char)PACK_TYPE_##type: \
+ arg.type[j] = val.sign##_; \
+ break;
+ ITYPE_MACROS
+ #undef T
case 'f': arg.f[j] = val.f; break;
case 'd': arg.d[j] = val.d; break;
}