diff options
| author | Ted Ross <tross@apache.org> | 2013-06-26 17:36:32 +0000 |
|---|---|---|
| committer | Ted Ross <tross@apache.org> | 2013-06-26 17:36:32 +0000 |
| commit | ede7589da6bdded56f54c0a7802e779c1e900ea2 (patch) | |
| tree | c0ad1631b29417b9322643be4bdfbfe557cc3426 /qpid/extras/dispatch/src/compose.c | |
| parent | 3a6acad9663e3b552ebed78645c77e855f9502ac (diff) | |
| download | qpid-python-ede7589da6bdded56f54c0a7802e779c1e900ea2.tar.gz | |
NO-JIRA - Major refactoring of the code for composing performatives in messages.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1497019 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/extras/dispatch/src/compose.c')
| -rw-r--r-- | qpid/extras/dispatch/src/compose.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/qpid/extras/dispatch/src/compose.c b/qpid/extras/dispatch/src/compose.c new file mode 100644 index 0000000000..3c0d8974ba --- /dev/null +++ b/qpid/extras/dispatch/src/compose.c @@ -0,0 +1,433 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <qpid/dispatch/ctools.h> +#include <qpid/dispatch/alloc.h> +#include <qpid/dispatch/buffer.h> +#include "message_private.h" +#include "compose_private.h" +#include <memory.h> + +typedef struct dx_composite_t { + DEQ_LINKS(struct dx_composite_t); + int isMap; + uint32_t count; + uint32_t length; + dx_field_location_t length_location; + dx_field_location_t count_location; +} dx_composite_t; + +ALLOC_DECLARE(dx_composite_t); +ALLOC_DEFINE(dx_composite_t); +DEQ_DECLARE(dx_composite_t, dx_field_stack_t); + + +struct dx_composed_field_t { + dx_buffer_list_t buffers; + dx_field_stack_t fieldStack; +}; + +ALLOC_DECLARE(dx_composed_field_t); +ALLOC_DEFINE(dx_composed_field_t); + + +static void bump_count(dx_composed_field_t *field) +{ + dx_composite_t *comp = DEQ_HEAD(field->fieldStack); + if (comp) + comp->count++; +} + + +static void dx_insert(dx_composed_field_t *field, const uint8_t *seq, size_t len) +{ + dx_buffer_t *buf = DEQ_TAIL(field->buffers); + dx_composite_t *comp = DEQ_HEAD(field->fieldStack); + + while (len > 0) { + if (buf == 0 || dx_buffer_capacity(buf) == 0) { + buf = dx_allocate_buffer(); + if (buf == 0) + return; + DEQ_INSERT_TAIL(field->buffers, buf); + } + + size_t to_copy = dx_buffer_capacity(buf); + if (to_copy > len) + to_copy = len; + memcpy(dx_buffer_cursor(buf), seq, to_copy); + dx_buffer_insert(buf, to_copy); + len -= to_copy; + seq += to_copy; + if (comp) + comp->length += to_copy; + } +} + + +static void dx_insert_8(dx_composed_field_t *field, uint8_t value) +{ + dx_insert(field, &value, 1); +} + + +static void dx_insert_32(dx_composed_field_t *field, uint32_t value) +{ + uint8_t buf[4]; + buf[0] = (uint8_t) ((value & 0xFF000000) >> 24); + buf[1] = (uint8_t) ((value & 0x00FF0000) >> 16); + buf[2] = (uint8_t) ((value & 0x0000FF00) >> 8); + buf[3] = (uint8_t) (value & 0x000000FF); + dx_insert(field, buf, 4); +} + + +static void dx_insert_64(dx_composed_field_t *field, uint64_t value) +{ + uint8_t buf[8]; + buf[0] = (uint8_t) ((value & 0xFF00000000000000L) >> 56); + buf[1] = (uint8_t) ((value & 0x00FF000000000000L) >> 48); + buf[2] = (uint8_t) ((value & 0x0000FF0000000000L) >> 40); + buf[3] = (uint8_t) ((value & 0x000000FF00000000L) >> 32); + buf[4] = (uint8_t) ((value & 0x00000000FF000000L) >> 24); + buf[5] = (uint8_t) ((value & 0x0000000000FF0000L) >> 16); + buf[6] = (uint8_t) ((value & 0x000000000000FF00L) >> 8); + buf[7] = (uint8_t) (value & 0x00000000000000FFL); + dx_insert(field, buf, 8); +} + + +static void dx_overwrite(dx_buffer_t **buf, size_t *cursor, uint8_t value) +{ + while (*buf) { + if (*cursor >= dx_buffer_size(*buf)) { + *buf = (*buf)->next; + *cursor = 0; + } else { + dx_buffer_base(*buf)[*cursor] = value; + (*cursor)++; + return; + } + } +} + + +static void dx_overwrite_32(dx_field_location_t *field, uint32_t value) +{ + dx_buffer_t *buf = field->buffer; + size_t cursor = field->offset; + + dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0xFF000000) >> 24)); + dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0x00FF0000) >> 24)); + dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0x0000FF00) >> 24)); + dx_overwrite(&buf, &cursor, (uint8_t) (value & 0x000000FF)); +} + + +static void dx_compose_start_composite(dx_composed_field_t *field, int isMap) +{ + if (isMap) + dx_insert_8(field, 0xd1); // map32 + else + dx_insert_8(field, 0xd0); // list32 + + // + // Push a composite descriptor on the field stack + // + dx_composite_t *comp = new_dx_composite_t(); + DEQ_ITEM_INIT(comp); + comp->isMap = isMap; + + // + // Mark the current location to later overwrite the length + // + comp->length_location.buffer = DEQ_TAIL(field->buffers); + comp->length_location.offset = dx_buffer_size(comp->length_location.buffer); + comp->length_location.length = 4; + comp->length_location.parsed = 1; + + dx_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4); + + // + // Mark the current location to later overwrite the count + // + comp->count_location.buffer = DEQ_TAIL(field->buffers); + comp->count_location.offset = dx_buffer_size(comp->count_location.buffer); + comp->count_location.length = 4; + comp->count_location.parsed = 1; + + dx_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4); + + comp->length = 4; // Include the length of the count field + comp->count = 0; + + DEQ_INSERT_HEAD(field->fieldStack, comp); +} + + +static void dx_compose_end_composite(dx_composed_field_t *field) +{ + dx_composite_t *comp = DEQ_HEAD(field->fieldStack); + assert(comp); + + dx_overwrite_32(&comp->length_location, comp->length); + dx_overwrite_32(&comp->count_location, comp->count); + + DEQ_REMOVE_HEAD(field->fieldStack); + free_dx_composite_t(comp); +} + + +dx_composed_field_t *dx_compose(uint8_t performative, dx_composed_field_t *extend) +{ + dx_composed_field_t *field = extend; + + if (field) { + assert(DEQ_SIZE(field->fieldStack) == 0); + } else { + field = new_dx_composed_field_t(); + if (!field) + return 0; + + DEQ_INIT(field->buffers); + DEQ_INIT(field->fieldStack); + } + + dx_insert(field, (const uint8_t*) "\x00\x53", 2); + dx_insert_8(field, performative); + + return field; +} + + +void dx_compose_free(dx_composed_field_t *field) +{ + dx_buffer_t *buf = DEQ_HEAD(field->buffers); + while (buf) { + DEQ_REMOVE_HEAD(field->buffers); + dx_free_buffer(buf); + } + + dx_composite_t *comp = DEQ_HEAD(field->fieldStack); + while (comp) { + DEQ_REMOVE_HEAD(field->fieldStack); + free_dx_composite_t(comp); + } + + free_dx_composed_field_t(field); +} + + +void dx_compose_start_list(dx_composed_field_t *field) +{ + dx_compose_start_composite(field, 0); +} + + +void dx_compose_end_list(dx_composed_field_t *field) +{ + dx_compose_end_composite(field); +} + + +void dx_compose_start_map(dx_composed_field_t *field) +{ + dx_compose_start_composite(field, 1); +} + + +void dx_compose_end_map(dx_composed_field_t *field) +{ + dx_compose_end_composite(field); +} + + +void dx_compose_insert_null(dx_composed_field_t *field) +{ + dx_insert_8(field, 0x40); + bump_count(field); +} + + +void dx_compose_insert_bool(dx_composed_field_t *field, int value) +{ + dx_insert_8(field, value ? 0x41 : 0x42); + bump_count(field); +} + + +void dx_compose_insert_uint(dx_composed_field_t *field, uint32_t value) +{ + if (value == 0) { + dx_insert_8(field, 0x43); // uint0 + } else if (value < 256) { + dx_insert_8(field, 0x52); // smalluint + dx_insert_8(field, (uint8_t) value); + } else { + dx_insert_8(field, 0x70); // uint + dx_insert_32(field, value); + } + bump_count(field); +} + + +void dx_compose_insert_ulong(dx_composed_field_t *field, uint64_t value) +{ + if (value == 0) { + dx_insert_8(field, 0x44); // ulong0 + } else if (value < 256) { + dx_insert_8(field, 0x53); // smallulong + dx_insert_8(field, (uint8_t) value); + } else { + dx_insert_8(field, 0x80); // ulong + dx_insert_64(field, value); + } + bump_count(field); +} + + +void dx_compose_insert_int(dx_composed_field_t *field, int32_t value) +{ + if (value >= -128 && value <= 127) { + dx_insert_8(field, 0x54); // smallint + dx_insert_8(field, (uint8_t) value); + } else { + dx_insert_8(field, 0x71); // int + dx_insert_32(field, (uint32_t) value); + } + bump_count(field); +} + + +void dx_compose_insert_long(dx_composed_field_t *field, int64_t value) +{ + if (value >= -128 && value <= 127) { + dx_insert_8(field, 0x55); // smalllong + dx_insert_8(field, (uint8_t) value); + } else { + dx_insert_8(field, 0x81); // long + dx_insert_64(field, (uint64_t) value); + } + bump_count(field); +} + + +void dx_compose_insert_timestamp(dx_composed_field_t *field, uint64_t value) +{ + dx_insert_8(field, 0x83); // timestamp + dx_insert_64(field, value); + bump_count(field); +} + + +void dx_compose_insert_uuid(dx_composed_field_t *field, const char *value) +{ + dx_insert_8(field, 0x98); // uuid + dx_insert(field, (const uint8_t*) value, 16); + bump_count(field); +} + + +void dx_compose_insert_binary(dx_composed_field_t *field, const uint8_t *value, uint32_t len) +{ + if (len < 256) { + dx_insert_8(field, 0xa0); // vbin8 + dx_insert_8(field, (uint8_t) len); + } else { + dx_insert_8(field, 0xb0); // vbin32 + dx_insert_32(field, len); + } + dx_insert(field, value, len); + bump_count(field); +} + + +void dx_compose_insert_binary_buffers(dx_composed_field_t *field, dx_buffer_list_t *buffers) +{ + dx_buffer_t *buf = DEQ_HEAD(*buffers); + uint32_t len = 0; + + // + // Calculate the size of the binary field to be appended. + // + while (buf) { + len += dx_buffer_size(buf); + buf = DEQ_NEXT(buf); + } + + // + // Supply the appropriate binary tag for the length. + // + if (len < 256) { + dx_insert_8(field, 0xa0); // vbin8 + dx_insert_8(field, (uint8_t) len); + } else { + dx_insert_8(field, 0xb0); // vbin32 + dx_insert_32(field, len); + } + + // + // Move the supplied buffers to the tail of the field's buffer list. + // + buf = DEQ_HEAD(*buffers); + while (buf) { + DEQ_REMOVE_HEAD(*buffers); + DEQ_INSERT_TAIL(field->buffers, buf); + buf = DEQ_HEAD(*buffers); + } +} + + +void dx_compose_insert_string(dx_composed_field_t *field, const char *value) +{ + uint32_t len = strlen(value); + + if (len < 256) { + dx_insert_8(field, 0xa1); // str8-utf8 + dx_insert_8(field, (uint8_t) len); + } else { + dx_insert_8(field, 0xb1); // str32-utf8 + dx_insert_32(field, len); + } + dx_insert(field, (const uint8_t*) value, len); + bump_count(field); +} + + +void dx_compose_insert_symbol(dx_composed_field_t *field, const char *value) +{ + uint32_t len = strlen(value); + + if (len < 256) { + dx_insert_8(field, 0xa3); // sym8 + dx_insert_8(field, (uint8_t) len); + } else { + dx_insert_8(field, 0xb3); // sym32 + dx_insert_32(field, len); + } + dx_insert(field, (const uint8_t*) value, len); + bump_count(field); +} + + +dx_buffer_list_t *dx_compose_buffers(dx_composed_field_t *field) +{ + return &field->buffers; +} + |
