diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index f9c28e7..aa1a6b8 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -12,6 +12,7 @@ #include "hive_hash.h" #include "bdberl_drv.h" +#include "bin_helper.h" /** * Function prototypes @@ -199,11 +200,12 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, // Pack the status and dbref (or errno) into a binary and return it // Byte 0 : Status // Byte 1..4: dbref/errno - ErlDrvBinary* result = driver_alloc_binary(5); - result->orig_bytes[0] = status; - memcpy(result->orig_bytes+1, (char*)&dbref, sizeof(dbref)); - *outbuf = (char*)result; - return result->orig_size; + BinHelper bh; + bin_helper_init(&bh, 5); + bin_helper_push_byte(&bh, status); + bin_helper_push_int32(&bh, dbref); + *outbuf = (char*)bh.bin; + return bh.bin->orig_size; } case CMD_CLOSE_DB: { @@ -214,10 +216,11 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, int rc = close_database(dbref, d); // Setup to return the rc - ErlDrvBinary* result = driver_alloc_binary(4); - memcpy(result->orig_bytes, (char*)&rc, sizeof(rc)); - *outbuf = (char*)result; - return result->orig_size; + BinHelper bh; + bin_helper_init(&bh, 4); + bin_helper_push_int32(&bh, rc); + *outbuf = (char*)bh.bin; + return bh.bin->orig_size; } } *outbuf = 0; diff --git a/c_src/bin_helper.c b/c_src/bin_helper.c new file mode 100644 index 0000000..66fd3fa --- /dev/null +++ b/c_src/bin_helper.c @@ -0,0 +1,48 @@ +/* ------------------------------------------------------------------- + * + * bin_helper: ErlDrvBinary helper functions + * Copyright (c) 2008 The Hive. All rights reserved. + * + * ------------------------------------------------------------------- */ +#include "bin_helper.h" + +#include +#include + + +static void bin_helper_check_size(BinHelper* bh, int space_needed) +{ + if (bh->offset + space_needed > bh->bin->orig_size) + { + // Need to realloc space -- grow by 2 * space_needed + bh->bin = driver_realloc_binary(bh->bin, bh->bin->orig_size + (2 * space_needed)); + } +} + +void bin_helper_init(BinHelper* bh, unsigned int size) +{ + bh->bin = driver_alloc_binary(size); + bh->offset = 0; +} + +void bin_helper_push_byte(BinHelper* bh, int value) +{ + bin_helper_check_size(bh, 1); + bh->bin->orig_bytes[bh->offset] = (char)value; + bh->offset++; +} + +void bin_helper_push_int32(BinHelper* bh, int value) +{ + bin_helper_check_size(bh, 4); + memcpy(bh->bin->orig_bytes+(bh->offset), (char*)&value, 4); + bh->offset += 4; +} + +void bin_helper_push_string(BinHelper* bh, const char* string) +{ + int sz = strlen(string); + bin_helper_check_size(bh, sz+1); + strncpy(bh->bin->orig_bytes+(bh->offset), string, sz+1); + bh->offset += sz + 1; +} diff --git a/c_src/bin_helper.h b/c_src/bin_helper.h new file mode 100644 index 0000000..053509a --- /dev/null +++ b/c_src/bin_helper.h @@ -0,0 +1,23 @@ +/* ------------------------------------------------------------------- + * + * bin_helper: ErlDrvBinary helper functions + * Copyright (c) 2008 The Hive. All rights reserved. + * + * ------------------------------------------------------------------- */ +#ifndef _BIN_HELPER +#define _BIN_HELPER + +#include "erl_driver.h" + +typedef struct +{ + ErlDrvBinary* bin; + unsigned int offset; +} BinHelper; + +void bin_helper_init(BinHelper* bh, unsigned int size); +void bin_helper_push_byte(BinHelper* bh, int value); +void bin_helper_push_int32(BinHelper* bh, int value); +void bin_helper_push_string(BinHelper* bh, const char* string); + +#endif