diff options
-rw-r--r-- | common.h | 12 | ||||
-rw-r--r-- | pack.c | 34 | ||||
-rw-r--r-- | unpack.c | 83 |
3 files changed, 65 insertions, 64 deletions
@@ -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 @@ -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; } @@ -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; } |