Files
torstenandCopilot 342ffd3e5c Update submodule to latest BUILD_RTI fixes
- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten
- svcTabCommon: Export-Header-Fix via Fallback-Target
- TrainingAreaBase: Stub-Header für BUILD_RTI=OFF
- ddsfts: Include-Pfad und Dependency-Fixes
- BUILD_RTI=OFF Compilation vollständig unterstützt

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
2026-08-21 19:30:20 +02:00

409 lines
13 KiB
C

/*
* (c) Copyright, Real-Time Innovations, 2002-2026.
* All rights reserved.
* No duplications, whole or partial, manual or electronic, may be made
* without express written permission. Any such copies, or
* revisions thereof, must display this notice unaltered.
* This code contains trade secrets of Real-Time Innovations, Inc.
*/
#ifndef reda_buffer_h
#define reda_buffer_h
#include "reda/reda_dll.h"
#include "osapi/osapi_type.h"
#include "osapi/osapi_alignment.h"
#include "osapi/osapi_compression.h"
/*e \file
\brief Defines the REDABuffer interface
*/
/*e \defgroup REDABufferClass REDABuffer
\ingroup REDAModule
\brief REDA buffers are equivalent to iovec buffers supported by the
sendmsg() socket API, or the WSABUF array used to do gather send on
Windows.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*e \ingroup REDABufferClass
\brief Generic buffer to hold data, described by a pointer to the data, as
well as the length of the data.
This structure deliberately mirrors
windows WSABUF so we can cast the passed in structure directly without
copying the fields into a structure on the stack.
@see REDABufferArray_getSize
*/
#define REDABuffer RTIOsapiBuffer
/*e \ingroup REDABufferClass
\brief Manages where in the buffer is the next available memory to use
@see REDABufferArray_getSize
*/
struct REDABufferManager {
/*e The buffer: its length and starting position */
struct REDABuffer buffer;
/*e Where in the buffer is the next available memory to use */
char *currentPosition;
/*e Increased every time getBuffer fails. */
unsigned int errorCount;
};
#define REDABufferManager_INITIALIZER \
{ \
{ 0, NULL }, /* buffer */ \
NULL, /* currentPosition */ \
0 /* errorCount */ \
}
/*e \ingroup REDABufferClass
\brief Configures a REDADynamicBufferManager
@see REDADynamicBufferManager_ensureCapacity
*/
struct REDADynamicBufferManagerProperty {
/*e The size of the initial buffer. That is, the minimum size that
* a DynamicBufferManager will allocate.
*/
unsigned int initialSize;
/*e Whether to trim to the intial size or not. When enabled, after calling
* reset or ensureCapacity with a size <= initialSize, the auxiliary buffer
* is deleted. When set to false, the auxiliary buffer never shrinks and
* will always be as big as the largest size ever requested with
* ensureCapacity.
*/
RTIBool trim;
};
/*e \ingroup REDABufferClass
\brief Default values for REDADynamicBufferManagerProperty
@see REDADynamicBufferManagerProperty
*/
#define REDADynamicBufferManagerProperty_INITIALIZER { 4092, RTI_FALSE }
/*e \ingroup REDABufferClass
\brief A memory-allocation utility to improve memory usage.
A REDADynamicBufferManager provides memory chunks of arbitrary sizes from a
contiguous buffer (see REDADynamicBufferManager_getBuffer).
Before you start asking for memory, you need to call ensureCapacity(x).
This guarantees you can request up to x bytes by calling getBuffer()
a number of times. (Note: since each chunk of memory can be aligned, the
total memory may you get may be less, so you need to account for that when
calling ensureCapacity())
You can "free" all the memory you requested at once by calling
reset(). Any memory previously requested with getBuffer() should be considered
invalid after that. The buffer manager won't actually release the underlying
buffer. After that, start over asking for memory, calling ensureCapacity()
again if needed.
When you call ensureCapacity(x) and x > property.initialSize the buffer
manager allocates (or reallocates) an auxiliary buffer of size x. When
property.trim is set and you call trim() or ensureCapacity(y) with y <=
property.initialSize the buffer manager deletes the auxiliary buffer and uses
the initial one. If trim is not set, the auxiliary buffer will never shrink.
@see REDADynamicBufferManagerProperty
*/
struct REDADynamicBufferManager {
/*e Internal buffer manager */
struct REDABufferManager _bufferManager;
/*e Configuration properties */
struct REDADynamicBufferManagerProperty _property;
/*e Initial buffer allocation */
struct REDABuffer _initialBuffer;
/*e Auxiliary buffer for larger allocations */
struct REDABuffer _largeBuffer;
};
#define REDADynamicBufferManager_INITIALIZER \
{ \
REDABufferManager_INITIALIZER, /* _bufferManager */ \
REDADynamicBufferManagerProperty_INITIALIZER, /* _property */ \
{ 0, NULL }, /* _initialBuffer */ \
{ 0, NULL }, /* _largeBuffer */ \
}
/*e \ingroup REDABufferClass
\brief static method to calculate the total data length in a gather buffer
@todo Needs to be renamed
Calculates the total size of an array of REDABuffer elements.
@pre valid answer, array, and arrayCount.
@param answer \b Out. Pointer to the integer sum of the lengths of all the
buffers.
@param array \b In. Iovec array, that is array of REDABuffer elements
@param arrayCount \b In. Number of elements in the array.
*/
extern REDADllExport void REDABufferArray_getSize(
size_t *answer,
const struct REDABuffer *array,
int arrayCount);
/*e \ingroup REDABufferClass
\brief Set the elements of a REDABuffer.
It is safer and more portable than setting the individual fields.
@pre buf answer and array.
@param pointer \b In. Underlying memory for the buffer
@param length \n In. The length of the underlying memory for the buffer
*/
extern REDADllExport void REDABuffer_set(
struct REDABuffer *me,
char *pointer,
int length);
/*e \ingroup REDABufferClass
* \brief Set the elements of a REDABuffer from an unsigned int.
* The buffer will point to the int, and the length will be 4 bytes.
*
* @param uint32Ptr \b In. The pointer to the value that the buffer's pointer
* shall be set to
*/
extern REDADllExport void REDABuffer_initializeFromUInt32(
struct REDABuffer *me,
RTI_UINT32 *uint32Ptr);
/*e \ingroup REDABufferClass
\brief Reset the elements of a REDABuffer.
It is safer and more portable than setting the individual fields.
@pre Valid buffer.
@post buffer set to REDA_BUFFER_INVALID
*/
extern REDADllExport void REDABuffer_reset(struct REDABuffer *me);
/*e \ingroup REDABufferClass
\brief Free the given REDABuffer and allocate a new one.
This has the potential to be faster than calling realloc when one does not
need to preserve the contents of the current buffer. If the given buffer is
already large enough, it is simply returned.
@note The given buffer must be in a valid state, i.e., the length must match
the size of the buffer pointer. A buffer in the reset state (length 0 and NULL
pointer) is valid.
@pre Buffer pointer not NULL and size greater than 0.
@post Buffer allocated to given size or reset if allocation failed.
@param self \b InOut. Pointer to the REDABuffer structure that is being
checked and potentially reallocated.
@param length \b In. The desired new length of the buffer. The function will
ensure that the buffer is at least this long.
@param alignment \b In. The alignment requirement for the buffer. This
ensures that the buffer's starting address satisfies the specified alignment.
*/
extern REDADllExport RTIBool REDABuffer_ensureLengthWithAlignment(
struct REDABuffer *self,
RTI_INT32 length,
RTIOsapiAlignment alignment);
/*e \ingroup REDABufferClass
\brief An invalid buffer, useful for initialization as indicated by
the usage:
\code
struct REDABuffer buf = REDA_BUFFER_INVALID;
\endcode
*/
#define REDA_BUFFER_INVALID { 0, NULL }
/*e \ingroup REDABufferClass
\brief Convert to string for printing during log messages and diagnostics.
@pre pre-allocated buffer big enough to hold the answer and valid
ptr. The function should verify this and either fail if there is not
enough space, or else truncate the output.
@post On success, the buffer holds the string and the length field
of the buffer is the numbers of characters (including the
terminating '\0'). The length field will never exceed the one passed
in. If fewer bytes are written than the available then it will be
shortened to reflect the true length of the string. On failure, the
REDABuffer is left unchanged.
@param ptr \b. In. "this" The object to be stringified.
@param buffer \b InOut. Pointer to a single REDABuffer that
satisfies the pre-condition. The function will use this to determine
where to write and the maximum number of bytes to write. REDABuffer.
@exception RTI_LOG_PRECONDITION_FAILURE
@return On success it returns the pointer to the character array
underlying the REDABuffer \e buffer. This character array should
contain the string representation of \e ptr. On failure the function
should return NULL.
@mtsafety should be implemented as a re-entrant function which will
be automatically thread-safe provided that it is not invoked
concurrently on the same buffer.
*/
typedef char *(*REDAToStringBufferFunction)(
const void *ptr,
struct REDABuffer *buffer);
/*e
* \ingroup REDABufferClass
* \brief Set the elements of a REDABufferManager.
*
* The buffer is loaned.
*
* @param pointer \b In. Underlying memory for the buffer
* @param length \n In. The length of the underlying memory for the buffer
*/
extern REDADllExport RTIBool REDABufferManager_init(
struct REDABufferManager *me,
char *pointer,
RTI_INT32 length);
/*e \ingroup REDABufferClass
\brief Initializes a REDABufferManager allocating a buffer of a given size.
The buffer is owned. Delete it with REDABufferManager_deleteBuffer
@param length \n In. The length of buffer to allocate
*/
extern REDADllExport RTIBool
REDABufferManager_createBuffer(struct REDABufferManager *me, int length);
/*e \ingroup REDABufferClass
\brief Deletes the buffer in this REDABufferManager.
Use this function when you initialized <code>me</code> with
<code>REDABufferManager_createBuffer</code>
*/
extern REDADllExport void REDABufferManager_deleteBuffer(
struct REDABufferManager *me);
/*e \ingroup REDABufferClass
\brief Resets the buffer by pointing to the beginning
After this function is called, the buffer has its original capacity and
all previous chunks of memory obtained by getBuffer should be considered
invalid. the error count is set to zero.
*/
extern REDADllExport void REDABufferManager_reset(
struct REDABufferManager *me,
RTIBool zeroBuffer);
/*e \ingroup REDABufferClass
\brief Return the starting location within the buffer of the next available
memory of a certain size.
If there's not enough space it returns NULL and increases errorCount.
@param sizeInBytes \b In. Size of memory requested
@param alignment \b In. Alignment of memory requested
*/
extern REDADllExport char *REDABufferManager_getBuffer(
struct REDABufferManager *me,
size_t sizeInBytes,
RTIOsapiAlignment alignment);
/*e \ingroup REDABufferClass
\brief Returns the number of times getBuffer has failed since the last
init or reset.
*/
extern REDADllExport unsigned int REDABufferManager_getErrorCount(
struct REDABufferManager *me);
/*e \ingroup REDABufferClass
*
*/
extern REDADllExport RTIBool REDADynamicBufferManager_initialize(
struct REDADynamicBufferManager *self,
const struct REDADynamicBufferManagerProperty *property);
/*e \ingroup REDABufferClass
*
* Ensures a buffer size of a given capacity for future calls to getBuffer().
*
* @see REDADynamicBufferManager
*/
extern REDADllExport RTIBool REDADynamicBufferManager_ensureCapacity(
struct REDADynamicBufferManager *self,
unsigned int capacity);
/*e \ingroup REDABufferClass
*
*/
extern REDADllExport unsigned int REDADynamicBufferManager_getCapacity(
struct REDADynamicBufferManager *self);
/*e \ingroup REDABufferClass
*
* @see REDADynamicBufferManager
*/
extern REDADllExport void REDADynamicBufferManager_trim(
struct REDADynamicBufferManager *self);
/*e \ingroup REDABufferClass
*
* Returns a buffer of a given size.
*
* Returns NULL if this buffer manager doesn't have enough capacity to return
* a buffer of that size with the requested alignment.
*
* @see REDADynamicBufferManager
*/
extern REDADllExport char *REDADynamicBufferManager_getBuffer(
struct REDADynamicBufferManager *self,
unsigned int sizeInBytes,
RTIOsapiAlignment alignment);
/*e
* \ingroup REDABufferClass
*
* Allows re-using the underlying buffer from the beginning. After calling
* reset() all memory previously obtained with getBuffer() is invalid.
*
* The caller can choose whether the contents of the buffers are zeroed out
* by providing the value of zeroBuffer.
*
* @param self The manager to reset
* @param zeroBuffer if set to TRUE, the buffer contents will be reset to 0. If
* set to FALSE, the contents of the memory are left as-is
*
* @see REDADynamicBufferManager
*/
extern REDADllExport void REDADynamicBufferManager_reset(
struct REDADynamicBufferManager *self,
RTIBool zeroBuffer);
/*e \ingroup REDABufferClass
*
*/
extern REDADllExport void REDADynamicBufferManager_finalize(
struct REDADynamicBufferManager *self);
#ifdef __cplusplus
} /* extern "C" */
#endif
/* pick up hidden performance boosting macros and optimizations */
#include "reda/reda_buffer_impl.h"
#endif /* reda_buffer_h */