A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
Diff: amqpvalue.c
- Revision:
- 26:64f1113cb959
- Parent:
- 25:1101516ee67d
- Child:
- 28:add19eb7defa
diff -r 1101516ee67d -r 64f1113cb959 amqpvalue.c --- a/amqpvalue.c Mon May 22 10:35:21 2017 -0700 +++ b/amqpvalue.c Wed May 24 09:46:35 2017 -0700 @@ -10,6 +10,7 @@ #include "azure_c_shared_utility/xlogging.h" #include "azure_uamqp_c/amqp_types.h" #include "azure_uamqp_c/amqpvalue.h" +#include "azure_c_shared_utility/refcount.h" /* Requirements satisfied by the current implementation without any code: Codes_SRS_AMQPVALUE_01_270: [<encoding code="0x56" category="fixed" width="1" label="boolean with the octet 0x00 being false and octet 0x01 being true"/>] @@ -164,6 +165,8 @@ AMQP_VALUE_UNION value; } AMQP_VALUE_DATA; +DEFINE_REFCOUNT_TYPE(AMQP_VALUE_DATA); + typedef enum DECODER_STATE_TAG { DECODER_STATE_CONSTRUCTOR, @@ -184,6 +187,7 @@ AMQP_VALUE_DATA* decode_to_value; INTERNAL_DECODER_HANDLE inner_decoder; DECODE_VALUE_STATE_UNION decode_value_state; + bool is_internal; } INTERNAL_DECODER_DATA; typedef struct AMQPVALUE_DECODER_HANDLE_DATA_TAG @@ -195,7 +199,7 @@ /* Codes_SRS_AMQPVALUE_01_003: [1.6.1 null Indicates an empty value.] */ AMQP_VALUE amqpvalue_create_null(void) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_002: [If allocating the AMQP_VALUE fails then amqpvalue_create_null shall return NULL.] */ @@ -213,7 +217,7 @@ /* Codes_SRS_AMQPVALUE_01_004: [1.6.2 boolean Represents a true or false value.] */ AMQP_VALUE amqpvalue_create_boolean(bool value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_007: [If allocating the AMQP_VALUE fails then amqpvalue_create_boolean shall return NULL.] */ @@ -266,7 +270,7 @@ /* Codes_SRS_AMQPVALUE_01_005: [1.6.3 ubyte Integer in the range 0 to 28 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_ubyte(unsigned char value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result != NULL) { /* Codes_SRS_AMQPVALUE_01_032: [amqpvalue_create_ubyte shall return a handle to an AMQP_VALUE that stores a unsigned char value.] */ @@ -314,7 +318,7 @@ /* Codes_SRS_AMQPVALUE_01_012: [1.6.4 ushort Integer in the range 0 to 216 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_ushort(uint16_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_039: [If allocating the AMQP_VALUE fails then amqpvalue_create_ushort shall return NULL.] */ @@ -367,7 +371,7 @@ /* Codes_SRS_AMQPVALUE_01_013: [1.6.5 uint Integer in the range 0 to 232 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_uint(uint32_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_045: [If allocating the AMQP_VALUE fails then amqpvalue_create_uint shall return NULL.] */ @@ -420,7 +424,7 @@ /* Codes_SRS_AMQPVALUE_01_014: [1.6.6 ulong Integer in the range 0 to 264 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_ulong(uint64_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_050: [If allocating the AMQP_VALUE fails then amqpvalue_create_ulong shall return NULL.] */ @@ -473,7 +477,7 @@ /* Codes_SRS_AMQPVALUE_01_015: [1.6.7 byte Integer in the range -(27) to 27 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_byte(char value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_056: [If allocating the AMQP_VALUE fails then amqpvalue_create_byte shall return NULL.] */ @@ -526,7 +530,7 @@ /* Codes_SRS_AMQPVALUE_01_016: [1.6.8 short Integer in the range -(215) to 215 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_short(int16_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_062: [If allocating the AMQP_VALUE fails then amqpvalue_create_short shall return NULL.] */ @@ -578,7 +582,7 @@ /* Codes_SRS_AMQPVALUE_01_017: [1.6.9 int Integer in the range -(231) to 231 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_int(int32_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_068: [If allocating the AMQP_VALUE fails then amqpvalue_create_int shall return NULL.] */ @@ -631,7 +635,7 @@ /* Codes_SRS_AMQPVALUE_01_018: [1.6.10 long Integer in the range -(263) to 263 - 1 inclusive.] */ AMQP_VALUE amqpvalue_create_long(int64_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_074: [If allocating the AMQP_VALUE fails then amqpvalue_create_long shall return NULL.] */ @@ -684,7 +688,7 @@ /* Codes_SRS_AMQPVALUE_01_019: [1.6.11 float 32-bit floating point number (IEEE 754-2008 binary32).] */ AMQP_VALUE amqpvalue_create_float(float value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_081: [If allocating the AMQP_VALUE fails then amqpvalue_create_float shall return NULL.] */ @@ -737,7 +741,7 @@ /* Codes_SRS_AMQPVALUE_01_020: [1.6.12 double 64-bit floating point number (IEEE 754-2008 binary64).] */ AMQP_VALUE amqpvalue_create_double(double value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_087: [If allocating the AMQP_VALUE fails then amqpvalue_create_double shall return NULL.] */ @@ -790,7 +794,7 @@ /* Codes_SRS_AMQPVALUE_01_024: [1.6.16 char A single Unicode character.] */ AMQP_VALUE amqpvalue_create_char(uint32_t value) { - AMQP_VALUE_DATA* result; + AMQP_VALUE result; /* Codes_SRS_AMQPVALUE_01_098: [If the code point value is outside of the allowed range [0, 0x10FFFF] then amqpvalue_create_char shall return NULL.] */ if (value > 0x10FFFF) @@ -800,7 +804,7 @@ } else { - result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_093: [If allocating the AMQP_VALUE fails then amqpvalue_create_char shall return NULL.] */ @@ -854,7 +858,7 @@ /* Codes_SRS_AMQPVALUE_01_025: [1.6.17 timestamp An absolute point in time.] */ AMQP_VALUE amqpvalue_create_timestamp(int64_t value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_108: [If allocating the AMQP_VALUE fails then amqpvalue_create_timestamp shall return NULL.] */ @@ -907,7 +911,7 @@ /* Codes_SRS_AMQPVALUE_01_026: [1.6.18 uuid A universally unique identifier as defined by RFC-4122 section 4.1.2 .] */ AMQP_VALUE amqpvalue_create_uuid(uuid value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_114: [If allocating the AMQP_VALUE fails then amqpvalue_create_uuid shall return NULL.] */ @@ -960,7 +964,7 @@ /* Codes_SRS_AMQPVALUE_01_027: [1.6.19 binary A sequence of octets.] */ AMQP_VALUE amqpvalue_create_binary(amqp_binary value) { - AMQP_VALUE_DATA* result; + AMQP_VALUE result; if ((value.bytes == NULL) && (value.length > 0)) { @@ -970,7 +974,7 @@ } else { - result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_128: [If allocating the AMQP_VALUE fails then amqpvalue_create_binary shall return NULL.] */ @@ -1049,7 +1053,7 @@ /* Codes_SRS_AMQPVALUE_01_028: [1.6.20 string A sequence of Unicode characters.] */ AMQP_VALUE amqpvalue_create_string(const char* value) { - AMQP_VALUE_DATA* result; + AMQP_VALUE result; if (value == NULL) { LogError("NULL argument value"); @@ -1059,7 +1063,7 @@ { size_t length = strlen(value); - result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_136: [If allocating the AMQP_VALUE fails then amqpvalue_create_string shall return NULL.] */ @@ -1124,7 +1128,7 @@ /* Codes_SRS_AMQPVALUE_01_029: [1.6.21 symbol Symbolic values from a constrained domain.] */ AMQP_VALUE amqpvalue_create_symbol(const char* value) { - AMQP_VALUE_DATA* result; + AMQP_VALUE result; if (value == NULL) { /* Codes_SRS_AMQPVALUE_01_400: [If value is NULL, amqpvalue_create_symbol shall fail and return NULL.] */ @@ -1143,7 +1147,7 @@ else { /* Codes_SRS_AMQPVALUE_01_143: [If allocating the AMQP_VALUE fails then amqpvalue_create_symbol shall return NULL.] */ - result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { LogError("Cannot allocate memory for AMQP value"); @@ -1209,7 +1213,7 @@ /* Codes_SRS_AMQPVALUE_01_030: [1.6.22 list A sequence of polymorphic values.] */ AMQP_VALUE amqpvalue_create_list(void) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_150: [If allocating the AMQP_VALUE fails then amqpvalue_create_list shall return NULL.] */ @@ -1499,8 +1503,7 @@ /* Codes_SRS_AMQPVALUE_01_031: [1.6.23 map A polymorphic mapping from distinct keys to values.] */ AMQP_VALUE amqpvalue_create_map(void) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); - + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { /* Codes_SRS_AMQPVALUE_01_179: [If allocating memory for the map fails, then amqpvalue_create_map shall return NULL.] */ @@ -1798,7 +1801,7 @@ AMQP_VALUE amqpvalue_create_array(void) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { LogError("Could not allocate memory for AMQP value"); @@ -2157,358 +2160,17 @@ if (value == NULL) { - LogError("NULL value"); + /* Codes_SRS_AMQPVALUE_01_402: [ If `value` is NULL, `amqpvalue_clone` shall return NULL. ]*/ + LogError("NULL value"); result = NULL; } else { - AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value; - switch (value_data->type) - { - default: - LogError("Invalid data type: %d", (int)value_data->type); - result = NULL; - break; - - case AMQP_TYPE_NULL: - /* Codes_SRS_AMQPVALUE_01_237: [null] */ - result = amqpvalue_create_null(); - break; - - case AMQP_TYPE_BOOL: - /* Codes_SRS_AMQPVALUE_01_238: [boolean] */ - result = amqpvalue_create_boolean(value_data->value.bool_value); - break; - - case AMQP_TYPE_UBYTE: - /* Codes_SRS_AMQPVALUE_01_239: [ubyte] */ - result = amqpvalue_create_ubyte(value_data->value.ubyte_value); - break; - - case AMQP_TYPE_USHORT: - /* Codes_SRS_AMQPVALUE_01_240: [ushort] */ - result = amqpvalue_create_ushort(value_data->value.ushort_value); - break; - - case AMQP_TYPE_UINT: - /* Codes_SRS_AMQPVALUE_01_241: [uint] */ - result = amqpvalue_create_uint(value_data->value.uint_value); - break; - - case AMQP_TYPE_ULONG: - /* Codes_SRS_AMQPVALUE_01_242: [ulong] */ - result = amqpvalue_create_ulong(value_data->value.ulong_value); - break; - - case AMQP_TYPE_BYTE: - /* Codes_SRS_AMQPVALUE_01_243: [byte] */ - result = amqpvalue_create_byte(value_data->value.byte_value); - break; - - case AMQP_TYPE_SHORT: - /* Codes_SRS_AMQPVALUE_01_244: [short] */ - result = amqpvalue_create_short(value_data->value.short_value); - break; - - case AMQP_TYPE_INT: - /* Codes_SRS_AMQPVALUE_01_245: [int] */ - result = amqpvalue_create_int(value_data->value.int_value); - break; - - case AMQP_TYPE_LONG: - /* Codes_SRS_AMQPVALUE_01_246: [long] */ - result = amqpvalue_create_long(value_data->value.long_value); - break; - - case AMQP_TYPE_FLOAT: - /* Codes_SRS_AMQPVALUE_01_247: [float] */ - result = amqpvalue_create_float(value_data->value.float_value); - break; - - case AMQP_TYPE_DOUBLE: - /* Codes_SRS_AMQPVALUE_01_248: [double] */ - result = amqpvalue_create_double(value_data->value.double_value); - break; - - case AMQP_TYPE_CHAR: - /* Codes_SRS_AMQPVALUE_01_252: [char] */ - result = amqpvalue_create_char(value_data->value.char_value); - break; - - case AMQP_TYPE_TIMESTAMP: - /* Codes_SRS_AMQPVALUE_01_253: [timestamp] */ - result = amqpvalue_create_timestamp(value_data->value.timestamp_value); - break; - - case AMQP_TYPE_UUID: - /* Codes_SRS_AMQPVALUE_01_254: [uuid] */ - result = amqpvalue_create_uuid(value_data->value.uuid_value); - break; - - case AMQP_TYPE_BINARY: - /* Codes_SRS_AMQPVALUE_01_255: [binary] */ - result = amqpvalue_create_binary(value_data->value.binary_value); - break; - - case AMQP_TYPE_STRING: - /* Codes_SRS_AMQPVALUE_01_256: [string] */ - result = amqpvalue_create_string(value_data->value.string_value.chars); - break; - - case AMQP_TYPE_SYMBOL: - /* Codes_SRS_AMQPVALUE_01_257: [symbol] */ - result = amqpvalue_create_symbol(value_data->value.symbol_value.chars); - break; - - case AMQP_TYPE_LIST: - { - /* Codes_SRS_AMQPVALUE_01_258: [list] */ - uint32_t i; - AMQP_VALUE_DATA* result_data = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); - if (result_data == NULL) - { - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - LogError("Cannot allocate memory for cloned value"); - result = NULL; - } - else - { - result_data->type = AMQP_TYPE_LIST; - result_data->value.list_value.count = value_data->value.list_value.count; - - if (value_data->value.list_value.count > 0) - { - result_data->value.list_value.items = (AMQP_VALUE*)malloc(value_data->value.list_value.count * sizeof(AMQP_VALUE)); - if (result_data->value.list_value.items == NULL) - { - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - LogError("Cannot allocate memory for cloned list"); - free(result_data); - result = NULL; - } - else - { - for (i = 0; i < value_data->value.list_value.count; i++) - { - result_data->value.list_value.items[i] = amqpvalue_clone(value_data->value.list_value.items[i]); - if (result_data->value.list_value.items[i] == NULL) - { - LogError("Cannot clone list item %u", (unsigned int)i); - break; - } - } - - if (i < value_data->value.list_value.count) - { - uint32_t j; - - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - /* destroy all the allocated values to return to the initial state */ - for (j = 0; j < i; j++) - { - amqpvalue_destroy(result_data->value.list_value.items[j]); - } - - free(result_data->value.list_value.items); - free(result_data); - result = NULL; - } - else - { - result = result_data; - } - } - } - else - { - result_data->value.list_value.items = NULL; - result = result_data; - } - } - - break; - } - case AMQP_TYPE_MAP: - { - /* Codes_SRS_AMQPVALUE_01_259: [map] */ - uint32_t i; - AMQP_VALUE_DATA* result_data = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); - if (result_data == NULL) - { - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - LogError("Cannot allocate memory for cloned map"); - result = NULL; - } - else - { - result_data->type = AMQP_TYPE_MAP; - result_data->value.map_value.pair_count = value_data->value.map_value.pair_count; - - if (result_data->value.map_value.pair_count > 0) - { - result_data->value.map_value.pairs = (AMQP_MAP_KEY_VALUE_PAIR*)malloc(value_data->value.map_value.pair_count * sizeof(AMQP_MAP_KEY_VALUE_PAIR)); - if (result_data->value.map_value.pairs == NULL) - { - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - LogError("Cannot allocate memory for cloned map storage"); - free(result_data); - result = NULL; - } - else - { - for (i = 0; i < value_data->value.map_value.pair_count; i++) - { - result_data->value.map_value.pairs[i].key = amqpvalue_clone(value_data->value.map_value.pairs[i].key); - if (result_data->value.map_value.pairs[i].key == NULL) - { - LogError("Cannot clone map key index %u", (unsigned int)i); - break; - } - - result_data->value.map_value.pairs[i].value = amqpvalue_clone(value_data->value.map_value.pairs[i].value); - if (result_data->value.map_value.pairs[i].value == NULL) - { - LogError("Cannot clone map value index %u", (unsigned int)i); - amqpvalue_destroy(result_data->value.map_value.pairs[i].key); - break; - } - } - - if (i < value_data->value.map_value.pair_count) - { - /* Codes_SRS_AMQPVALUE_01_236: [If creating the cloned value fails, amqpvalue_clone shall return NULL.] */ - uint32_t j; - - for (j = 0; j < i; j++) - { - amqpvalue_destroy(result_data->value.map_value.pairs[j].key); - amqpvalue_destroy(result_data->value.map_value.pairs[j].value); - } - - free(result_data->value.map_value.pairs); - free(result_data); - result = NULL; - } - else - { - result = (AMQP_VALUE)result_data; - } - } - } - else - { - result_data->value.map_value.pairs = NULL; - result = (AMQP_VALUE)result_data; - } - } - - break; - } - case AMQP_TYPE_ARRAY: - { - uint32_t i; - AMQP_VALUE_DATA* result_data = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); - if (result_data == NULL) - { - LogError("Cannot allocate memory for cloned array"); - result = NULL; - } - else - { - result_data->type = AMQP_TYPE_ARRAY; - result_data->value.array_value.count = value_data->value.array_value.count; - - if (value_data->value.array_value.count > 0) - { - result_data->value.array_value.items = (AMQP_VALUE*)malloc(value_data->value.array_value.count * sizeof(AMQP_VALUE)); - if (result_data->value.array_value.items == NULL) - { - LogError("Cannot allocate memory for cloned array storage"); - free(result_data); - result = NULL; - } - else - { - for (i = 0; i < value_data->value.array_value.count; i++) - { - result_data->value.array_value.items[i] = amqpvalue_clone(value_data->value.array_value.items[i]); - if (result_data->value.array_value.items[i] == NULL) - { - LogError("Cannot allocate memory for cloned array item %u", (unsigned int)i); - break; - } - } - - if (i < value_data->value.array_value.count) - { - uint32_t j; - - for (j = 0; j < i; j++) - { - amqpvalue_destroy(result_data->value.array_value.items[j]); - } - - free(result_data->value.array_value.items); - free(result_data); - result = NULL; - } - else - { - result = result_data; - } - } - } - else - { - result_data->value.array_value.items = NULL; - result = result_data; - } - } - - break; - } - case AMQP_TYPE_DESCRIBED: - result = amqpvalue_create_described(amqpvalue_clone(value_data->value.described_value.descriptor), amqpvalue_clone(value_data->value.described_value.value)); - break; - - case AMQP_TYPE_COMPOSITE: - { - AMQP_VALUE_DATA* result_data = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); - AMQP_VALUE cloned_descriptor; - AMQP_VALUE cloned_list; - - if (result_data == NULL) - { - LogError("Cannot allocate memory for cloned composite value"); - result = NULL; - } - else if ((cloned_descriptor = amqpvalue_clone(value_data->value.described_value.descriptor)) == NULL) - { - LogError("Cannot clone descriptor"); - free(result_data); - result = NULL; - } - else if ((cloned_list = amqpvalue_clone(value_data->value.described_value.value)) == NULL) - { - LogError("Cannot clone described value"); - amqpvalue_destroy(cloned_descriptor); - free(result_data); - result = NULL; - } - else - { - result_data->value.described_value.descriptor = cloned_descriptor; - result_data->value.described_value.value = cloned_list; - result_data->type = AMQP_TYPE_COMPOSITE; - - result = (AMQP_VALUE)result_data; - } - break; - } - } + /* Codes_SRS_AMQPVALUE_01_235: [amqpvalue_clone shall clone the value passed as argument and return a new non-NULL handle to the cloned AMQP value.] */ + INC_REF(AMQP_VALUE_DATA, value); + result = value; } - /* Codes_SRS_AMQPVALUE_01_235: [amqpvalue_clone shall clone the value passed as argument and return a new non-NULL handle to the cloned AMQP value.] */ return result; } @@ -3639,22 +3301,26 @@ } else { - /* Codes_SRS_AMQPVALUE_01_314: [amqpvalue_destroy shall free all resources allocated by any of the amqpvalue_create_xxx functions or amqpvalue_clone.] */ - AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value; - amqpvalue_clear(value_data); - free(value); + if (DEC_REF(AMQP_VALUE_DATA, value) == DEC_RETURN_ZERO) + { + /* Codes_SRS_AMQPVALUE_01_314: [amqpvalue_destroy shall free all resources allocated by any of the amqpvalue_create_xxx functions or amqpvalue_clone.] */ + AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value; + amqpvalue_clear(value_data); + free(value); + } } } -static INTERNAL_DECODER_DATA* internal_decoder_create(ON_VALUE_DECODED on_value_decoded, void* callback_context, AMQP_VALUE_DATA* value_data) +static INTERNAL_DECODER_DATA* internal_decoder_create(ON_VALUE_DECODED on_value_decoded, void* callback_context, AMQP_VALUE_DATA* value_data, bool is_internal) { INTERNAL_DECODER_DATA* internal_decoder_data = (INTERNAL_DECODER_DATA*)malloc(sizeof(INTERNAL_DECODER_DATA)); - if (internal_decoder_data == NULL) + if (internal_decoder_data == NULL) { LogError("Cannot allocate memory for internal decoder structure"); } else { + internal_decoder_data->is_internal = is_internal; internal_decoder_data->on_value_decoded = on_value_decoded; internal_decoder_data->on_value_decoded_context = callback_context; internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR; @@ -3710,7 +3376,24 @@ case DECODER_STATE_CONSTRUCTOR: { - amqpvalue_clear(internal_decoder_data->decode_to_value); + if ((internal_decoder_data->decode_to_value != NULL) && (!internal_decoder_data->is_internal)) + { + amqpvalue_destroy(internal_decoder_data->decode_to_value); + internal_decoder_data->decode_to_value = NULL; + } + + if (internal_decoder_data->decode_to_value == NULL) + { + internal_decoder_data->decode_to_value = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); + } + + if (internal_decoder_data->decode_to_value == NULL) + { + LogError("Cannot allocate decode value"); + result = __FAILURE__; + break; + } + internal_decoder_data->constructor_byte = buffer[0]; buffer++; size--; @@ -3727,7 +3410,7 @@ { AMQP_VALUE_DATA* descriptor; internal_decoder_data->decode_to_value->type = AMQP_TYPE_DESCRIBED; - descriptor = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + descriptor = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (descriptor == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -3738,7 +3421,7 @@ { descriptor->type = AMQP_TYPE_UNKNOWN; internal_decoder_data->decode_to_value->value.described_value.descriptor = descriptor; - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, descriptor); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, descriptor, true); if (internal_decoder_data->inner_decoder == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -4175,10 +3858,10 @@ if (inner_decoder->decoder_state == DECODER_STATE_DONE) { - AMQP_VALUE_DATA* described_value; + AMQP_VALUE described_value; internal_decoder_destroy(inner_decoder); - described_value = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + described_value = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (described_value == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -4189,7 +3872,7 @@ { described_value->type = AMQP_TYPE_UNKNOWN; internal_decoder_data->decode_to_value->value.described_value.value = (AMQP_VALUE)described_value; - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, described_value); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, described_value, true); if (internal_decoder_data->inner_decoder == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -5111,7 +4794,7 @@ if (internal_decoder_data->bytes_decoded == 0) { - AMQP_VALUE_DATA* list_item = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* list_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (list_item == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -5121,7 +4804,7 @@ { list_item->type = AMQP_TYPE_UNKNOWN; internal_decoder_data->decode_to_value->value.list_value.items[internal_decoder_data->decode_value_state.list_value_state.item] = list_item; - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, list_item); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, list_item, true); if (internal_decoder_data->inner_decoder == NULL) { LogError("Could not create inner decoder for list items"); @@ -5319,7 +5002,7 @@ if (internal_decoder_data->bytes_decoded == 0) { - AMQP_VALUE_DATA* map_item = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* map_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (map_item == NULL) { LogError("Could not allocate memory for map item"); @@ -5337,7 +5020,7 @@ { internal_decoder_data->decode_to_value->value.map_value.pairs[internal_decoder_data->decode_value_state.map_value_state.item].value = map_item; } - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, map_item); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, map_item, true); if (internal_decoder_data->inner_decoder == NULL) { LogError("Could not create inner decoder for map item"); @@ -5528,7 +5211,7 @@ AMQP_VALUE_DATA* array_item; internal_decoder_data->decode_value_state.array_value_state.constructor_byte = buffer[0]; - array_item = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + array_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (array_item == NULL) { LogError("Could not allocate memory for array item to be decoded"); @@ -5539,7 +5222,7 @@ { array_item->type = AMQP_TYPE_UNKNOWN; internal_decoder_data->decode_to_value->value.array_value.items[internal_decoder_data->decode_value_state.array_value_state.item] = array_item; - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, array_item); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, array_item, true); if (internal_decoder_data->inner_decoder == NULL) { internal_decoder_data->decoder_state = DECODER_STATE_ERROR; @@ -5585,7 +5268,7 @@ } else { - AMQP_VALUE_DATA* array_item = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* array_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (array_item == NULL) { LogError("Could not allocate memory for array item"); @@ -5596,7 +5279,7 @@ { array_item->type = AMQP_TYPE_UNKNOWN; internal_decoder_data->decode_to_value->value.array_value.items[internal_decoder_data->decode_value_state.array_value_state.item] = array_item; - internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, array_item); + internal_decoder_data->inner_decoder = internal_decoder_create(inner_decoder_callback, internal_decoder_data, array_item, true); if (internal_decoder_data->inner_decoder == NULL) { LogError("Could not create inner decoder for array item"); @@ -5670,7 +5353,7 @@ } else { - decoder_instance->decode_to_value = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + decoder_instance->decode_to_value = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (decoder_instance->decode_to_value == NULL) { /* Codes_SRS_AMQPVALUE_01_313: [If creating the decoder fails, amqpvalue_decoder_create shall return NULL.] */ @@ -5681,7 +5364,7 @@ else { decoder_instance->decode_to_value->type = AMQP_TYPE_UNKNOWN; - decoder_instance->internal_decoder = internal_decoder_create(on_value_decoded, callback_context, decoder_instance->decode_to_value); + decoder_instance->internal_decoder = internal_decoder_create(on_value_decoded, callback_context, decoder_instance->decode_to_value, false); if (decoder_instance->internal_decoder == NULL) { /* Codes_SRS_AMQPVALUE_01_313: [If creating the decoder fails, amqpvalue_decoder_create shall return NULL.] */ @@ -5709,7 +5392,7 @@ { AMQPVALUE_DECODER_HANDLE_DATA* decoder_instance = (AMQPVALUE_DECODER_HANDLE_DATA*)handle; /* Codes_SRS_AMQPVALUE_01_316: [amqpvalue_decoder_destroy shall free all resources associated with the amqpvalue_decoder.] */ - amqpvalue_destroy(decoder_instance->decode_to_value); + amqpvalue_destroy(decoder_instance->internal_decoder->decode_to_value); internal_decoder_destroy(decoder_instance->internal_decoder); free(handle); } @@ -5807,7 +5490,7 @@ AMQP_VALUE amqpvalue_create_described(AMQP_VALUE descriptor, AMQP_VALUE value) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { LogError("Cannot allocate memory for described type"); @@ -5824,7 +5507,7 @@ AMQP_VALUE amqpvalue_create_composite(AMQP_VALUE descriptor, uint32_t list_size) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { LogError("Cannot allocate memory for composite type"); @@ -5868,7 +5551,7 @@ AMQP_VALUE amqpvalue_create_composite_with_ulong_descriptor(uint64_t descriptor) { - AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)malloc(sizeof(AMQP_VALUE_DATA)); + AMQP_VALUE_DATA* result = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA); if (result == NULL) { LogError("Cannot allocate memory for composite type");