diff options
Diffstat (limited to 'libccnx-common/ccnx/common/ccnx_NameSegment.h')
-rw-r--r-- | libccnx-common/ccnx/common/ccnx_NameSegment.h | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/ccnx_NameSegment.h b/libccnx-common/ccnx/common/ccnx_NameSegment.h new file mode 100644 index 00000000..44c1ee57 --- /dev/null +++ b/libccnx-common/ccnx/common/ccnx_NameSegment.h @@ -0,0 +1,566 @@ +/* + * 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_NameSegment.h + * @ingroup Naming + * @brief A path segment of a CCNx Name + * + * An RFC3986 compliant implementation of URI segments, where each path segment carries a label. + * See {@link CCNxName} for more information. + * + */ +#ifndef libccnx_ccnx_NameSegment_h +#define libccnx_ccnx_NameSegment_h +#include <stdbool.h> +#include <stdint.h> + +#include <parc/algol/parc_BufferComposer.h> +#include <parc/algol/parc_Buffer.h> + +#include <ccnx/common/ccnx_NameLabel.h> + +#include <parc/algol/parc_URI.h> + +struct ccnx_name_Segment; +/** + * @typedef CCNxNameSegment + * @brief A path segment of a `CCNxName` + */ +typedef struct ccnx_name_segment CCNxNameSegment; + +/** + * Create a CCNxNameSegment instance initialised with the given type and value. + * + * @param [in] type A valid CCNxNameLabelType + * @param [in] value A valid PARCBuffer containing the value of the name segment. + * + * @return non-NULL A pointer to a valid CCNxNameSegment instance. + * @return NULL An error occurred. + * + * Example: + * @code + * { + * PARCBuffer *value = parcBuffer_WrapCString("value"); + * + * CCNxNameSegment *expected = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, value); + * + * parcBuffer_Release(&value); + * } + * @endcode + */ +CCNxNameSegment *ccnxNameSegment_CreateTypeValue(CCNxNameLabelType type, const PARCBuffer *value); + +/** + * Create a CCNxNameSegment instance initialised with the given type and value taken from the given array of bytes. + * + * @param [in] type A valid CCNxNameLabelType + * @param [in] length The number of bytes in @p array. + * @param [in] array A pointer to a buffer containing the bytes for the value of the name segment. + * + * @return non-NULL A pointer to a valid CCNxNameSegment instance. + * @return NULL An error occurred. + * + * Example: + * @code + * { + * CCNxNameSegment *expected = ccnxNameSegment_CreateTypeValueArray(CCNxNameLabelType_NAME, 5, "value"); + * } + * @endcode + */ +CCNxNameSegment *ccnxNameSegment_CreateTypeValueArray(CCNxNameLabelType type, size_t length, const char *array); + +/** + * Parse a `CCNxNameSegment` from a {@link PARCURISegment} consisting of type specification and value. + * + * The name must be in conformance with `draft-mosko-icnrg-ccnxlabeledcontent-00` + * + * Names that use mnemonic values for labels, must conform to thier respective specifications. + * See `draft-scott-icnrg-ccnxnameregistry-00` for a list of assigned names and type values. + * + * @param [in] uriSegment A pointer to a valid `PARCURISegment` + * @return non-NULL A pointer to an allocated `CCNxNameSegment` which must eventually be released by calling + * {@link ccnxNameSegment_Release}(). + * @return NULL An error occurred. + * @see `ccnxNameSegment_Release()` + * + * Example: + * @code + * { + * char *lciSegment = CCNxNameLabel_Name "=" "abcde"; + * PARC_URISegment *uriSegment = parcURISegment_Parse(lciSegment, NULL); + * + * CCNxNameSegment *actual = ccnxNameSegment_ParseURISegment(uriSegment); + * + * CCNxNameLabelType type = ccnxNameSegment_GetType(actual); + * assertTrue(CCNxNameLabelType_NAME == type, "Expected %04x, actual %04x", 0x20, type); + * + * ccnxNameSegment_Release(&actual); + * parcURISegment_Release(&uriSegment); + * } + * @endcode + */ +CCNxNameSegment *ccnxNameSegment_ParseURISegment(const PARCURISegment *uriSegment); + +/** + * Create a new `CCNxNameSegment` by copying the given `CCNxNameSegment`. This is a deep copy, + * and the created instance must eventually be released by calling {@link ccnxNameSegment_Release}(). + * + * @param [in] segment A `CCNxNameSegment` pointer. + * @return An allocated `CCNxNameSegment` which must eventually be released by calling {@link ccnxNameSegment_Release}(). + * + * Example: + * @code + * { + * PARCBuffer *value = parcBuffer_WrapCString("hello"); + * CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, value); + * + * CCNxNameSegment *copy = ccnxNameSegment_Copy(segment); + * + * ccnxNameSegment_Release(&segment); + * ccnxNameSegment_Copy(©); + * parcBuffer_Release(&value); + * } + * @endcode + */ +CCNxNameSegment *ccnxNameSegment_Copy(const CCNxNameSegment *segment); + +/** + * Determine if two `CCNxNameSegment` instances are equal. + * + * The following equivalence relations on non-null `CCNxNameSegment` instances are maintained: + * + * * It is reflexive: for any non-null reference value x, `ccnxNameSegment_Equal(x, x)` must return true. + * + * * It is symmetric: for any non-null reference values x and y, `ccnxNameSegment_Equal(x, y)` must return true if and only if + * `ccnxNameSegment_Equal(y x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `ccnxNameSegment_Equal(x, y)` returns true and + * `ccnxNameSegment_Equal(y, z)` returns true, + * then `ccnxNameSegment_Equal(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple invocations of `ccnxNameSegment_Equal(x, y)` + * consistently return true or consistently return false. + * + * * For any non-null reference value x, `ccnxNameSegment_Equal(x, NULL)` must return false. + * + * @param [in] segmentA A pointer to a `CCNxNameSegment` instance. + * @param [in] segmentB A pointer to a `CCNxNameSegment` instance to be compared to `segmentA`. + * + * @return `true` if the given `CCNxNameSegment` instances are equal. + * + * Example: + * @code + * { + * char *lciSegment = CCNxNameLabelType_Label_Chunk "=" "123"; + * PARC_URISegment *uriSegment = parcURISegment_Parse(lciSegment, NULL); + * CCNxNameSegment *segmentA = ccnxNameSegment_ParseURISegment(uriSegment); + * + * PARCBuffer *buf = parcBuffer_WrapCString("123"); + * CCNxNameSegment *segmentB = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_CHUNK, buf); + * + * if (ccnxNameSegment_Equals(expected, actual)) { + * // true + * } else { + * // false + * } + * ccnxNameSegment_Release(&segmentA); + * ccnxNameSegment_Release(&segmentB); + * parcURISegment_Release(&uriSegment); + * parcBuffer_Release(&buf); + * } + * @endcode + */ +bool ccnxNameSegment_Equals(const CCNxNameSegment *segmentA, const CCNxNameSegment *segmentB); + +/** + * A signum function comparing two `CCNxNameSegment` instances. + * + * Used to determine the ordering relationship of two `CCNxNameSegment` instances. + * + * @param [in] segmentA A pointer to a `CCNxNameSegment` instance. + * @param [in] segmentB A pointer to a `CCNxNameSegment` instance to be compared to `segmentA`. + * + * @return 0 if `segmentA` and `segmentB` are equivalent + * @return < 0 if `segmentA` < `segmentB` + * @return > 0 if `segmentA` > `segmentB` + * + * Example: + * @code + * { + * PARCBuffer *valueA = parcBuffer_WrapCString("apple"); + * CCNxNameSegment *segmentA = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, valueA); + * + * PARCBuffer *valueB = parcBuffer_WrapCString("banana"); + * CCNxNameSegment *segmentB = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, valueB); + * + * int signum = ccnxNameSegment_Compare(segmentA, segmentB); + * + * ccnxNameSegment_Release(&segmentA); + * parcBuffer_Release(&bufA); + * ccnxNameSegment_Release(&segmentB); + * parcBuffer_Release(&bufB); + * } + * @endcode + */ +int ccnxNameSegment_Compare(const CCNxNameSegment *segmentA, const CCNxNameSegment *segmentB); + +/** + * Get a pointer to the underlying PARCBuffer storing the value of the given `CCNxNameSegment`. + * + * A new reference to the instance is not created. + * If the caller requires a reference to live beyond the lifetime of the `CCNxNameSegment` + * it must acquire a reference via {@link parcBuffer_Acquire}. + * + * Any modifications to the buffer's position, limit or mark will affect subsequent use of the buffer. + * + * @param [in] segment A pointer to a `CCNxNameSegment` instance. + * @return A pointer to the underlying @link PARCBuffer. + * + * Example: + * @code + * { + * PARC_URISegment *uriSegment = parcURISegment_Parse("label:param=value"); + * + * CCNxNameSegment *actual = ccnxNameSegment_ParseURISegment(uriSegment); + * + * PARCBuffer *value = ccnxNameSegment_GetValue(actual); + * + * ccnxNameSegment_Release(&actual); + * parcURISegment_Release(&uriSegment); + * } + * @endcode + * + * @see {@link ccnxNameSegment_Length}() + */ +PARCBuffer *ccnxNameSegment_GetValue(const CCNxNameSegment *segment); + +/** + * Get a pointer to the underlying PARCBuffer storing the parameter of the given `CCNxNameSegment`. + * + * A new reference to the instance is not created. + * If the caller requires a reference to live beyond the lifetime of the `CCNxNameSegment` + * it must acquire a reference via {@link parcBuffer_Acquire}. + * + * Any modifications to the buffer's position, limit or mark will affect subsequent use of the buffer. + * + * @param [in] segment A pointer to a `CCNxNameSegment` instance. + * @return NULL The given `CCNxNameSegment` does not specify a parameter value. + * @return non-NULL A pointer to the underlying `PARCBuffer`. + * + * Example: + * @code + * { + * CCNxNameSegment *segment = ccnxNameSegment_ParseURISegment("label:param=value"); + * + * PARCBuffer *parameter = ccnxNameSegment_GetParameter(segment); + * + * ccnxNameSegment_Release(&segment); + * } + * @endcode + * + * @see {@link ccnxNameSegment_Length}() + */ +PARCBuffer *ccnxNameSegment_GetParameter(const CCNxNameSegment *segment); + +/** + * Produce a nul-terminated C string representation of the given `CCNxNameSegment`. + * + * A string representation, such as "1=foo". + * + * @param [in] segment A CCNxNameSegment pointer. + * @return An allocated null-terminated byte array that must be deallocated by `{@link parcMemory_Deallocate}()`. + * + * Example: + * @code + * { + * CCNxName *name = ccnxName_CreateFromCString("lci:/parc/csl/sensors/radiation/212"); + * CCNxNameSegment *segment = ccnxName_GetSegment(name, 3); + * + * char *string = ccnxNameSegment_ToString(segment); + * printf("Hello: %s\n", string); + * + * parcMemory_Deallocate(string); + * ccnxName_Release(&name); + * } + * @endcode + * + * @see `parcMemory_Deallocate` + */ +char *ccnxNameSegment_ToString(const CCNxNameSegment *segment); + +/** + * Print a human readable representation of the given `CCNxNameSegment`. + * + * @param [in] segment A pointer to the instance to display. + * @param [in] indentation The level of indentation to use to pretty-print the output. + * + * Example: + * @code + * { + * CCNxName *name = ccnxName_CreateFromCString("lci:/parc/csl/sensors/radiation/212"); + * CCNxNameSegment *segment = ccnxName_GetSegment(name, 3); + * + * ccnxNameSegment_Display(segment, 0); + * + * ccnxName_Release(&name); + * } + * @endcode + * + */ +void ccnxNameSegment_Display(const CCNxNameSegment *segment, int indentation); + +/** + * Append a printable-character representation of the specified instance to the given {@link PARCBufferComposer}. + * + * @param [in] segment A pointer to the `CCNxNameSegment` instance. + * @param [in,out] composer A pointer to the `PARCBufferComposer` instance onto which to append our printable representation. + * + * @return NULL Cannot allocate memory. + * @return non-NULL The @p composer. + * + * Example: + * @code + * { + * PARCBufferComposer *result = parcBufferComposer_Create(); + * + * ccnxNameSegment_BuildString(instance, result); + * + * char *string = parcBuffer_ToString(parcBufferComposer_ProduceBuffer(result)); + * printf("Hello: %s\n", string); + * parcMemory_Deallocate(string); + * + * parcBufferComposer_Release(&result); + * } + * @endcode + * + * @see PARCBufferComposer + */ +PARCBufferComposer *ccnxNameSegment_BuildString(const CCNxNameSegment *segment, PARCBufferComposer *composer); + +/** + * Return the length of the specified `CCNxNameSegment`, in bytes. + * + * @param [in] segment A pointer to a `CCNxNameSegment` instance. + * @return The number of bytes for the value of the given `CCNxNameSegment`. + * + * Example: + * @code + * { + * CCNxName *name = ccnxName_CreateFromCString("lci:/parc/csl/sensors/humidity/12"); + * CCNxNameSegment *segment = ccnxName_GetSegment(name, 3); + * + * int length = ccnxNameSegment_Length(segment); + * + * ccnxName_Release(&name); + * } + * @endcode + */ +size_t ccnxNameSegment_Length(const CCNxNameSegment *segment); + +/** + * Get the label of the given `CCNxNameSegment`. + * + * @param [in] segment A pointer to a `CCNxNameSegment` instance. + * @return non-NULL A pointer to a PARCBuffer instance containing the label. + * @return NULL The CCNxNameSegment instance does not have a label. + * + * Example: + * @code + * { + * PARCBuffer *buf = parcBuffer_WrapCString("apple"); + * CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buf); + * + * CCNxNameLabelType type = ccnxNameSegment_GetType(segment); + * + * ccnxNameSegment_Release(&segment); + * parcBuffer_Release(&buf); + * } + * @endcode + * + * @see `CCNxNameLabelType` + */ +PARCBuffer *ccnxNameSegment_GetLabel(const CCNxNameSegment *segment); + +/** + * Get the {@link CCNxNameLabelType} of the given `CCNxNameSegment`. + * + * @param [in] segment A pointer to a `CCNxNameSegment` instance. + * @return The `CCNxNameLabelType` of the specified `CCNxNameSegment` instance. + * + * Example: + * @code + * { + * PARCBuffer *buf = parcBuffer_WrapCString("apple"); + * CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buf); + * + * CCNxNameLabelType type = ccnxNameSegment_GetType(segment); + * + * ccnxNameSegment_Release(&segment); + * parcBuffer_Release(&buf); + * } + * @endcode + * + * @see `CCNxNameLabelType` + */ +CCNxNameLabelType ccnxNameSegment_GetType(const CCNxNameSegment *segment); + +/** + * Return a hashcode for the given `CCNxNameSegment`. + * + * Whenever `HashCode()` is invoked on the same instance more than once within the same execution environment, + * the HashCode function must consistently return the same value, provided no information used in its corresponding + * `Equals()` comparisons on the same instance is modified. + * + * This value need not remain consistent from one execution of an application to another execution of the same application. + * + * If two instances are equal according to the `Equals()` function, + * then calling the `HashCode` function on each of the two objects must produce the same integer result. + * + * It is not required that if two instances are unequal according to the `Equals()` function, + * then calling the HashCode() method on each of the two instances must produce distinct integer results. + * However, the programmer should be aware that producing distinct results for unequal instances + * may improve the performance of some data structures. + * + * @param segment A pointer to a `CCNxNameSegment` instance. + * @return An unsigned 32-bit integer hash code value. + * + * Example: + * @code + * { + * PARCBuffer *bufA =parcBuffer_WrapCString("Test"); + * + * CCNxNameSegment *segmentA = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, bufA); + * + * uint32_t hashCode = ccnxNameSegment_HashCode(segmentA); + * + * ccnxNameSegment_Release(&segmentA); + * parcBuffer_Release(&bufA); + * } + * @endcode + * + * @see `parcHash32Bits_Hash` + */ +PARCHashCode ccnxNameSegment_HashCode(const CCNxNameSegment *segment); + +/** + * Increase the number of references to a `CCNxNameSegment`. + * + * Note that a new `CCNxNameSegment` is not created, + * only that the given `CCNxNameSegment` reference count is incremented. + * Discard the reference by invoking {@link ccnxNameSegment_Release}(). + * + * @param [in] segment A pointer to the original instance. + * @return The value of the input parameter @p instance. + * + * Example: + * @code + * { + * ... + * + * CCNxNameSegment *segment = ccnxNameSegment_Acquire(instance); + * + * ccnxNameSegment_Release(&segment); + * + * } + * @endcode + * + * @see ccnxNameSegment_Release + */ +CCNxNameSegment *ccnxNameSegment_Acquire(const CCNxNameSegment *segment); + +/** + * 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,out] segmentP A pointer to a pointer to the instance to release. + * + * + * Example: + * @code + * { + * ... + * + * CCNxNameSegment *segment = ccnxNameSegment_Acquire(instance); + * + * ccnxNameSegment_Release(&segment); + * + * } + * @endcode + * + * @see ccnxNameSegment_Acquire + */ +void ccnxNameSegment_Release(CCNxNameSegment **segmentP); + +#ifdef Libccnx_DISABLE_VALIDATION +# define ccnxNameSegment_OptionalAssertValid(_instance_) +#else +# define ccnxNameSegment_OptionalAssertValid(_instance_) ccnxNameSegment_AssertValid(_instance_) +#endif + +/** + * Assert that an instance of `CCNxNameSegment` is valid. + * + * If the instance is not valid, terminate via {@link trapIllegalValue} + * + * Valid means the internal state of the type is consistent with its + * required current or future behaviour. + * This may include the validation of internal instances of types. + * + * @param [in] segment A pointer to the instance to check. + * + * Example: + * @code + * { + * ... + * + * ccnxNameSegment_AssertValid(segment); + * + * } + * @endcode + */ +void ccnxNameSegment_AssertValid(const CCNxNameSegment *segment); + +/** + * Determine if an instance of `CCNxNameSegment` is valid. + * + * Valid means the internal state of the type is consistent with its + * required current or future behaviour. + * This may include the validation of internal instances of referenced objects. + * + * @param [in] segment A pointer to the instance to check. + * + * @return true The instance is valid. + * @return false The instance is not valid. + * + * Example: + * @code + * { + * ... + * + * ccnxNameSegment_IsValid(segment); + * + * } + * @endcode + */ +bool ccnxNameSegment_IsValid(const CCNxNameSegment *segment); +#endif // libccnx_ccnx_NameSegment_h |