diff options
-rw-r--r-- | src/pack.c | 178 |
1 files changed, 177 insertions, 1 deletions
@@ -24,2 +24,4 @@ #include <limits.h> +#include <arpa/inet.h> +#include <errno.h> #include "pack.h" @@ -49,2 +51,10 @@ + n An unsigned short (16-bit) in "network" (big-endian) order. + N An unsigned long (32-bit) in "network" (big-endian) order. + v An unsigned short (16-bit) in "VAX" (little-endian) order. + V An unsigned long (32-bit) in "VAX" (little-endian) order. + + f A single-precision float in native format. + d A double-precision float in native format. + x A null byte (a.k.a ASCII NUL, "\000", chr(0)) @@ -330,2 +340,162 @@ I_unpacker(struct packenv *env, int rep) +/* n - An unsigned short (16-bit) in "network" (big-endian) order. */ +static void +n_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + uintmax_t x; + if (getunum(arg, UINT16_MAX, &x) == 0) { + uint16_t v = htons((uint16_t) x); + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + } + env->buf_pos += sizeof(uint16_t); +} + +static void +n_unpacker(struct packenv *env, int rep) +{ + uint16_t v = ntohs(*(uint16_t *)(env->buf_base + env->buf_pos)); + printunum(env->fp, v); + env->buf_pos += sizeof(uint16_t); +} + +/* N - An unsigned long (32-bit) in "network" (big-endian) order. */ +static void +N_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + uintmax_t x; + if (getunum(arg, UINT32_MAX, &x) == 0) { + uint32_t v = htonl((uint32_t) x); + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + } + env->buf_pos += sizeof(uint32_t); +} + +static void +N_unpacker(struct packenv *env, int rep) +{ + uint32_t v = ntohl(*(uint32_t *)(env->buf_base + env->buf_pos)); + printunum(env->fp, v); + env->buf_pos += sizeof(uint32_t); +} + +/* v - An unsigned short (16-bit) in "VAX" (little-endian) order. */ +static void +v_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + uintmax_t x; + if (getunum(arg, UINT16_MAX, &x) == 0) { + uint16_t v = ntohs((uint16_t) x); + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + } + env->buf_pos += sizeof(uint16_t); +} + +static void +v_unpacker(struct packenv *env, int rep) +{ + uint16_t v = htons(*(uint16_t *)(env->buf_base + env->buf_pos)); + printunum(env->fp, v); + env->buf_pos += sizeof(uint16_t); +} + +/* V - An unsigned long (32-bit) in "VAX" (little-endian) order. */ +static void +V_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + uintmax_t x; + if (getunum(arg, UINT32_MAX, &x) == 0) { + uint32_t v = ntohl((uint32_t) x); + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + } + env->buf_pos += sizeof(uint32_t); +} + +static void +V_unpacker(struct packenv *env, int rep) +{ + uint32_t v = htonl(*(uint32_t *)(env->buf_base + env->buf_pos)); + printunum(env->fp, v); + env->buf_pos += sizeof(uint32_t); +} + +/* f - A single-precision float in native format. */ +static void +f_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + float v; + char *p; + + errno = 0; + v = strtof(arg, &p); + if (*p == 0 && errno == 0) + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + env->buf_pos += sizeof(float); +} + +static void +f_unpacker(struct packenv *env, int rep) +{ + float v = *(float *)(env->buf_base + env->buf_pos); + fprintf(env->fp, "%f", v); /* FIXME: Format? */ + env->buf_pos += sizeof(uint32_t); +} + +/* d - A double-precision float in native format. */ +static void +d_packer(struct packenv *env, int rep) +{ + if (env->buf_base) { + char *arg = packenv_get(env); + if (arg) { + double v; + char *p; + + errno = 0; + v = strtod(arg, &p); + if (*p == 0 && errno == 0) + memcpy(env->buf_base + env->buf_pos, + &v, sizeof(v)); + } + } + env->buf_pos += sizeof(double); +} + +static void +d_unpacker(struct packenv *env, int rep) +{ + double v = *(double *)(env->buf_base + env->buf_pos); + fprintf(env->fp, "%g", v); /* FIXME: Format? */ + env->buf_pos += sizeof(double); +} + static void @@ -395,3 +565,9 @@ static struct packspec packspec[] = { { 'I', 0, I_packer, I_unpacker }, - /* FIXME: n N v V f d */ + { 'n', 0, n_packer, n_unpacker }, + { 'N', 0, N_packer, N_unpacker }, + { 'v', 0, v_packer, v_unpacker }, + { 'V', 0, V_packer, V_unpacker }, + { 'f', 0, f_packer, f_unpacker }, + { 'd', 0, d_packer, d_unpacker }, + { 'x', 0, x_packer, x_unpacker }, |