diff options
author | David Wragg <david@rabbitmq.com> | 2010-10-21 17:49:04 +0100 |
---|---|---|
committer | David Wragg <david@rabbitmq.com> | 2010-10-21 17:49:04 +0100 |
commit | 0d25d02e769dca4ced51580a7d47061717da2bec (patch) | |
tree | 8d5ccaaf6af7f70278b4cb9711ecea24ed4239d5 | |
parent | 905b591638861dafd76d6c9525bf7d9edf64f81f (diff) | |
download | rabbitmq-c-github-ask-0d25d02e769dca4ced51580a7d47061717da2bec.tar.gz |
Introduce new codec helper inline functions; convert amqp_table.c
These replace the macros that relied on gccisms.
-rw-r--r-- | librabbitmq/amqp.h | 5 | ||||
-rw-r--r-- | librabbitmq/amqp_connection.c | 2 | ||||
-rw-r--r-- | librabbitmq/amqp_private.h | 114 | ||||
-rw-r--r-- | librabbitmq/amqp_socket.c | 2 | ||||
-rw-r--r-- | librabbitmq/amqp_table.c | 497 |
5 files changed, 357 insertions, 263 deletions
diff --git a/librabbitmq/amqp.h b/librabbitmq/amqp.h index f08990b..03072bc 100644 --- a/librabbitmq/amqp.h +++ b/librabbitmq/amqp.h @@ -68,7 +68,7 @@ typedef struct amqp_bytes_t_ { #define AMQP_EMPTY_BYTES ((amqp_bytes_t) { .len = 0, .bytes = NULL }) typedef struct amqp_decimal_t_ { - int decimals; + uint8_t decimals; uint32_t value; } amqp_decimal_t; @@ -128,7 +128,7 @@ the code. */ typedef struct amqp_field_value_t_ { - char kind; + uint8_t kind; union { amqp_boolean_t boolean; int8_t i8; @@ -162,6 +162,7 @@ typedef enum { AMQP_FIELD_KIND_I32 = 'I', AMQP_FIELD_KIND_U32 = 'i', AMQP_FIELD_KIND_I64 = 'l', + AMQP_FIELD_KIND_U64 = 'L', AMQP_FIELD_KIND_F32 = 'f', AMQP_FIELD_KIND_F64 = 'd', AMQP_FIELD_KIND_DECIMAL = 'D', diff --git a/librabbitmq/amqp_connection.c b/librabbitmq/amqp_connection.c index 3d95e98..0bac627 100644 --- a/librabbitmq/amqp_connection.c +++ b/librabbitmq/amqp_connection.c @@ -58,8 +58,6 @@ #include "amqp_framing.h" #include "amqp_private.h" -#include "socket.h" - #define INITIAL_FRAME_POOL_PAGE_SIZE 65536 #define INITIAL_DECODING_POOL_PAGE_SIZE 131072 #define INITIAL_INBOUND_SOCK_BUFFER_SIZE 131072 diff --git a/librabbitmq/amqp_private.h b/librabbitmq/amqp_private.h index 9d7c4e5..905c638 100644 --- a/librabbitmq/amqp_private.h +++ b/librabbitmq/amqp_private.h @@ -53,10 +53,6 @@ #include "config.h" -#ifdef __cplusplus -extern "C" { -#endif - /* Error numbering: Because of differences in error numbering on * different platforms, we want to keep error numbers opaque for * client code. Internally, we encode the category of an error @@ -80,6 +76,8 @@ extern "C" { extern char *amqp_os_error_string(int err); +#include "socket.h" + /* * Connection states: * @@ -148,6 +146,106 @@ struct amqp_connection_state_t_ { amqp_rpc_reply_t most_recent_api_result; }; +static inline void *amqp_offset(void *data, size_t offset) +{ + return (char *)data + offset; +} + +/* assuming a machine that supports unaligned accesses (for now) */ + +#define DECLARE_CODEC_BASE_TYPE(bits, htonx, ntohx) \ + \ +static inline void amqp_e##bits(void *data, size_t offset, \ + uint##bits##_t val) \ +{ \ + *(uint##bits##_t *)amqp_offset(data, offset) = htonx(val); \ +} \ + \ +static inline uint##bits##_t amqp_d##bits(void *data, size_t offset) \ +{ \ + return ntohx(*(uint##bits##_t *)amqp_offset(data, offset)); \ +} \ + \ +static inline int amqp_encode_##bits(amqp_bytes_t encoded, size_t *offset, \ + uint##bits##_t input) \ + \ +{ \ + size_t o = *offset; \ + if ((*offset = o + bits / 8) <= encoded.len) { \ + amqp_e##bits(encoded.bytes, o, input); \ + return 1; \ + } \ + else { \ + return 0; \ + } \ +} \ + \ +static inline int amqp_decode_##bits(amqp_bytes_t encoded, size_t *offset, \ + uint##bits##_t *output) \ + \ +{ \ + size_t o = *offset; \ + if ((*offset = o + bits / 8) <= encoded.len) { \ + *output = amqp_d##bits(encoded.bytes, o); \ + *output = ntohx(*(uint##bits##_t *)((char *)encoded.bytes + o)); \ + return 1; \ + } \ + else { \ + return 0; \ + } \ +} + +/* assuming little endian (for now) */ + +#define DECLARE_XTOXLL(func) \ +static inline uint64_t func##ll(uint64_t val) \ +{ \ + union { \ + uint64_t whole; \ + uint32_t halves[2]; \ + } u = { val }; \ + uint32_t t = u.halves[0]; \ + u.halves[0] = func##l(u.halves[1]); \ + u.halves[1] = func##l(t); \ + return u.whole; \ +} + +DECLARE_XTOXLL(hton) +DECLARE_XTOXLL(ntoh) + +DECLARE_CODEC_BASE_TYPE(8,,) +DECLARE_CODEC_BASE_TYPE(16, htons, ntohs) +DECLARE_CODEC_BASE_TYPE(32, htonl, ntohl) +DECLARE_CODEC_BASE_TYPE(64, htonll, ntohll) + +static inline int amqp_encode_bytes(amqp_bytes_t encoded, size_t *offset, + amqp_bytes_t input) +{ + size_t o = *offset; + if ((*offset = o + input.len) <= encoded.len) { + memcpy(amqp_offset(encoded.bytes, o), input.bytes, input.len); + return 1; + } + else { + return 0; + } +} + +static inline int amqp_decode_bytes(amqp_bytes_t encoded, size_t *offset, + amqp_bytes_t *output, size_t len) +{ + size_t o = *offset; + if ((*offset = o + len) <= encoded.len) { + output->bytes = amqp_offset(encoded.bytes, o); + output->len = len; + return 1; + } + else { + return 0; + } +} + + #define CHECK_LIMIT(b, o, l, v) ({ if ((o + l) > (b).len) { return -ERROR_BAD_AMQP_DATA; } (v); }) #define BUF_AT(b, o) (&(((uint8_t *) (b).bytes)[o])) @@ -175,11 +273,11 @@ struct amqp_connection_state_t_ { extern int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_table_t *output, - int *offsetptr); + size_t *offset); extern int amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input, - int *offsetptr); + size_t *offset); #define amqp_assert(condition, ...) \ ({ \ @@ -205,8 +303,4 @@ extern void amqp_dump(void const *buffer, size_t len); #define amqp_dump(buffer, len) ((void) 0) #endif -#ifdef __cplusplus -} -#endif - #endif diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c index 13f6376..42fe446 100644 --- a/librabbitmq/amqp_socket.c +++ b/librabbitmq/amqp_socket.c @@ -59,8 +59,6 @@ #include "amqp_framing.h" #include "amqp_private.h" -#include "socket.h" - int amqp_open_socket(char const *hostname, int portnumber) diff --git a/librabbitmq/amqp_table.c b/librabbitmq/amqp_table.c index 3f5eb61..e85217f 100644 --- a/librabbitmq/amqp_table.c +++ b/librabbitmq/amqp_table.c @@ -55,7 +55,6 @@ #include "amqp.h" #include "amqp_private.h" -#include "socket.h" #include <assert.h> @@ -65,356 +64,360 @@ static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_field_value_t *entry, - int *offsetptr); /* forward */ + size_t *offset); static int amqp_encode_field_value(amqp_bytes_t encoded, amqp_field_value_t *entry, - int *offsetptr); /* forward */ + size_t *offset); /*---------------------------------------------------------------------------*/ static int amqp_decode_array(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_array_t *output, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; - uint32_t arraysize = D_32(encoded, offset); + uint32_t arraysize; int num_entries = 0; - amqp_field_value_t *entries = malloc(INITIAL_ARRAY_SIZE * sizeof(amqp_field_value_t)); int allocated_entries = INITIAL_ARRAY_SIZE; - int limit; + amqp_field_value_t *entries; + size_t limit; + int res; - if (entries == NULL) { - return -ERROR_NO_MEMORY; - } + if (!amqp_decode_32(encoded, offset, &arraysize)) + return -ERROR_BAD_AMQP_DATA; - offset += 4; - limit = offset + arraysize; + entries = malloc(allocated_entries * sizeof(amqp_field_value_t)); + if (entries == NULL) + return -ERROR_NO_MEMORY; - while (offset < limit) { + limit = *offset + arraysize; + while (*offset < limit) { if (num_entries >= allocated_entries) { void *newentries; allocated_entries = allocated_entries * 2; newentries = realloc(entries, allocated_entries * sizeof(amqp_field_value_t)); - if (newentries == NULL) { - free(entries); - return -ERROR_NO_MEMORY; - } + res = -ERROR_NO_MEMORY; + if (newentries == NULL) + goto out; + entries = newentries; } - AMQP_CHECK_RESULT_CLEANUP(amqp_decode_field_value(encoded, - pool, - &entries[num_entries], - &offset), - free(entries)); + res = amqp_decode_field_value(encoded, pool, &entries[num_entries], + offset); + if (res < 0) + goto out; + num_entries++; } output->num_entries = num_entries; output->entries = amqp_pool_alloc(pool, num_entries * sizeof(amqp_field_value_t)); - if (output->entries == NULL && num_entries > 0) { - /* NULL is legitimate if we requested a zero-length block. */ - free(entries); - return -ERROR_NO_MEMORY; - } + res = -ERROR_NO_MEMORY; + /* NULL is legitimate if we requested a zero-length block. */ + if (output->entries == NULL && num_entries > 0) + goto out; memcpy(output->entries, entries, num_entries * sizeof(amqp_field_value_t)); - free(entries); + res = 0; - *offsetptr = offset; - return 0; + out: + free(entries); + return res; } int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_table_t *output, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; - uint32_t tablesize = D_32(encoded, offset); + uint32_t tablesize; int num_entries = 0; - amqp_table_entry_t *entries = malloc(INITIAL_TABLE_SIZE * sizeof(amqp_table_entry_t)); + amqp_table_entry_t *entries; int allocated_entries = INITIAL_TABLE_SIZE; - int limit; + size_t limit; + int res; - if (entries == NULL) { - return -ERROR_NO_MEMORY; - } + if (!amqp_decode_32(encoded, offset, &tablesize)) + return -ERROR_BAD_AMQP_DATA; - offset += 4; - limit = offset + tablesize; + entries = malloc(allocated_entries * sizeof(amqp_table_entry_t)); + if (entries == NULL) + return -ERROR_NO_MEMORY; - while (offset < limit) { - size_t keylen; - amqp_table_entry_t *entry; + limit = *offset + tablesize; + while (*offset < limit) { + uint8_t keylen; - keylen = D_8(encoded, offset); - offset++; + res = -ERROR_BAD_AMQP_DATA; + if (!amqp_decode_8(encoded, offset, &keylen)) + goto out; if (num_entries >= allocated_entries) { void *newentries; allocated_entries = allocated_entries * 2; newentries = realloc(entries, allocated_entries * sizeof(amqp_table_entry_t)); - if (newentries == NULL) { - free(entries); - return -ERROR_NO_MEMORY; - } + res = -ERROR_NO_MEMORY; + if (newentries == NULL) + goto out; + entries = newentries; } - entry = &entries[num_entries]; - entry->key.len = keylen; - entry->key.bytes = D_BYTES(encoded, offset, keylen); - offset += keylen; + res = -ERROR_BAD_AMQP_DATA; + if (!amqp_decode_bytes(encoded, offset, &entries[num_entries].key, keylen)) + goto out; + + res = amqp_decode_field_value(encoded, pool, &entries[num_entries].value, + offset); + if (res < 0) + goto out; - AMQP_CHECK_RESULT_CLEANUP(amqp_decode_field_value(encoded, - pool, - &entry->value, - &offset), - free(entries)); num_entries++; } output->num_entries = num_entries; output->entries = amqp_pool_alloc(pool, num_entries * sizeof(amqp_table_entry_t)); - if (output->entries == NULL && num_entries > 0) { - /* NULL is legitimate if we requested a zero-length block. */ - free(entries); - return -ERROR_NO_MEMORY; - } + res = -ERROR_NO_MEMORY; + /* NULL is legitimate if we requested a zero-length block. */ + if (output->entries == NULL && num_entries > 0) + goto out; memcpy(output->entries, entries, num_entries * sizeof(amqp_table_entry_t)); - free(entries); + res = 0; - *offsetptr = offset; - return 0; + out: + free(entries); + return res; } static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_field_value_t *entry, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; + int res = -ERROR_BAD_AMQP_DATA; - entry->kind = D_8(encoded, offset); - offset++; + if (!amqp_decode_8(encoded, offset, &entry->kind)) + goto out; + +#define TRIVIAL_FIELD_DECODER(bits) if (!amqp_decode_##bits(encoded, offset, &entry->value.u##bits)) goto out; break +#define SIMPLE_FIELD_DECODER(bits, dest, how) { uint##bits##_t val; if (!amqp_decode_##bits(encoded, offset, &val)) goto out; entry->value.dest = how; } break switch (entry->kind) { - case AMQP_FIELD_KIND_BOOLEAN: - entry->value.boolean = D_8(encoded, offset) ? 1 : 0; - offset++; - break; - case AMQP_FIELD_KIND_I8: - entry->value.i8 = (int8_t) D_8(encoded, offset); - offset++; - break; - case AMQP_FIELD_KIND_U8: - entry->value.u8 = D_8(encoded, offset); - offset++; - break; - case AMQP_FIELD_KIND_I16: - entry->value.i16 = (int16_t) D_16(encoded, offset); - offset += 2; - break; - case AMQP_FIELD_KIND_U16: - entry->value.u16 = D_16(encoded, offset); - offset += 2; - break; - case AMQP_FIELD_KIND_I32: - entry->value.i32 = (int32_t) D_32(encoded, offset); - offset += 4; - break; - case AMQP_FIELD_KIND_U32: - entry->value.u32 = D_32(encoded, offset); - offset += 4; - break; - case AMQP_FIELD_KIND_I64: - entry->value.i64 = (int64_t) D_64(encoded, offset); - offset += 8; - break; - case AMQP_FIELD_KIND_F32: - entry->value.u32 = D_32(encoded, offset); - /* and by punning, f32 magically gets the right value...! */ - offset += 4; - break; - case AMQP_FIELD_KIND_F64: - entry->value.u64 = D_64(encoded, offset); - /* and by punning, f64 magically gets the right value...! */ - offset += 8; - break; - case AMQP_FIELD_KIND_DECIMAL: - entry->value.decimal.decimals = D_8(encoded, offset); - offset++; - entry->value.decimal.value = D_32(encoded, offset); - offset += 4; - break; - case AMQP_FIELD_KIND_UTF8: - /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the - same implementation, but different interpretations. */ - /* fall through */ - case AMQP_FIELD_KIND_BYTES: - entry->value.bytes.len = D_32(encoded, offset); - offset += 4; - entry->value.bytes.bytes = D_BYTES(encoded, offset, entry->value.bytes.len); - offset += entry->value.bytes.len; - break; - case AMQP_FIELD_KIND_ARRAY: - AMQP_CHECK_RESULT(amqp_decode_array(encoded, pool, &(entry->value.array), &offset)); - break; - case AMQP_FIELD_KIND_TIMESTAMP: - entry->value.u64 = D_64(encoded, offset); - offset += 8; - break; - case AMQP_FIELD_KIND_TABLE: - AMQP_CHECK_RESULT(amqp_decode_table(encoded, pool, &(entry->value.table), &offset)); - break; - case AMQP_FIELD_KIND_VOID: - break; - default: - return -ERROR_BAD_AMQP_DATA; + case AMQP_FIELD_KIND_BOOLEAN: + SIMPLE_FIELD_DECODER(8, boolean, val ? 1 : 0); + + case AMQP_FIELD_KIND_I8: + SIMPLE_FIELD_DECODER(8, i8, (int8_t)val); + case AMQP_FIELD_KIND_U8: + TRIVIAL_FIELD_DECODER(8); + + case AMQP_FIELD_KIND_I16: + SIMPLE_FIELD_DECODER(16, i16, (int16_t)val); + case AMQP_FIELD_KIND_U16: + TRIVIAL_FIELD_DECODER(16); + + case AMQP_FIELD_KIND_I32: + SIMPLE_FIELD_DECODER(32, i32, (int32_t)val); + case AMQP_FIELD_KIND_U32: + TRIVIAL_FIELD_DECODER(32); + + case AMQP_FIELD_KIND_I64: + SIMPLE_FIELD_DECODER(64, i64, (int64_t)val); + case AMQP_FIELD_KIND_U64: + TRIVIAL_FIELD_DECODER(64); + + case AMQP_FIELD_KIND_F32: + TRIVIAL_FIELD_DECODER(32); + /* and by punning, f32 magically gets the right value...! */ + + case AMQP_FIELD_KIND_F64: + TRIVIAL_FIELD_DECODER(64); + /* and by punning, f64 magically gets the right value...! */ + + case AMQP_FIELD_KIND_DECIMAL: + if (!amqp_decode_8(encoded, offset, &entry->value.decimal.decimals) + || !amqp_decode_32(encoded, offset, &entry->value.decimal.value)) + goto out; + break; + + case AMQP_FIELD_KIND_UTF8: + /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the + same implementation, but different interpretations. */ + /* fall through */ + case AMQP_FIELD_KIND_BYTES: { + uint32_t len; + if (!amqp_decode_32(encoded, offset, &len) + || !amqp_decode_bytes(encoded, offset, &entry->value.bytes, len)) + goto out; + break; } - *offsetptr = offset; - return 0; + case AMQP_FIELD_KIND_ARRAY: + res = amqp_decode_array(encoded, pool, &(entry->value.array), offset); + goto out; + + case AMQP_FIELD_KIND_TIMESTAMP: + TRIVIAL_FIELD_DECODER(64); + + case AMQP_FIELD_KIND_TABLE: + res = amqp_decode_table(encoded, pool, &(entry->value.table), offset); + goto out; + + case AMQP_FIELD_KIND_VOID: + break; + + default: + goto out; + } + + res = 0; + + out: + return res; } /*---------------------------------------------------------------------------*/ static int amqp_encode_array(amqp_bytes_t encoded, amqp_array_t *input, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; - int arraysize_offset = offset; - int i; + size_t start = *offset; + int i, res; - offset += 4; /* skip space for the size of the array to be filled in later */ + *offset += 4; /* size of the array gets filled in later on */ for (i = 0; i < input->num_entries; i++) { - AMQP_CHECK_RESULT(amqp_encode_field_value(encoded, &(input->entries[i]), &offset)); + res = amqp_encode_field_value(encoded, &input->entries[i], offset); + if (res < 0) + goto out; } - E_32(encoded, arraysize_offset, (offset - *offsetptr - 4)); - *offsetptr = offset; - return 0; + if (amqp_encode_32(encoded, &start, *offset - start - 4)) + res = 0; + else + res = -ERROR_BAD_AMQP_DATA; + + out: + return res; } int amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; - int tablesize_offset = offset; - int i; + size_t start = *offset; + int i, res; - offset += 4; /* skip space for the size of the table to be filled in later */ + *offset += 4; /* size of the table gets filled in later on */ for (i = 0; i < input->num_entries; i++) { - amqp_table_entry_t *entry = &(input->entries[i]); - - E_8(encoded, offset, entry->key.len); - offset++; + res = amqp_encode_8(encoded, offset, input->entries[i].key.len); + if (res < 0) + goto out; - E_BYTES(encoded, offset, entry->key.len, entry->key.bytes); - offset += entry->key.len; + res = amqp_encode_bytes(encoded, offset, input->entries[i].key); + if (res < 0) + goto out; - AMQP_CHECK_RESULT(amqp_encode_field_value(encoded, &(entry->value), &offset)); + res = amqp_encode_field_value(encoded, &input->entries[i].value, offset); + if (res < 0) + goto out; } - E_32(encoded, tablesize_offset, (offset - *offsetptr - 4)); - *offsetptr = offset; - return 0; + if (amqp_encode_32(encoded, &start, *offset - start - 4)) + res = 0; + else + res = -ERROR_BAD_AMQP_DATA; + + out: + return res; } static int amqp_encode_field_value(amqp_bytes_t encoded, amqp_field_value_t *entry, - int *offsetptr) + size_t *offset) { - int offset = *offsetptr; + int res = -ERROR_BAD_AMQP_DATA; + + if (!amqp_encode_8(encoded, offset, entry->kind)) + goto out; - E_8(encoded, offset, entry->kind); - offset++; +#define FIELD_ENCODER(bits, val) if (!amqp_encode_##bits(encoded, offset, val)) goto out; break switch (entry->kind) { - case AMQP_FIELD_KIND_BOOLEAN: - E_8(encoded, offset, entry->value.boolean ? 1 : 0); - offset++; - break; - case AMQP_FIELD_KIND_I8: - E_8(encoded, offset, (uint8_t) entry->value.i8); - offset++; - break; - case AMQP_FIELD_KIND_U8: - E_8(encoded, offset, entry->value.u8); - offset++; - break; - case AMQP_FIELD_KIND_I16: - E_16(encoded, offset, (uint16_t) entry->value.i16); - offset += 2; - break; - case AMQP_FIELD_KIND_U16: - E_16(encoded, offset, entry->value.u16); - offset += 2; - break; - case AMQP_FIELD_KIND_I32: - E_32(encoded, offset, (uint32_t) entry->value.i32); - offset += 4; - break; - case AMQP_FIELD_KIND_U32: - E_32(encoded, offset, entry->value.u32); - offset += 4; - break; - case AMQP_FIELD_KIND_I64: - E_64(encoded, offset, (uint64_t) entry->value.i64); - offset += 8; - break; - case AMQP_FIELD_KIND_F32: - /* by punning, u32 magically gets the right value...! */ - E_32(encoded, offset, entry->value.u32); - offset += 4; - break; - case AMQP_FIELD_KIND_F64: - /* by punning, u64 magically gets the right value...! */ - E_64(encoded, offset, entry->value.u64); - offset += 8; - break; - case AMQP_FIELD_KIND_DECIMAL: - E_8(encoded, offset, entry->value.decimal.decimals); - offset++; - E_32(encoded, offset, entry->value.decimal.value); - offset += 4; - break; - case AMQP_FIELD_KIND_UTF8: - /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the - same implementation, but different interpretations. */ - /* fall through */ - case AMQP_FIELD_KIND_BYTES: - E_32(encoded, offset, entry->value.bytes.len); - offset += 4; - E_BYTES(encoded, offset, entry->value.bytes.len, entry->value.bytes.bytes); - offset += entry->value.bytes.len; - break; - case AMQP_FIELD_KIND_ARRAY: - AMQP_CHECK_RESULT(amqp_encode_array(encoded, &(entry->value.array), &offset)); - break; - case AMQP_FIELD_KIND_TIMESTAMP: - E_64(encoded, offset, entry->value.u64); - offset += 8; - break; - case AMQP_FIELD_KIND_TABLE: - AMQP_CHECK_RESULT(amqp_encode_table(encoded, &(entry->value.table), &offset)); - break; - case AMQP_FIELD_KIND_VOID: - break; - default: - abort(); + case AMQP_FIELD_KIND_BOOLEAN: + FIELD_ENCODER(8, entry->value.boolean ? 1 : 0); + + case AMQP_FIELD_KIND_I8: + FIELD_ENCODER(8, entry->value.i8); + case AMQP_FIELD_KIND_U8: + FIELD_ENCODER(8, entry->value.u8); + + case AMQP_FIELD_KIND_I16: + FIELD_ENCODER(16, entry->value.i16); + case AMQP_FIELD_KIND_U16: + FIELD_ENCODER(16, entry->value.u16); + + case AMQP_FIELD_KIND_I32: + FIELD_ENCODER(32, entry->value.i32); + case AMQP_FIELD_KIND_U32: + FIELD_ENCODER(32, entry->value.u32); + + case AMQP_FIELD_KIND_I64: + FIELD_ENCODER(64, entry->value.i64); + case AMQP_FIELD_KIND_U64: + FIELD_ENCODER(64, entry->value.u64); + + case AMQP_FIELD_KIND_F32: + /* by punning, u32 magically gets the right value...! */ + FIELD_ENCODER(32, entry->value.u32); + + case AMQP_FIELD_KIND_F64: + /* by punning, u64 magically gets the right value...! */ + FIELD_ENCODER(64, entry->value.u64); + + case AMQP_FIELD_KIND_DECIMAL: + if (!amqp_encode_8(encoded, offset, entry->value.decimal.decimals) + || !amqp_encode_32(encoded, offset, entry->value.decimal.value)) + goto out; + break; + + case AMQP_FIELD_KIND_UTF8: + /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the + same implementation, but different interpretations. */ + /* fall through */ + case AMQP_FIELD_KIND_BYTES: + if (!amqp_encode_32(encoded, offset, entry->value.bytes.len) + || !amqp_encode_bytes(encoded, offset, entry->value.bytes)) + goto out; + break; + + case AMQP_FIELD_KIND_ARRAY: + res = amqp_encode_array(encoded, &entry->value.array, offset); + goto out; + + case AMQP_FIELD_KIND_TIMESTAMP: + FIELD_ENCODER(64, entry->value.u64); + + case AMQP_FIELD_KIND_TABLE: + res = amqp_encode_table(encoded, &entry->value.table, offset); + goto out; + + case AMQP_FIELD_KIND_VOID: + break; + + default: + abort(); } - *offsetptr = offset; - return 0; + res = 0; + + out: + return res; } /*---------------------------------------------------------------------------*/ |