diff options
Diffstat (limited to 'unpack.c')
-rw-r--r-- | unpack.c | 83 |
1 files changed, 38 insertions, 45 deletions
@@ -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; } |