diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-13 10:30:31 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-10-13 10:30:31 +0300 |
commit | fcc1c011757f71bb3ec1c883a19c1945fd83cf11 (patch) | |
tree | 47d6b18dffb09c86ab6041a0ac39b095dd458fbc | |
parent | 4d4fde41b23815719f8c59e27832e29766c35bf0 (diff) | |
download | vmod-binlog-fcc1c011757f71bb3ec1c883a19c1945fd83cf11.tar.gz vmod-binlog-fcc1c011757f71bb3ec1c883a19c1945fd83cf11.tar.bz2 |
Implement n, N, v, V, f, and d conversions.
-rw-r--r-- | src/pack.c | 178 |
1 files changed, 177 insertions, 1 deletions
@@ -22,6 +22,8 @@ #include <ctype.h> #include <inttypes.h> #include <limits.h> +#include <arpa/inet.h> +#include <errno.h> #include "pack.h" /* Data format specification is a simplified form of Perl pack() template. @@ -47,6 +49,14 @@ i A signed integer value. I A unsigned integer value. + 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)) X Back up a byte. @ Null-fill or truncate to absolute position, counted from the @@ -328,6 +338,166 @@ I_unpacker(struct packenv *env, int rep) env->buf_pos += sizeof(unsigned); } +/* 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 x_packer(struct packenv *env, int rep) { @@ -393,7 +563,13 @@ static struct packspec packspec[] = { { 'Q', 0, Q_packer, Q_unpacker }, { 'i', 0, i_packer, i_unpacker }, { '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 }, { 'X', 0, X_packer, X_packer }, { '@', F_REP, at_packer, at_unpacker }, |