diff options
Diffstat (limited to 'libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h')
-rwxr-xr-x | libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h | 1127 |
1 files changed, 1127 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h new file mode 100755 index 00000000..bae0ec8b --- /dev/null +++ b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h @@ -0,0 +1,1127 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed 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. + */ + +/** + * @file ccnx_TlvDictionary.h + * @brief Stores pointers to PARCBuffers indexed by keys + * + * A message dictionary stores each field of a message in an array entry. The user of the dictionary needs to + * have a schema so it knows which array entry is which field. + * + * A message dictionary carries two distinguished fields that are not part of the array. The MessageType is + * Interest, ContentObject, or Control. The SchemaVersion is 0 or 1. These fields are independent of + * anything that is in the dictionary. + * + * The message dictionary creates two arrays. The first array is an array of PARCBuffer. The second array + * is a list of (type, PARCBuffer). This structure is designed such that well-known TLV keys + * are stored in the first array under well-known indicies. + * + * unknown TLV keys are stored in the second array, where each list corresponds to a TLV container. + * For example, an unknown TLV type found under the Content Object Metadata container would + * go in a list corresponding to the Metadata container and they be added to the list with the + * pair (type, PARCBuffer), where 'type' is the unknown TLV type. + * + */ + +#ifndef libccnx_ccnx_TlvDictionary_h +#define libccnx_ccnx_TlvDictionary_h + +#include <stdbool.h> +#include <sys/time.h> +#include <parc/algol/parc_Buffer.h> +#include <parc/algol/parc_JSON.h> + +#include <ccnx/common/internal/ccnx_MessageInterface.h> + +#include <ccnx/common/ccnx_Name.h> +#include <ccnx/common/codec/ccnxCodec_NetworkBuffer.h> + + +struct ccnx_tlv_dictionary; +typedef struct ccnx_tlv_dictionary CCNxTlvDictionary; + +typedef enum { + CCNxTlvDictionary_SchemaVersion_V0 = 0, + CCNxTlvDictionary_SchemaVersion_V1 = 1, +} CCNxTlvDictionary_SchemaVersion; + + +/** + * Creates a new TLV dictionary with the given size + * + * There will be 'bufferCount' array elements of type Buffer and + * 'listCount' elements of type List. Each array is indexed from 0. + * + * @param [in] bufferCount The number of Buffer elements to allocate within the dictionary. + * @param [in] listCount The number of List elements to allocate within the dictionary. + * + * @return NULL A new CCNxTlvDictionary object could not be allocated. + * @return CCNxTlvDictionary A new CCNxTlvDictionary instance with bufferCount Buffer and listCount List elements. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_PutBuffer(dict, 3, nameBuffer); + * rtatlvDictionary_PutListBuffer(dict, 2, unknownType, unknownBuffer); + * } + * @endcode + */ +CCNxTlvDictionary *ccnxTlvDictionary_Create(size_t bufferCount, size_t listCount); + +/** + * Acquire a handle to the CCNxTlvDictionary instance. + * + * Note that new instance is not created, + * only that the given instance's reference count is incremented. + * Discard the reference by invoking `ccnxTlvDictionary_Release()`. + * + * @param [in] dictionary A pointer to the original instance. + * @return The value of the input parameter @p instance. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Acquire(instance); + * + * ccnxTlvDictionary_Release(&dict); + * } + * @endcode + */ +CCNxTlvDictionary *ccnxTlvDictionary_Acquire(const CCNxTlvDictionary *dictionary); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in] dictionaryPtr A pointer to a pointer to the instance to release. + * + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Acquire(instance); + * + * ccnxTlvDictionary_Release(&dict); + * } + * @endcode + */ +void ccnxTlvDictionary_Release(CCNxTlvDictionary **dictionaryPtr); + +/** + * Adds a buffer to a dictionary entry + * + * Stores a reference count to the buffer + * + * @param [in] dictionary An CCNxTlvDictionary instance to which the Buffer entry will be added. + * @param [in] key The integer key that is to be associated with the new Buffer entry. + * @param [in] buffer The Buffer entry value to be inserted into the dictionary. + * + * @return true Key was not previously set + * @return false Key already has a buffer assigned to it + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutBuffer(dict, 1, buffer); + * // use the dictionary as needed + * } + * @endcode + */ +bool ccnxTlvDictionary_PutBuffer(CCNxTlvDictionary *dictionary, uint32_t key, const PARCBuffer *buffer); + +/** + * Determine if the value associated with the specified key is a Buffer. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * + * @param [in] dictionary The dictionary instance which will be examined. + * @param [in] key The key to use when indexing the dictionary. + * + * @return true The value associated with the key is of type Buffer. + * @return false The value associated with the key is -not- of type Buffer. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutBuffer(dict, 1, buffer); + * bool truthy = ccnxTlvDictionary_IsValueBuffer(dict, 1); + * // truthy will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueBuffer(const CCNxTlvDictionary *dictionary, uint32_t key); + +// caw TODO +bool ccnxTlvDictionary_IsValueObject(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Retrieves an entry from the dictionary from the specified key. + * + * @param [in] dictionary The dictionary instance which will be examined. + * @param [in] key The key to use when indexing the dictionary. + * + * @return NULL if key not found + * @return non-null The desired key + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutBuffer(dict, 1, buffer); + * PARCBuffer *copy = ccnxTlvDictionary_GetBuffer(dict, 1); + * // copy will be equal to the buffer instance + * } + * @endcode + */ +PARCBuffer *ccnxTlvDictionary_GetBuffer(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Put a new integer value in the dictionary, overwriting the old value if the key is + * already present. + * + * You can put an integer value many times, its OK to overwrite. + * They key must be UNSET or INTEGER, you cannot overwrite a different type + * The integer will be encoded as per the schema, it will not necessarily be an 8-byte field. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] key The key used when indexing the dictionary + * @param [in] value The new value to insert into the dictionary assoicated with the above key + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET/INTEGER type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * bool success = ccnxTlvDictionary_PutInteger(dict, 2, 1337); + * // success will be true since key 2 was UNSET + * } + * @endcode + */ +bool ccnxTlvDictionary_PutInteger(CCNxTlvDictionary *dictionary, uint32_t key, const uint64_t value); + +/** + * Determine if the value associated with the specified key is an Integer. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * + * @param [in] dictionary The dictionary instance which will be examined. + * @param [in] key The key to use when indexing the dictionary. + * + * @return true The value associated with the key is of type INTEGER. + * @return false The value associated with the key is -not- of type INTEGER. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_PutInteger(dict, 2, 1337); + * bool truthy = ccnxTlvDictionary_IsValueInteger(dict, 2); + * // truthy will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueInteger(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Returns an integer value stored in a key + * + * Will trapIllegalValue if the given key is not of type Integer. You should use + * ccnxTlvDictionary_IsValueInteger before calling. An unset key is not of type Integer. + * + * @param [in] dictionary The dictionary to check + * @param [in] key The key to retrieve + * + * @return number The value stored under the key + * + * Example: + * @code + * static uint32_t + * _fetchUint32(const CCNxTlvDictionary *interestDictionary, uint32_t key, uint32_t defaultValue) + * { + * if (ccnxTlvDictionary_IsValueInteger(interestDictionary, key)) { + * return (uint32_t) ccnxTlvDictionary_GetInteger(interestDictionary, key); + * } + * return defaultValue; + * } + * @endcode + */ +uint64_t ccnxTlvDictionary_GetInteger(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Put a new CCNxName into the `CCNxTlvDictionary` instance. + * + * You can only set a Name field once. The key must be UNSET. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] key The key used when indexing the dictionary + * @param [in] name The new CCNxName value to insert into the dictionary assoicated with the above key + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); + * bool success = ccnxTlvDictionary_PutName(dict, 2, name); + * // success will be true since key 2 was UNSET + * } + * @endcode + */ +bool ccnxTlvDictionary_PutName(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxName *name); + +/** + * Determine if the value associated with the specified key is a CCNxName. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * + * @param [in] dictionary The dictionary instance which will be examined. + * @param [in] key The key to use when indexing the dictionary. + * + * @return true The value associated with the key is of type NAME. + * @return false The value associated with the key is -not- of type NAME. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); + * ccnxTlvDictionary_PutName(dict, 2, name); + * bool truthy = ccnxTlvDictionary_IsValueName(dict, 2); + * // truthy will be true since a name was inserted with key=2 + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueName(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Retrieve the CCNxName instance associated with the specified key. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * The entry is expected to be of type NAME, and will return NULL if not. + * + * @param [in] dictionary The dictionary instance which will be queried. + * @param [in] key The key to use when indexing the dictionary. + * + * @return NULL The entry associated with the key is not of type NAME. + * @return CCNxName A CCNxName instance associated with the specified key. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); + * ccnxTlvDictionary_PutName(dict, 2, name); + * CCNxName *copy = ccnxTlvDictionary_GetName(dict, 2); + * // do something with copy + * } + * @endcode + */ +CCNxName *ccnxTlvDictionary_GetName(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Insert a `CCNxCodecNetworkBufferIoVec` instance into the dictionary. + * + * Stores a scatter/gather network buffer. Could be either the wire format we recieve + * or the wire format we're about to send. The resulting entry type will be IOVEC. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] key The key used when indexing the dictionary + * @param [in] vec The new CCNxCodecNetworkBufferIoVec value to insert into the dictionary assoicated with the above key + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL); + * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer); + * bool success = ccnxTlvDictionary_PutName(dict, 2, iovec); + * // success will be true since key 2 was UNSET + * } + * @endcode + */ +bool ccnxTlvDictionary_PutIoVec(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxCodecNetworkBufferIoVec *vec); + +/** + * Determine if the value associated with the specified key is a CCNxCodecNetworkBufferIoVec. + * + * @param [in] dictionary The dictionary instance to be examined + * @param [in] key The key used when indexing the dictionary + * + * @return true The TLV dictionary has the given key and it is of type IOVEC + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL); + * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer); + * ccnxTlvDictionary_PutName(dict, 2, iovec); + * bool truthy = ccnxTlvDictionary_IsValueIoVec(dict, 2); + * // truthy will be true since key 2 was IOVEC and previously inserted + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueIoVec(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Retrieve the CCNxCodecNetworkBufferIoVec instance associated with the specified key. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * The entry is expected to be of type IOVEC, and will return NULL if not. + * + * @param [in] dictionary The dictionary instance which will be queried. + * @param [in] key The key to use when indexing the dictionary. + * + * @return NULL The entry associated with the key is not of type IOVEC. + * @return CCNxCodecNetworkBufferIoVec A CCNxCodecNetworkBufferIoVec instance associated with the specified key. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL); + * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer); + * ccnxTlvDictionary_PutName(dict, 2, iovec); + * CCNxCodecNetworkBufferIoVec *copy = ccnxTlvDictionary_GetIoVec(dict, 2); + * // do something with copy + * } + * @endcode + */ +CCNxCodecNetworkBufferIoVec *ccnxTlvDictionary_GetIoVec(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Insert a new List item into the dictionary. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * You can only set a Buffer field once. The key must be UNSET. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] listKey The list key used when indexing the dictionary lists + * @param [in] key The key type of the element being inserted into the list + * @param [in] buffer The new PARCBuffer value to insert into the dictionary list indexed by the listKey + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * bool success = ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer); + * // success will be true since list key 1 was UNSET, and the new item will have key type 1 + * } + * @endcode + */ +bool ccnxTlvDictionary_PutListBuffer(CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t key, const PARCBuffer *buffer); + +/** + * Insert a new `PARCJSON` instance into the dictionary. + * + * The caller may destroy its reference to JSON since the type is deep-copied internally. + * The key must be within the dictionary, and the entry must be UNSET. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] key The key used when indexing the dictionary + * @param [in] json The new PARCJSON value to insert into the dictionary associated with the above key + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCJSON *json = ccnxJson_CreateNumber(1); + * bool success = ccnxTlvDictionary_PutJson(dict, 1, json); + * // success will be true since the key was UNSET + * } + * @endcode + */ +bool ccnxTlvDictionary_PutJson(CCNxTlvDictionary *dictionary, uint32_t key, const PARCJSON *json); + +/** + * Determine if the value associated with the specified key is a `PARCJSON` instance. + * + * @param [in] dictionary The dictionary instance to be examined + * @param [in] key The key used when indexing the dictionary + * + * @return true The TLV dictionary has the given key and it is of type JSON + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCJSON *json = ccnxJson_CreateNumber(1); + * ccnxTlvDictionary_PutJson(dict, 1, json); + * bool truthy = ccnxTlvDictionary_IsValueJson(dict, 1); + * // truthy will be true since the JSON object was previously inserted + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueJson(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Retrieve the `PARCJSON` instance associated with the specified key. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * The entry is expected to be of type JSON, and will return NULL if not. + * + * @param [in] dictionary The dictionary instance which will be queried. + * @param [in] key The key to use when indexing the dictionary. + * + * @return NULL The entry associated with the key is not of type JSON. + * @return PARCJSON A PARCJSON instance associated with the specified key. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCJSON *json = ccnxJson_CreateNumber(1); + * ccnxTlvDictionary_PutJson(dict, 1, json); + * PARCJSON *copy = ccnxTlvDictionary_GetJson(dict, 1); + * // do something with copy + * } + * @endcode + */ +PARCJSON *ccnxTlvDictionary_GetJson(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Insert a new `PARCJSON` instance into the dictionary. + * + * The caller may destroy its reference to PARCObject since the type is deep-copied internally. + * The key must be within the dictionary, and the entry must be UNSET. + * + * @param [in] dictionary The dictionary instance to be modified + * @param [in] key The key used when indexing the dictionary + * @param [in] json The new PARCObject value to insert into the dictionary associated with the above key + * + * @return true If the put/update was successful. + * @return false Otherwise (e.g., not UNSET type) + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCObject *object = ccnxName_CreateFromCString("ccnx/test"); + * bool success = ccnxTlvDictionary_PutObject(dict, 1, object); + * // success will be true since the key was UNSET + * } + * @endcode + */ +bool ccnxTlvDictionary_PutObject(CCNxTlvDictionary *dictionary, uint32_t key, const PARCObject *json); + +/** + * Determine if the value associated with the specified key is a `PARCObject` instance. + * + * @param [in] dictionary The dictionary instance to be examined + * @param [in] key The key used when indexing the dictionary + * + * @return true The TLV dictionary has the given key and it is of type PARCObject + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCObject *object = ccnxName_CreateFromCString("ccnx/test"); + * ccnxTlvDictionary_PutObject(dict, 1, object); + * bool truthy = ccnxTlvDictionary_IsValueObject(dict, 1); + * // truthy will be true since the PARCObject was previously inserted + * } + * @endcode + */ +bool ccnxTlvDictionary_IsValueObject(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Retrieve the `PARCObject` instance associated with the specified key. + * + * The key must be within the interval [0, bufferCount] for the dictionary. + * The entry is expected to be of type PARCObject, and will return NULL if not. + * + * @param [in] dictionary The dictionary instance which will be queried. + * @param [in] key The key to use when indexing the dictionary. + * + * @return NULL The entry associated with the key is not of type PARCObject. + * @return PARCObject A PARCObject instance associated with the specified key. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCObject *object = ccnxName_CreateFromCString("ccnx/test"); + * ccnxTlvDictionary_PutObject(dict, 1, object); + * PARCObject *copy = ccnxTlvDictionary_GetObject(dict, 1); + * // do something with copy + * } + * @endcode + */ +PARCObject *ccnxTlvDictionary_GetObject(const CCNxTlvDictionary *dictionary, uint32_t key); + +/** + * Fetches a buffer from the ordinal position 'listItem' from the list key 'key' + * + * The entry 'key' must be type list. + * + * @param [in] dictionary The dictionary instance being examined + * @param [in] listKey The key used to identify the list to be searched + * @param [in] listPosition The index within the target list of the dictionary + * @param [out] bufferPtr If position is found, the buffer at that position + * @param [out] keyPtr If position is found, the key of the buffer + * + * @return true position found + * @return false position not found + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer); + * PARCBuffer *copy = NULL; + * uint32_t key = 0; + * ccnxTlvDictionary_ListGetByPosition(dict, 1, 0, ©, &key); + * // use the copy and key as necessary + * } + * @endcode + */ +bool ccnxTlvDictionary_ListGetByPosition(const CCNxTlvDictionary *dictionary, uint32_t listKey, size_t listPosition, PARCBuffer **bufferPtr, uint32_t *keyPtr); + +/** + * Returns the first buffer in the list identified by 'listkey' with the buffer type 'type' + * + * @param [in] dictionary The dictionary instance being examined + * @param [in] listKey The key used to index into the dictionary lists + * @param [in] type The type of element used to search within the dictionary list + * + * @return PARCBuffer* Pointer to the first PARCBuffer instance whose type matches the type argument in the target list + * @return NULL If no element in the target list has the specified type. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer); + * PARCBuffer *copy = ccnxTlvDictionary_ListGetByType(dict, 1, 1); + * // copy and buffer will have equal PARCBuffer values + * } + * @endcode + */ +PARCBuffer *ccnxTlvDictionary_ListGetByType(const CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t type); + +/** + * Retrieve the number of elements in the list identified by 'key' + * + * The dictionary entry 'key' must be of type list. + * + * @param [in] dictionary The dictionary instance to be examined + * @param [in] listKey The key used to index into the list whose size will be checked + * + * @return The size of the list associated with the given list key + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer); + * size_t listSize = ccnxTlvDictionary_ListSize(dictionary, 1); + * // listSize will be 1 + * } + * @endcode + */ +size_t ccnxTlvDictionary_ListSize(const CCNxTlvDictionary *dictionary, uint32_t listKey); + +/** + * Set the type of message which this dictionary stores/represents to be an Interest. + * + * @param [in] dictionary The dictionary instance whose type is to be modified + * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0); + * // use the dictionary + * } + * @endcode + */ +void ccnxTlvDictionary_SetMessageType_Interest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion); + +/** + * Set the type of message which this dictionary stores/represents to be a ContentObject. + * + * @param [in] dictionary The dictionary instance whose type is to be modified + * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_ContentObject(dict, CCNxTlvDictionary_SchemaVersion_V1); + * // use the dictionary + * } + * @endcode + */ +void ccnxTlvDictionary_SetMessageType_ContentObject(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion); + +/** + * Set the type of message which this dictionary stores/represents to be a Control (message). + * + * @param [in] dictionary The dictionary instance whose type is to be modified + * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Control(dict, CCNxTlvDictionary_SchemaVersion_V1); + * // use the dictionary + * } + * @endcode + */ +void ccnxTlvDictionary_SetMessageType_Control(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion); + +/** + * Set the type of message which this dictionary stores/represents to be a Manifest (message). + * + * @param [in] dictionary The dictionary instance whose type is to be modified. + * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Manifest(dict, CCNxTlvDictionary_SchemaVersion_V1); + * // use the dictionary + * } + * @endcode + */ +void ccnxTlvDictionary_SetMessageType_Manifest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion); + +/** + * Set the type of message which this dictionary stores/represents to be an InterestReturn. + * + * @param [in] dictionary The dictionary instance whose type is to be modified + * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_InterestReturn(dict, CCNxTlvDictionary_SchemaVersion_V0); + * // use the dictionary + * } + * @endcode + */ +void ccnxTlvDictionary_SetMessageType_InterestReturn(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion); + + +/** + * Retrieve the schema version `CCNxTlvDictionary_SchemaVersion` used to encode the contents of the dictionary. + * + * Currently, only two schema versions are supported: CCNxTlvDictionary_SchemaVersion_V0 and CCNxTlvDictionary_SchemaVersion_V1 + * + * @param [in] dictionary The dictionary instance being examined + * + * @return The `CCNxTlvDictionary_SchemaVersion` version used for encoding. + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0); + * CCNxTlvDictionary_SchemaVersion ver = ccnxTlvDictionary_GetSchemaVersion(dict); + * // ver will be equal to CCNxTlvDictionary_SchemaVersion_V0 + * } + * @endcode + */ +CCNxTlvDictionary_SchemaVersion ccnxTlvDictionary_GetSchemaVersion(const CCNxTlvDictionary *dictionary); + +/** + * Determine if the specified dictionary represents an Interest message. + * + * @param [in] dictionary The dictionary instance being examined. + * + * @return true The dictionary represents an Interest message. + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0); + * bool isInterest = ccnxTlvDictionary_IsInterest(dict); + * // isInterest will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsInterest(const CCNxTlvDictionary *dictionary); + +/** + * Determine if the specified dictionary represents an InterestReturn message. + * + * @param [in] dictionary The dictionary instance being examined. + * + * @return true The dictionary represents an InterestReturn message. + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_InterestReturn(dict, CCNxTlvDictionary_SchemaVersion_V1); + * bool isInterestReturn = ccnxTlvDictionary_IsInterestReturn(dict); + * // isInterest will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsInterestReturn(const CCNxTlvDictionary *dictionary); + +/** + * Determine if the specified dictionary represents a ContentObject message. + * + * @param [in] dictionary The dictionary instance being examined. + * + * @return true The dictionary represents a ContentObject message. + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_ContentObject(dict, CCNxTlvDictionary_SchemaVersion_V0); + * bool isContentObject = ccnxTlvDictionary_IsContentObject(dict); + * // isContentObject will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsContentObject(const CCNxTlvDictionary *dictionary); + +/** + * Determine if the specified dictionary represents a Control message. + * + * @param [in] dictionary The dictionary instance being examined. + * + * @return true The dictionary represents a Control message. + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Control(dict, CCNxTlvDictionary_SchemaVersion_V0); + * bool isControl = ccnxTlvDictionary_IsControl(dict); + * // isControl will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsControl(const CCNxTlvDictionary *dictionary); + +/** + * Determine if the specified dictionary represents a Manifest message. + * + * @param [in] dictionary The dictionary instance being examined. + * + * @return true The dictionary represents a Manifest message. + * @return false Otherwise + * + * Example: + * @code + * { + * ... + * + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageType_Manifest(dict, CCNxTlvDictionary_SchemaVersion_V1); + * bool isManifest = ccnxTlvDictionary_IsManifest(dict); + * // isManifest will be true + * } + * @endcode + */ +bool ccnxTlvDictionary_IsManifest(const CCNxTlvDictionary *dictionary); + +/** + * If in DEBUG mode, returns how long the message has been in the system + * + * If not in DEBUG mode, will always be {.tv_sec = 0, .tv_usec = 0}. The time is based + * on gettimeofday(). + * + * Measured since the time when the dictionary was created + * + * @param [in] dictionary The dictionary instance whose lifetime is being queried + * + * @return struct timeval The lifetime of the dictionary message. + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * // do some things ... + * struct timeval = ccnxTlvDictionary_GetLifetime(dict); + * // use the time as needed + * } + * @endcode + */ +struct timeval ccnxTlvDictionary_GetLifetime(const CCNxTlvDictionary *dictionary); + +/** + * Display the dictionary and its contents + * + * The contents of the dictionary are printed to stdout. This is often useful + * for verbose debugging purposes. + * + * @param [in] indent The number of tabs to indent all lines printed on stdout + * @param [in] dictionary The dictionary instance whose contents will be printed to stdout + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_Display(dict, 0); + * } + * @endcode + */ +void ccnxTlvDictionary_Display(const CCNxTlvDictionary *dictionary, int indent); + +/** + * Determine if two CCNxTlvDictionary instances are equal. + * + * Two CCNxTlvDictionary instances are equal if, and only if, they contain the same number + * of keys, the keys are equal, and each key points to the same value. + * + * The following equivalence relations on non-null `CCNxTlvDictionary` instances are maintained: + * + * * It is reflexive: for any non-null reference value x, `ccnxTlvDictionary_Equals(x, x)` + * must return true. + * + * * It is symmetric: for any non-null reference values x and y, + * `ccnxTlvDictionary_Equals(x, y)` must return true if and only if + * `ccnxTlvDictionary_Equals(y, x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `ccnxTlvDictionary_Equals(x, y)` returns true and + * `ccnxTlvDictionary_Equals(y, z)` returns true, + * then `ccnxTlvDictionary_Equals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple + * invocations of `ccnxTlvDictionary_Equals(x, y)` consistently return true or + * consistently return false. + * + * * For any non-null reference value x, `ccnxTlvDictionary_Equals(x, NULL)` must + * return false. + * + * @param a A pointer to a `CCNxTlvDictionary` instance. + * @param b A pointer to a `CCNxTlvDictionary` instance. + * + * NULL == NULL, non-NULL != NULL, otherwise the dictionaries need to be the same + * type, schema, and all fields must compare for equality. + * + * Equals does not include the CreationTime (lifetime) or the SetInfo() value. + * + * @return true Dictionaries are equal + * @return false Dictionaries differ in some way + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *dict1 = ccnxTlvDictionary_Create(5, 3); + * CCNxTlvDictionary *dict2 = ccnxTlvDictionary_Create(5, 3); + * if (ccnxTlvDictionary_Equals(dict1, dict2)) { + * // true + * } else { + * // false + * } + * } + * @endcode + */ +bool ccnxTlvDictionary_Equals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b); + +/** + * Allocates a new instance of the specified CCNxTlvDictionary that is + * a "Shallow" copy of the original. The new instance contains the + * same contents as the original CCNxTlvDictionary but an Acquire() + * operation is used where possible to form a new link to the original + * contained content (a Copy() operation is used otherwise). Note that + * this means that modifying the content of the copy will, in most + * cases, modify the content of the original. In any case, the + * contents are protected from premature deallocation. + * + * @param [in] source The dictionary to copy + * + * @return CCNxTlvDictionary A pointer to a copy of the source dictionary + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *source = ccnxTlvDictionary_Create(5, 3); + * PARCBuffer *buffer = parcBuffer_Allocate(1); + * ccnxTlvDictionary_PutListBuffer(source, 1, 1, buffer); + * ... + * CCNxTlvDictionary *copy = ccnxTlvDictionary_ShallowCopy(source); + * PARCBuffer *buffcopy; + * uint32_t key = 0; + * ccnxTlvDictionary_ListGetByPosition(copy, 1, 0, &buffcopy, &key); + * ... + * assertTrue(ccnxTlvDictionary_Equals(source, copy), "Error: not a copy"); + * assertTrue(buffcopy == buffer, "Error: not a shallow copy"); + * } + * @endcode + */ +CCNxTlvDictionary *ccnxTlvDictionary_ShallowCopy(const CCNxTlvDictionary *source); + +/** + * Set the pointer to the implementation used to create the message type represented by this + * CCNxTlvDictionary. For example, if the CCNxTlvDictionary represents a V1 ContentObject, + * the implementation pointer should be set to &CCNxContentObjectFacadeV1_Implementation. + * The type can be inferred from the dictionary's schemaVersion and messageType. + * + * Consumers of this CCNxTlvDictionary should use the implementation pointer to access + * fields in the dictionary. Examples of implementations would be those that define + * {@link CCNxContentObjectInterface} or {@link CCNxInterestInterface}, such as + * {@link CCNxContentObjectFacadeV1_Implementation} or {CCNxInterestFacadeV1_Implementation}. + * + * @param [in] dictionary The dictionary instance on which to set the implementation pointer. + * @param [in] implementation The address of the implementation to be used to access this dictionary. + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageInterface(&CCNxContentObjectFacadeV1_Implementation); + * } + * @endcode + * @see `ccnxTlvDictionary_GetMessageTypeInterface` + */ +void ccnxTlvDictionary_SetMessageInterface(CCNxTlvDictionary *dictionary, const CCNxMessageInterface *implementation); + +/** + * Return the address of the implementation used to access fields in the the message represented by this + * CCNxTlvDictionary instance. The implementation pointer would typically be + * {@link CCNxContentObjectFacadeV1_Implementation} or {@link CCNxContentObjectFacadeV1_Implementation}. + * If it is not set, it can be inferred from the messageType and the schemaVersion. + * + * @param [in] dictionary The dictionary instance from which to retrieve the implementation pointer. + * + * Example: + * @code + * { + * ... + * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3); + * ccnxTlvDictionary_SetMessageTypeInterface(&CCNxContentObjectFacadeV1_Implementation); + * CCNxContentObjectInterface *impl = ccnxTlvDictionary_GetMessageTypeInterface(dict); + * } + * @endcode + * @see `ccnxTlvDictionary_SetMessageTypeInterface` + * @see `ccnxContentObjectInterface_GetInterface` + * @see `ccnxInterestInterface_GetInterface` + */ +CCNxMessageInterface *ccnxTlvDictionary_GetMessageInterface(const CCNxTlvDictionary *dictionary); +#endif // libccnx_ccnx_TlvDictionary_h |