83 lines
2.5 KiB
C
83 lines
2.5 KiB
C
#include "sim_event.h"
|
|
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
typedef struct sim_event_state {
|
|
uint32_t count;
|
|
uint32_t last_seq;
|
|
uint32_t last_tick;
|
|
sim_event_record records[SIM_EVENT_CAPACITY];
|
|
} sim_event_state;
|
|
|
|
static sim_event_state state;
|
|
|
|
static uint64_t hash_payload(const uint8_t *payload, uint32_t payload_len) {
|
|
uint64_t hash = 1469598103934665603ULL;
|
|
uint32_t index;
|
|
if (payload == NULL && payload_len != 0U) return 0;
|
|
for (index = 0; index < payload_len; ++index) {
|
|
hash ^= payload[index];
|
|
hash *= 1099511628211ULL;
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
void sim_event_reset(void) {
|
|
memset(&state, 0, sizeof(state));
|
|
}
|
|
|
|
int32_t sim_event_append(uint32_t seq, uint32_t tick, const char *kind,
|
|
const uint8_t *payload, uint32_t payload_len) {
|
|
sim_event_record *record;
|
|
size_t kind_len;
|
|
if (seq == 0U || seq != state.last_seq + 1U) return SIM_EVENT_ERR_SEQUENCE;
|
|
if (tick < state.last_tick) return SIM_EVENT_ERR_TICK;
|
|
if (kind == NULL || kind[0] == '\0') return SIM_EVENT_ERR_ARGUMENT;
|
|
kind_len = strlen(kind);
|
|
if (kind_len >= SIM_EVENT_KIND_CAPACITY || (payload == NULL && payload_len != 0U)) return SIM_EVENT_ERR_ARGUMENT;
|
|
if (state.count >= SIM_EVENT_CAPACITY) return SIM_EVENT_ERR_FULL;
|
|
record = &state.records[state.count++];
|
|
memset(record, 0, sizeof(*record));
|
|
memcpy(record->kind, kind, kind_len);
|
|
record->seq = seq;
|
|
record->tick = tick;
|
|
record->payload_hash = hash_payload(payload, payload_len);
|
|
state.last_seq = seq;
|
|
state.last_tick = tick;
|
|
return SIM_EVENT_OK;
|
|
}
|
|
|
|
uint32_t sim_event_count(void) {
|
|
return state.count;
|
|
}
|
|
|
|
uint32_t sim_event_cursor(void) {
|
|
return state.last_seq;
|
|
}
|
|
|
|
uint32_t sim_event_read(uint32_t index, uint8_t *out, uint32_t capacity) {
|
|
const uint32_t size = (uint32_t)sizeof(sim_event_record);
|
|
if (index >= state.count) return 0;
|
|
if (out == NULL || capacity < size) return size;
|
|
memcpy(out, &state.records[index], size);
|
|
return size;
|
|
}
|
|
|
|
uint32_t sim_event_export(uint8_t *out, uint32_t capacity) {
|
|
const uint32_t size = (uint32_t)sizeof(state);
|
|
if (out == NULL || capacity < size) return size;
|
|
memcpy(out, &state, size);
|
|
return size;
|
|
}
|
|
|
|
int32_t sim_event_import(const uint8_t *data, uint32_t len) {
|
|
if (data == NULL || len != sizeof(state)) return SIM_EVENT_ERR_ARGUMENT;
|
|
memcpy(&state, data, sizeof(state));
|
|
if (state.count > SIM_EVENT_CAPACITY) {
|
|
sim_event_reset();
|
|
return SIM_EVENT_ERR_ARGUMENT;
|
|
}
|
|
return SIM_EVENT_OK;
|
|
}
|