diff options
Diffstat (limited to 'libparc/parc/algol/parc_BufferComposer.h')
-rwxr-xr-x | libparc/parc/algol/parc_BufferComposer.h | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/libparc/parc/algol/parc_BufferComposer.h b/libparc/parc/algol/parc_BufferComposer.h new file mode 100755 index 00000000..f45aeb8e --- /dev/null +++ b/libparc/parc/algol/parc_BufferComposer.h @@ -0,0 +1,571 @@ +/* + * 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 parc_BufferComposer.h + * @ingroup memory + * @brief An elastic memory composer of PARCBuffer instances. + * + * A `PARCBufferComposer` is a dynamically allocated buffer that can be used to incrementally add (append) + * intrinsic values and/or `PARCBuffer` instance contents to a single location. It is meant to be a general + * purpose buffer in that all native types may be added to the buffer. When finished, the user can finalize + * the composer and produce a flipped `PARCBuffer` instance. + * + */ +#ifndef libparc_parc_BufferComposer_h +#define libparc_parc_BufferComposer_h + +struct parc_buffer_composer; +typedef struct parc_buffer_composer PARCBufferComposer; + +#include <parc/algol/parc_Buffer.h> + +extern parcObjectDescriptor_Declaration(PARCBufferComposer); + +#ifdef PARCLibrary_DISABLE_VALIDATION +# define parcBufferComposer_OptionalAssertValid(_instance_) +#else +# define parcBufferComposer_OptionalAssertValid(_instance_) parcBufferComposer_AssertValid(_instance_) +#endif + +/** + * Create an empty (zero-length) `PARCBufferComposer`. + * + * @return NULL Memory could not be allocated. + * @return non-NULL A pointer to the new `PARCBufferComposer`. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Create(); + * + * // insert contents... + * + * parcBufferComposer_Release(&composer); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_Create(void); + +/** + * Create a new instance of `PARCBufferComposer` starting with an initial amount of dynamically allocated memory. + * + * The new buffer's position will be zero, its limit will be set to `length`, its capacity will be set to limit, + * its mark will be undefined, and each of its elements will be initialized to zero. + * + * @param [in] length The number of bytes to pre-allocate. + * + * @return A pointer to a `PARCBufferComposer` instance + * + * Example: + * @code + * { + * PARCBufferComposer *buffer = parcBufferComposer_Allocate(10); + * + * parcBufferComposer_Release(&buffer); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_Allocate(size_t length); + +/** + * Assert that an instance of `PARCBufferComposer` is valid. + * + * If the instance is not valid, terminate via `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] instance A pointer to a PARCBufferComposer instance. + */ +void parcBufferComposer_AssertValid(const PARCBufferComposer *instance); + +/** + * This function returns a pointer to a shared `PARCBufferComposer`. + * An implementation may choose to produce a whole copy of the original `PARCBufferComposer`, + * or a reference counted pointer to a common copy. + * + * {@link parcBufferComposer_Release()} must perform the right operations to take care of a shared `PARCBufferComposer`, + * or simple copies. + * + * @param [in] original A pointer to a `PARCBufferComposer` that will be copied. + * + * @return A pointer to a `PARCBufferComposer` + * + * Example: + * @code + * { + * PARCBufferComposer *buffer = parcBufferComposer_Allocate(10); + * + * PARCBufferComposer *handle = parcBufferComposer_Acquire(buffer); + * // handle and buffer will be equal + * + * parcBufferComposer_Release(&handle); + * parcBufferComposer_Release(&buffer); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_Acquire(const PARCBufferComposer *original); + +/** + * 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] composerPtr A pointer to a pointer to the instance to release. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Create(); + * + * parcBufferComposer_Release(&composer); + * } + * @endcode + */ +void parcBufferComposer_Release(PARCBufferComposer **composerPtr); + +/** + * Determine if two `PARCBufferComposer` instances are equal. + * + * The following equivalence relations on non-null `PARCBufferComposer` instances are maintained: * + * * It is reflexive: for any non-null reference value x, `parcBufferComposer_Equals(x, x)` must return true. + * + * * It is symmetric: for any non-null reference values x and y, `parcBufferComposer_Equals(x, y)` must return true if and only if + * `parcBufferComposer_Equals(y x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `parcBufferComposer_Equals(x, y)` returns true and + * `parcBufferComposer_Equals(y, z)` returns true, + * then `parcBufferComposer_Equals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple invocations of `parcBufferComposer_Equals(x, y)` + * consistently return true or consistently return false. + * + * * For any non-null reference value x, `parcBufferComposer_Equals(x, NULL)` must return false. + * + * + * @param [in] x A pointer to a `PARCBufferComposer` instance. + * @param [in] y A pointer to a `PARCBufferComposer` instance. + * + * @return true `PARCBufferComposer` x and y are equal. + * @return false `PARCBufferComposer` x and y are not equal. + * + * Example: + * @code + * { + * PARCBufferComposer *composerA = parcBuffer_Allocate(10); + * PARCBufferComposer *composerB = parcBuffer_Allocate(10); + * + * if (parcBufferComposer_Equals(composerA, composerB)) { + * printf("Composers are equal.\n"); + * } else { + * printf("Composers are NOT equal.\n"); + * } + * + * parcBufferComposer_Release(&composerA); + * parcBufferComposer_Release(&composerB); + * } + * @endcode + */ +bool parcBufferComposer_Equals(const PARCBufferComposer *x, const PARCBufferComposer *y); + +/** + * Append `length` number of bytes from the given byte array `bytes` to the given `PARCBufferComposer`. + * + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to the PARCBufferComposer to receive the data. + * @param [in] bytes A pointer to the array that contains the data. + * @param [in] length The number of bytes of data to put into @p buffer. + * + * @return NULL Memory could not be allocated, and the buffer is unmodified. + * @return non-NULL The value of the parameter @p buffer. + * + * Example: + * @code + * PARCBufferComposer *composer = parcBufferComposer_Allocate(10); + * uint8_t string[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; + * + * parcBufferComposer_PutArray(composer, string, strlen(string)); + * + * parcBufferComposer_Release(&composer); + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutArray(PARCBufferComposer *composer, const unsigned char *bytes, size_t length); + +/** + * Append a single char to the given `PARCBufferComposer` at the current position. + * + * The buffer's position will be advanced by 1 (== sizeof(char)). + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance that will receive the char value. + * @param [in] value A single char value. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p buffer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(10); + * parcBufferComposer_PutChar(composer, 0x12); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutChar(PARCBufferComposer *composer, char value); + +/** + * Append a single uint8_t to the given `PARCBufferComposer` at the current position. + * + * The buffer's position will be advanced by 1 (== sizeof(uint8_t)). + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance that will receive the uint8_t value. + * @param [in] value A uint8_t value. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p buffer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(10); + * parcBufferComposer_PutUint8(composer, 0x12); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutUint8(PARCBufferComposer *composer, uint8_t value); + +/** + * Append a single uint16_t to the given `PARCBufferComposer` at the current position. + * + * The buffer's position will be advanced by 2. + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance that will receive the uint16_t value. + * @param [in] value A uint16_t value. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p buffer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(10); + * parcBufferComposer_PutUint16(composer, 0x1234); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutUint16(PARCBufferComposer *composer, uint16_t value); + +/** + * Append a single uint16_t to the given `PARCBufferComposer` at the current position. + * + * The buffer's position will be advanced by 4. + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance that will receive the uint32_t value. + * @param [in] value A `uint32_t` value. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p composer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(10); + * parcBufferComposer_PutUint32(composer, 0x12345678); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutUint32(PARCBufferComposer *composer, uint32_t value); + +/** + * Append a single uint64_t to the given `PARCBufferComposer` at the current position. + * + * The value is encoded in full, 8 byte, form in big-endian format, or network byte order. + * The buffer's position will be advanced by 8. + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance that will receive the uint64_t value. + * @param [in] value A `uint64_t` value. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p composer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(20); + * parcBufferComposer_PutUint32(composer, 0x0123456789ABCDEF); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_PutUint64(PARCBufferComposer *composer, uint64_t value); + +/** + * Put (append) the content of the source buffer into the destination buffer. + * + * The contents are taken from the current position of the source buffer + * to its limit. The destination buffer is expanded as necessary. + * + * When complete, the source buffer's position is set to its limit. + * + * Both the input `PARCBufferComposer` and `PARCBuffer` instances are modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance. + * @param [in] sourceBuffer The buffer that will produce the data. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p composer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * PARCBuffer *buffer = parcBuffer_AllocateCString("Hello, World!"); + * parcBufferComposer_PutBuffer(composer, buffer); + * } + * @endcode + * + * @see parcBufferComposer_GetBuffer + */ +PARCBufferComposer *parcBufferComposer_PutBuffer(PARCBufferComposer *composer, const PARCBuffer *sourceBuffer); + +/** + * Put (append) the content of the null-terminated, C-style string into the destination buffer. + * + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance. + * @param [in] cString A pointer to a null-terminated C string to append to this `PARCBufferComposer`. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p composer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * parcBufferComposer_PutString(composer, "Hello, World!"); + * // Hello, World! + * } + * @endcode + * + * @see parcBufferComposer_PutBuffer + * @see parcBufferComposer_GetBuffer + */ +PARCBufferComposer *parcBufferComposer_PutString(PARCBufferComposer *composer, const char *cString); + +/** + * Put (append) the content of an arbitrary number of null-terminated, C-style strings + * into the destination buffer. + * + * The input `PARCBufferComposer` instance is modified. + * + * @param [in,out] composer A pointer to a `PARCBufferComposer` instance. + * @param [in] ... The null-terminated, C-style strings to append to the given `PARCBufferComposer`. + * + * @return NULL Memory could not be allocated. + * @return non-NULL The value of the parameter @p buffer. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * parcBufferComposer_PutString(composer, "Hello"); + * parcBufferComposer_PutStrings(composer, ", ", "World", "!"); + * // Hello, World! + * } + * @endcode + * + * @see parcBufferComposer_PutString + * @see parcBufferComposer_PutBuffer + * @see parcBufferComposer_GetBuffer + */ +PARCBufferComposer *parcBufferComposer_PutStrings(PARCBufferComposer *composer, ...); + +/** + * Append a formatted nul-terminated, C string string to the given `PARCBufferComposer` instance. + * The input `PARCBufferComposer` instance is modified. + * + * The format string is a nul-terminated C string compatible with the `vasprintf(3)` C library function. + * + * @param [in,out] composer A pointer to `PARCBufferComposer`. + * @param [in] format The format string compatible with the `vasprintf(3)` C library function. + * @param [in] ... Remaining parameters used to format the string. + * + * @return The same pointer as the `composer` parameter. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * + * parcBufferComposer_Format(composer, "Hello %s\n", "World"); + * + * char *string = parcBuffer_ToString(parcBufferComposer_ProduceBuffer(string))); + * printf("String = %s\n", string); + * + * parcMemory_Deallocate(&string); + * } + * @endcode + */ +PARCBufferComposer *parcBufferComposer_Format(PARCBufferComposer *composer, const char *format, ...) +__attribute__((format(printf, 2, 3))); + +/** + * Return a pointer to the underlying {@link PARCBuffer} instance currently used by the given `PARCBufferComposer`. + * + * WARNING: This function is not safe. Use with caution. + * + * There is no guarantee that the returned `PARCBuffer` instance will not + * be released and deallocated before use by the caller of this function. + * If modifications need to be made, a reference should be acquired manually. + * + * Also, if the caller modifies the state of the returned `PARCBuffer` instance, + * e.g., via a {@link parcBuffer_GetUint8}() call, any future writes to this + * same `PARCBufferComposer` will not behave as expected unless the instance is + * returned to its original state. + * + * To safely access the underlying `PARCBuffer` instance, use + * the {@link parcBufferComposer_CreateBuffer}() function instead. + * + * No new reference is created. The caller must acquire a reference to the returned `PARCBuffer` + * if it needs retain it beyond the life of the given `PARCBufferComposer`. + * + * @param composer [in] A pointer to a `PARCBufferComposer` instance. + * + * @return A pointer to the internal `PARCBuffer` which is wrapped by this `PARCBufferComposer`. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * PARCBuffer *buffer = parcBuffer_AllocateCString("Hello, World!"); + * parcBufferComposer_PutBuffer(composer, buffer); + * + * PARCBuffer *sameBuffer = parcBufferComposer_GetBuffer(composer); + * // buffer and sameBuffer are equal + * } + * @endcode + * + * @see parcBufferComposer_PutBuffer + * @see parcBufferComposer_ProduceBuffer + */ +PARCBuffer *parcBufferComposer_GetBuffer(const PARCBufferComposer *composer); + +/** + * Create a `PARCBuffer` pointing to the underlying `PARCBuffer` instance. + * + * This is functionally equivalent to {@link parcBufferComposer_GetBuffer} but + * is safe since it allocates a new `PARCBuffer` instance for the same buffer. + * + * The result must be freed by the caller via {@link parcBuffer_Release}. + * + * @param [in] composer A pointer to a `PARCBufferComposer` instance. + * + * @return A pointer to the `PARCBuffer` which is stored by this `PARCBufferComposer`. + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * PARCBuffer *buffer = parcBuffer_AllocateCString("Hello, World!"); + * parcBufferComposer_PutBuffer(composer, buffer); + * + * PARCBuffer *writeBuffer = parcBufferComposer_CreateBuffer(composer); + * + * // use writeBuffer as needed + * + * parcBuffer_Release(&writeBuffer); + * } + * @endcode + * + * @see parcBufferComposer_GetBuffer + * @see parcBufferComposer_ProduceBuffer + */ +PARCBuffer *parcBufferComposer_CreateBuffer(PARCBufferComposer *composer); + +/** + * Finalize this `PARCBufferComposer` and return the resulting {@link PARCBuffer}. + * + * Note that, unlike {@link parcBufferComposer_GetBuffer}, the return buffer is flipped + * via {@link parcBuffer_Flip}. This effectively finalizes this `PARCBufferComposer`. + * No more writes should be made to this instance. + * + * Also note that {@link parcBufferComposer_ToString} cannot be called after this function + * is invoked. + * + * The result must be freed by the caller via {@link parcBuffer_Release}. + * + * @param [in] composer A pointer to a `PARCBufferComposer` instance. + * + * @return A pointer to the final `PARCBuffer` which is stored by this `PARCBufferComposer` + * + * Example: + * @code + * { + * PARCBufferComposer *composer = parcBufferComposer_Allocate(1024); + * PARCBuffer *buffer = parcBuffer_AllocateCString("Hello, World!"); + * parcBufferComposer_PutBuffer(composer, buffer); + * + * PARCBuffer *readBuffer = parcBufferComposer_ProduceBuffer(composer); + * parcBufferComposer_Release(&composer); + * + * // use readBuffer as needed + * + * parcBuffer_Release(&readBuffer); + * } + * @endcode + * + * @see parcBufferComposer_GetBuffer + */ +PARCBuffer *parcBufferComposer_ProduceBuffer(PARCBufferComposer *composer); + +/** + * Produce a null-terminated string containing the characters from 0 to the current + * position of the given `PARCBufferComposer`. + * The composer is not modified and may continue to be used. + * + * The result must be freed by the caller via {@link parcMemory_Deallocate}. + * + * @param [in] instance A pointer to a valid PARCBufferComposer instance. + * + * @return NULL Cannot allocate memory. + * @return non-NULL A pointer to an allocated, null-terminated C string that must be deallocated via {@link parcMemory_Deallocate}. + * + * Example: + * @code + * { + * PARCBufferComposer *a = parcBufferComposer_Create(); + * + * char *string = parcBufferComposer_ToString(a); + * + * parcBufferComposer_Release(&a); + * + * parcMemory_Deallocate(&string); + * } + * @endcode + */ +char *parcBufferComposer_ToString(PARCBufferComposer *composer); +#endif // libparc_parc_BufferComposer_h |