From ee3935744b0c33758a680e0fd5214503c5c78e24 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sun, 13 Jan 2002 13:26:30 +0000 Subject: [PATCH] New hex encoding stuff. Organization: Straylight/Edgeware From: mdw --- hex.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hex.h | 109 ++++++++++++++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100644 hex.c create mode 100644 hex.h diff --git a/hex.c b/hex.c new file mode 100644 index 0000000..93bc3de --- /dev/null +++ b/hex.c @@ -0,0 +1,212 @@ +/* -*-c-*- + * + * $Id: hex.c,v 1.1 2002/01/13 13:26:30 mdw Exp $ + * + * Hexadecimal encoding and decoding. + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: hex.c,v $ + * Revision 1.1 2002/01/13 13:26:30 mdw + * New hex encoding stuff. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include "dstr.h" +#include "hex.h" + +/*----- Important tables --------------------------------------------------*/ + +static const char encodemap[] = { "0123456789abcdef" }; + +static const signed char decodemap[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 1x */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 2x */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, -1, -1, -1, -1, -1, /* 3x */ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 4x */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 5x */ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 6x */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 7x */ + }; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @hex_encode@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to a context block + * @const void *p@ = pointer to a source buffer + * @size_t sz@ = size of the source buffer + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Encodes a binary string in hex. + */ + +void hex_encode(hex_ctx *ctx, const void *p, size_t sz, dstr *d) +{ + if (p) { + const unsigned char *src = p; + + while (sz) { + unsigned x = *src++; + sz--; + DPUTC(d, encodemap[(x >> 4) & 0xf]); + DPUTC(d, encodemap[(x >> 0) & 0xf]); + ctx->lnlen += 2; + if (ctx->maxline && ctx->lnlen >= ctx->maxline) { + dstr_puts(d, ctx->indent); + ctx->lnlen = 0; + } + } + } +} + +/* --- @hex_decode@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to a context block + * @const void *p@ = pointer to a source buffer + * @size_t sz@ = size of the source buffer + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Decodes a binary string in hex. Pass in a null source + * pointer when you thing you've finished. + */ + +void hex_decode(hex_ctx *ctx, const void *p, size_t sz, dstr *d) +{ + if (p) { + unsigned long acc = ctx->acc; + unsigned qsz = ctx->qsz; + const char *src = p; + int ch; + + while (sz) { + + /* --- Get the next character and convert it --- */ + + ch = *src++; + if (ch >= 128 || ch < 0) + ch = -1; + else + ch = decodemap[ch]; + sz--; + if (ch == -1) + continue; + + /* --- Bung it in the accumulator --- */ + + acc = (acc << 4) | ch; + qsz++; + + /* --- Maybe write out a completed triplet --- */ + + if (qsz == 2) { + DPUTC(d, acc & 0xff); + acc = 0; + qsz = 0; + } + } + + ctx->acc = acc; + ctx->qsz = qsz; + } else { + if (ctx->qsz) + DPUTC(d, ctx->acc << 4); + } +} + +/* --- @hex_init@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a hex context properly. + */ + +void hex_init(hex_ctx *ctx) +{ + ctx->acc = 0; + ctx->qsz = 0; + ctx->lnlen = 0; + ctx->indent = "\n"; + ctx->maxline = 72; +} + +/*----- Test driver code --------------------------------------------------*/ + +#ifdef TEST_RIG + +int main(int argc, char *argv[]) +{ + unsigned char buf[BUFSIZ]; + dstr d = DSTR_INIT; + hex_ctx ctx; + void (*proc)(hex_ctx *, const unsigned char *, size_t, dstr *); + size_t sz; + + hex_init(&ctx); + + if (argc > 1 && strcmp(argv[1], "-d") == 0) + proc = hex_decode; + else { + proc = hex_encode; + putchar('\t'); + ctx.indent = "\n\t"; + ctx.maxline = 64; + } + + do { + sz = fread(buf, 1, sizeof(buf), stdin); + if (sz) { + proc(&ctx, buf, sz, &d); + dstr_write(&d, stdout); + dstr_destroy(&d); + } + } while (sz == sizeof(buf)); + + proc(&ctx, 0, 0, &d); + dstr_write(&d, stdout); + + if (proc == hex_encode) + putchar('\n'); + + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/hex.h b/hex.h new file mode 100644 index 0000000..6d5a8d6 --- /dev/null +++ b/hex.h @@ -0,0 +1,109 @@ +/* -*-c-*- + * + * $Id: hex.h,v 1.1 2002/01/13 13:26:30 mdw Exp $ + * + * Hexadecimal encoding and decoding + * + * (c) 2001 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the mLib utilities library. + * + * mLib is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * mLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with mLib; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: hex.h,v $ + * Revision 1.1 2002/01/13 13:26:30 mdw + * New hex encoding stuff. + * + */ + +#ifndef MLIB_HEX_H +#define MLIB_HEX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include "dstr.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct hex_ctx { + unsigned long acc; /* Accumulator for output data */ + unsigned qsz; /* Length of data queued */ + unsigned lnlen; /* Length of the current line */ + const char *indent; /* Newline-and-indent string */ + unsigned maxline; /* Maximum permitted line length */ +} hex_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @hex_encode@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to a context block + * @const void *p@ = pointer to a source buffer + * @size_t sz@ = size of the source buffer + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Encodes a binary string in hex. + */ + +extern void hex_encode(hex_ctx */*ctx*/, const void */*p*/, size_t /*sz*/, + dstr */*d*/); + +/* --- @hex_decode@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to a context block + * @const void *p@ = pointer to a source buffer + * @size_t sz@ = size of the source buffer + * @dstr *d@ = pointer to destination string + * + * Returns: --- + * + * Use: Decodes a binary string in hex. Pass in a null source + * pointer when you thing you've finished. + */ + +extern void hex_decode(hex_ctx */*ctx*/, const void */*p*/, size_t /*sz*/, + dstr */*d*/); + +/* --- @hex_init@ --- * + * + * Arguments: @hex_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a hex context properly. + */ + +extern void hex_init(hex_ctx */*ctx*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif -- [mdw]