132 lines
5.5 KiB
C
132 lines
5.5 KiB
C
#include "c_BinaryOutStream.h"
|
|
#include "c_BufferOutputStream.h"
|
|
#include "c_Float.h"
|
|
#include "c_Test.h"
|
|
#include "c_Hex.h"
|
|
|
|
typedef struct {
|
|
const unsigned char* data;
|
|
c_size_t size;
|
|
c_size_t byte_ptr;
|
|
int buffer;
|
|
int n;
|
|
} c_BinaryInHelper_t;
|
|
|
|
static inline void c_BinaryInHelper_Init(c_BinaryInHelper_t* self, const void* data, c_size_t size) {
|
|
self->data = (const unsigned char*)data;
|
|
self->size = size;
|
|
self->byte_ptr = 0;
|
|
self->buffer = 0;
|
|
self->n = 0;
|
|
}
|
|
|
|
static inline uint32_t c_BinaryInHelper_ReadBits(c_BinaryInHelper_t* self, int bit_count) {
|
|
uint32_t result = 0;
|
|
for (int i = 0; i < bit_count; ++i) {
|
|
if (self->n == 0) {
|
|
self->buffer = self->data[self->byte_ptr++];
|
|
self->n = 8;
|
|
}
|
|
int bit = (self->buffer >> (self->n - 1)) & 1;
|
|
self->n--;
|
|
result = (result << 1) | bit;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
TEST_CASE(test_binary_out_stream_extended_apis) {
|
|
c_OutStream_t* mem_stream = NULL;
|
|
|
|
/* 1. Spin up an in-memory dynamic serialization stream subclass */
|
|
c_err_t err = c_BufferOutputStream_Create(&mem_stream, 32, NULL);
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
|
|
|
/* 2. Bind the expanded binary bit-packer onto the abstract handle */
|
|
c_BinaryOutStream_t bin_out;
|
|
err = c_BinaryOutStream_Init(&bin_out, mem_stream);
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
|
|
|
/* 3. Serialize a mixture of unaligned bits and primitive types */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteBit(&bin_out, 1)); /* 1 bit */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteBits(&bin_out, 0x0A, 4)); /* 4 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteByte(&bin_out, 0xFE)); /* 8 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteChar(&bin_out, 'C')); /* 8 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteUInt16(&bin_out, 0xABCD)); /* 16 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteUInt32(&bin_out, 0x12345678)); /* 32 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteUInt64(&bin_out, 0x1122334455667788ULL)); /* 64 bits */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteFloat(&bin_out, -2.0f)); /* 32 bits (IEEE 754) */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteDouble(&bin_out, 3.1415926535)); /* 64 bits (IEEE 754) */
|
|
ASSERT_INT_EQ(C_SUCCESS, c_BinaryOutStream_WriteString(&bin_out, "DAG")); /* 'D','A','G','\0' bytes */
|
|
|
|
/* Flush out the remaining bit cache down into the underlying memory stream buffer */
|
|
err = c_BinaryOutStream_Flush(&bin_out);
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
|
|
|
/* 4. Intercept the written raw payload buffer to verify bit-level precision */
|
|
const void* raw_data = NULL;
|
|
c_size_t total_bytes = 0;
|
|
err = c_BufferOutputStream_GetBuffer(mem_stream, &raw_data, &total_bytes);
|
|
ASSERT_INT_EQ(C_SUCCESS, err);
|
|
ASSERT_TRUE(total_bytes > 0);
|
|
|
|
c_Hex_Dump(raw_data, total_bytes);
|
|
|
|
/* 5. Initialize our bit-level reader helper over the raw payload */
|
|
c_BinaryInHelper_t bin_in;
|
|
c_BinaryInHelper_Init(&bin_in, raw_data, total_bytes);
|
|
|
|
/* Verify unaligned bit configurations */
|
|
ASSERT_LL_EQ(1, c_BinaryInHelper_ReadBits(&bin_in, 1));
|
|
ASSERT_LL_EQ(0x0A, c_BinaryInHelper_ReadBits(&bin_in, 4));
|
|
|
|
/* Verify byte-aligned primitives */
|
|
ASSERT_LL_EQ(0xFE, c_BinaryInHelper_ReadBits(&bin_in, 8));
|
|
ASSERT_LL_EQ('C', c_BinaryInHelper_ReadBits(&bin_in, 8));
|
|
ASSERT_LL_EQ(0xABCD, c_BinaryInHelper_ReadBits(&bin_in, 16));
|
|
ASSERT_LL_EQ(0x12345678, c_BinaryInHelper_ReadBits(&bin_in, 32));
|
|
|
|
/* Reconstruct 64-bit unsigned integer splits */
|
|
uint64_t actual_u64 = ((uint64_t)c_BinaryInHelper_ReadBits(&bin_in, 32) << 32) | c_BinaryInHelper_ReadBits(&bin_in, 32);
|
|
ASSERT_LL_EQ(0x1122334455667788ULL, actual_u64);
|
|
|
|
/* Verify IEEE 754 Single-Precision Float using your bit-casting utilities */
|
|
uint32_t float_bits = c_BinaryInHelper_ReadBits(&bin_in, 32);
|
|
c_float_t actual_float = c_Float_FromBits(float_bits);
|
|
ASSERT_DOUBLE_EQ_MSG(-2.0, (double)actual_float, "Float stream serialization precision failed");
|
|
|
|
/* Verify IEEE 754 Double-Precision Float */
|
|
uint64_t double_bits = ((uint64_t)c_BinaryInHelper_ReadBits(&bin_in, 32) << 32) | c_BinaryInHelper_ReadBits(&bin_in, 32);
|
|
c_double_t actual_double = c_Double_FromBits(double_bits);
|
|
/* Float comparisons use your Epsilon tolerances helper pattern */
|
|
ASSERT_TRUE(fabs(actual_double - 3.1415926535) <= 1e-9);
|
|
|
|
/* Verify null-terminated String extraction sequence loops */
|
|
char actual_str[4];
|
|
actual_str[0] = (char)c_BinaryInHelper_ReadBits(&bin_in, 8);
|
|
actual_str[1] = (char)c_BinaryInHelper_ReadBits(&bin_in, 8);
|
|
actual_str[2] = (char)c_BinaryInHelper_ReadBits(&bin_in, 8);
|
|
actual_str[3] = (char)c_BinaryInHelper_ReadBits(&bin_in, 8); /* Should read the '\0' delimiter */
|
|
|
|
ASSERT_INT_EQ(0, strcmp("DAG", actual_str));
|
|
ASSERT_INT_EQ('\0', actual_str[3]);
|
|
|
|
/* 6. Clean up polymorphic dynamic stream via virtual tables */
|
|
c_OutStream_Destroy(mem_stream);
|
|
}
|
|
|
|
int main(void) {
|
|
/* Fire up the core testing wrapper suite */
|
|
TEST_START(BinaryOutStream_ExtendedAPIs_Suite);
|
|
|
|
/* Run the specified data stream pipeline integration test */
|
|
RUN_TEST(test_binary_out_stream_extended_apis);
|
|
|
|
/* Output summary metrics logs to console */
|
|
TEST_REPORT();
|
|
|
|
/* Unwind back with proper testing suite status codes */
|
|
RETURN_TEST_STATUS;
|
|
}
|
|
|