116 lines
3.9 KiB
C
116 lines
3.9 KiB
C
#include <c_BinaryInStream.h>
|
|
#include "c_Float.h"
|
|
|
|
c_err_t c_BinaryInStream_Init(c_BinaryInStream_t* self, c_InStream_t* underlying_io_port) {
|
|
if (!self || !underlying_io_port) return C_ERR_PARAM;
|
|
self->base_io = underlying_io_port;
|
|
self->buffer = 0;
|
|
self->n = 0;
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadBits(c_BinaryInStream_t* self, int bit_count, uint32_t* out_value) {
|
|
if (!self || !self->base_io || !out_value || bit_count < 1 || bit_count > 32) return C_ERR_PARAM;
|
|
|
|
uint32_t result = 0;
|
|
for (int i = 0; i < bit_count; ++i) {
|
|
if (self->n == 0) {
|
|
unsigned char next_byte = 0;
|
|
c_size_t read_bytes = 0;
|
|
c_err_t err = c_InStream_Read(self->base_io, &next_byte, 1, &read_bytes);
|
|
if (err != C_SUCCESS && err != C_ERR_OUTOFBOUND) return err;
|
|
if (read_bytes == 0) return C_ERR_OUTOFBOUND;
|
|
|
|
self->buffer = next_byte;
|
|
self->n = 8;
|
|
}
|
|
int bit = (self->buffer >> (self->n - 1)) & 1;
|
|
self->n--;
|
|
result = (result << 1) | bit;
|
|
}
|
|
*out_value = result;
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadBit(c_BinaryInStream_t* self, int* out_bit) {
|
|
if (!out_bit) return C_ERR_PARAM;
|
|
uint32_t val = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 1, &val);
|
|
if (err == C_SUCCESS) *out_bit = (int)val;
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadByte(c_BinaryInStream_t* self, int* out_byte) {
|
|
if (!out_byte) return C_ERR_PARAM;
|
|
uint32_t val = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 8, &val);
|
|
if (err == C_SUCCESS) *out_byte = (int)val;
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadChar(c_BinaryInStream_t* self, char* out_char) {
|
|
if (!out_char) return C_ERR_PARAM;
|
|
uint32_t val = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 8, &val);
|
|
if (err == C_SUCCESS) *out_char = (char)val;
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadUInt16(c_BinaryInStream_t* self, uint16_t* out_x) {
|
|
if (!out_x) return C_ERR_PARAM;
|
|
uint32_t val = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 16, &val);
|
|
if (err == C_SUCCESS) *out_x = (uint16_t)val;
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadUInt32(c_BinaryInStream_t* self, uint32_t* out_x) {
|
|
return c_BinaryInStream_ReadBits(self, 32, out_x);
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadUInt64(c_BinaryInStream_t* self, uint64_t* out_x) {
|
|
if (!out_x) return C_ERR_PARAM;
|
|
uint32_t high = 0, low = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 32, &high);
|
|
if (err != C_SUCCESS) return err;
|
|
err = c_BinaryInStream_ReadBits(self, 32, &low);
|
|
if (err != C_SUCCESS) return err;
|
|
*out_x = ((uint64_t)high << 32) | low;
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadFloat(c_BinaryInStream_t* self, float* out_x) {
|
|
if (!out_x) return C_ERR_PARAM;
|
|
uint32_t bits = 0;
|
|
c_err_t err = c_BinaryInStream_ReadBits(self, 32, &bits);
|
|
if (err == C_SUCCESS) *out_x = c_Float_FromBits(bits);
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadDouble(c_BinaryInStream_t* self, double* out_x) {
|
|
if (!out_x) return C_ERR_PARAM;
|
|
uint64_t bits = 0;
|
|
c_err_t err = c_BinaryInStream_ReadUInt64(self, &bits);
|
|
if (err == C_SUCCESS) *out_x = c_Double_FromBits(bits);
|
|
return err;
|
|
}
|
|
|
|
c_err_t c_BinaryInStream_ReadString(c_BinaryInStream_t* self, char* out_buffer, c_size_t buffer_cap) {
|
|
if (!self || !out_buffer || buffer_cap == 0) return C_ERR_PARAM;
|
|
|
|
c_size_t idx = 0;
|
|
while (idx < buffer_cap - 1) {
|
|
char ch = 0;
|
|
c_err_t err = c_BinaryInStream_ReadChar(self, &ch);
|
|
if (err != C_SUCCESS) {
|
|
out_buffer[idx] = '\0';
|
|
return err;
|
|
}
|
|
|
|
out_buffer[idx++] = ch;
|
|
if (ch == '\0') return C_SUCCESS; /* Completed extraction sequence safely */
|
|
}
|
|
|
|
out_buffer[idx] = '\0'; /* Force sentinel safety ceiling string termination */
|
|
return C_ERR_OUTOFBOUND;
|
|
} |