Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
Buffer Module - User Guide

What is a Buffer?

  • A Buffer is a lightweight, bounds-tracked view over caller-owned storage.
  • You provide the backing storage (static array, stack buffer), and the buffer
  • tracks how much data is currently valid. No allocation, no freeing - just
  • state tracking.
  • Key concept: Buffer is a VIEW, not the owner of storage.

Quick Start

1. Allocate Backing Storage

  • * // Static buffer for 256 bytes
    * static uint8_t buffer_storage[256];
    *

2. Bind Buffer View

  • * sapi_buffer_t buf;
    *
    * sapi_status_t rc = sapi_buffer_init(&buf, buffer_storage, sizeof(buffer_storage));
    * if (rc != SAPI_STATUS_OK) {
    * printf("Buffer init failed\n");
    * return rc;
    * }
    *
    * // buf now has: data=buffer_storage, capacity=256, length=0
    *

3. Use Buffer

  • * // Write data into storage (caller manages writes to data pointer)
    * memcpy(buf.data, input, input_len);
    *
    * // Mark data as valid
    * sapi_buffer_set_length(&buf, input_len);
    *
    * // Read data
    * printf("Buffer contains %zu bytes\n", buf.length);
    *
    * // Clear for reuse
    * sapi_buffer_clear(&buf); // Sets length=0, keeps data/capacity
    *

Key Structures

  • * typedef struct {
    * void *data; // Pointer to backing storage (caller-owned)
    * size_t capacity; // Total bytes available in storage
    * size_t length; // Bytes currently holding valid data
    * } sapi_buffer_t;
    *
    * typedef struct {
    * const void *data; // Read-only view of data
    * size_t length; // Bytes of valid data
    * } sapi_const_buffer_t;
    *
  • Invariant: length <= capacity

Practical Examples

Example 1: Fixed-Size Message Buffer

  • * typedef struct {
    * uint32_t command_id;
    * uint32_t seq_num;
    * uint8_t payload[128];
    * } message_t;
    *
    * message_t msg = {0};
    * sapi_buffer_t buf;
    *
    * // Bind buffer to message payload
    * sapi_buffer_init(&buf, msg.payload, sizeof(msg.payload));
    *
    * // Receive data into payload
    * receive_from_network(&buf.data[0], 64);
    * sapi_buffer_set_length(&buf, 64);
    *
    * // Send message
    * msg.command_id = 1;
    * msg.seq_num = seq++;
    * send_message(&msg);
    *
    * // Clear for next use
    * sapi_buffer_clear(&buf);
    *

Example 2: Read-Only View

  • * sapi_buffer_t mutable_buf = {...};
    *
    * // Create read-only view
    * sapi_const_buffer_t view = {
    * .data = mutable_buf.data,
    * .length = mutable_buf.length
    * };
    *
    * // Pass to function that should not modify
    * process_read_only(&view);
    *

Buffer Operations

Initialize

  • * sapi_buffer_init(&buf, storage, capacity);
    *
  • - Sets buf.data = storage
  • - Sets buf.capacity = capacity
  • - Sets buf.length = 0
  • - Returns INVALID_PARAM if storage==NULL or capacity==0

Write Data

  • * // Caller writes to buf.data
    * memcpy(buf.data + offset, input, size);
    *
    * // Mark data as valid
    * sapi_buffer_set_length(&buf, new_length);
    *
  • sapi_buffer_set_length() fails if new_length > capacity.

Read Data

  • * // Caller reads from buf.data
    * size_t n = buf.length; // How much valid data
    * memcpy(output, buf.data, n);
    *

Clear

  • * sapi_buffer_clear(&buf); // Sets length=0, keeps capacity/data
    *

Best Practices

  • 1. Caller owns storage lifetime
  • - Buffer just tracks state
  • - Storage must outlive buffer
  • - Static or stack allocation recommended
  • 2. Check capacity before writing
  • - Caller responsible for bounds checking
  • - Buffer tracks length, not write protection
  • - sapi_buffer_set_length() validates
  • 3. Use sapi_buffer_set_length() for bounds checking
  • - Always call after writing
  • - Returns error if length > capacity
  • - Prevents out-of-bounds bugs
  • 4. Use const_buffer_t for read-only access
  • - Pass to functions that should not modify
  • - Type-safe read-only contract
  • 5. Clear when done
  • - Reset length to 0 for reuse
  • - Resets valid-data range, not storage

See Also