#ifndef MOLECULE_READER_H #define MOLECULE_READER_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include #include #ifndef MOLECULE_API_DECORATOR #define __DEFINE_MOLECULE_API_DECORATOR #define MOLECULE_API_DECORATOR #endif /* MOLECULE_API_DECORATOR */ #define MOLECULE_API_VERSION 7000 #define MOLECULEC_VERSION_MIN 5000 #if MOLECULE_API_VERSION < MOLECULE_API_VERSION_MIN #error This file was generated by a newer version of moleculec which is \ incompatible with current headers in use. Please update the headers. #endif #if MOLECULEC_VERSION < MOLECULEC_VERSION_MIN #error This file was generated by an older version of moleculec which is \ incompatible with current headers in use. Please regenerate this file \ with a newer version of moleculec. #endif /* * This part is not for normal users. */ // Test if the host is big endian machine. #define is_le() \ ((union { \ uint16_t i; \ unsigned char c; \ }){.i = 1} \ .c) /* * Definitions of types and simple utilities. */ /* Core types */ typedef uint32_t mol_num_t; // Item Id typedef uint8_t mol_errno; // Error Number #define MolNum UINT32_C #define MOL_NUM_T_SIZE 4 // Bytes segment. typedef struct { uint8_t *ptr; // Pointer mol_num_t size; // Full size } mol_seg_t; // Unpacked Union typedef struct { mol_num_t item_id; // Item Id mol_seg_t seg; // Segment } mol_union_t; // Result for returning segment. typedef struct { mol_errno errno; // Error Number mol_seg_t seg; // Segment } mol_seg_res_t; /* Error Numbers */ #define MOL_OK 0x00 #define MOL_ERR 0xff #define MOL_ERR_TOTAL_SIZE 0x01 #define MOL_ERR_HEADER 0x02 #define MOL_ERR_OFFSET 0x03 #define MOL_ERR_UNKNOWN_ITEM 0x04 #define MOL_ERR_INDEX_OUT_OF_BOUNDS 0x05 #define MOL_ERR_FIELD_COUNT 0x06 #define MOL_ERR_DATA 0x07 /* Utilities. */ MOLECULE_API_DECORATOR mol_num_t mol_unpack_number(const uint8_t *src) { uint32_t output = 0; uint8_t *dst = (uint8_t *)&output; if (is_le()) { dst[3] = src[3]; dst[2] = src[2]; dst[1] = src[1]; dst[0] = src[0]; } else { dst[3] = src[0]; dst[2] = src[1]; dst[1] = src[2]; dst[0] = src[3]; } return output; } /* * Core functions. */ /* Verify Functions. */ // Verify Array / Struct. MOLECULE_API_DECORATOR mol_errno mol_verify_fixed_size(const mol_seg_t *input, mol_num_t total_size) { return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE; } // Verify FixVec. MOLECULE_API_DECORATOR mol_errno mol_fixvec_verify(const mol_seg_t *input, mol_num_t item_size) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } mol_num_t item_count = mol_unpack_number(input->ptr); if (item_count == 0) { return input->size == MOL_NUM_T_SIZE ? MOL_OK : MOL_ERR_TOTAL_SIZE; } mol_num_t total_size = MOL_NUM_T_SIZE + item_size * item_count; return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE; } /* Getters. * * ### Notice * * The input of getters should be checked. * * These getters will raise segmentation fault if the input is illegal or * return an incorrect result. */ // Check if an Option is None. MOLECULE_API_DECORATOR bool mol_option_is_none(const mol_seg_t *input) { return input->size == 0; } // Get the inner of a Union. MOLECULE_API_DECORATOR mol_union_t mol_union_unpack(const mol_seg_t *input) { mol_union_t ret; ret.item_id = mol_unpack_number(input->ptr); ret.seg.ptr = input->ptr + MOL_NUM_T_SIZE; ret.seg.size = input->size - MOL_NUM_T_SIZE; return ret; } // Get the length of a FixVec. MOLECULE_API_DECORATOR mol_num_t mol_fixvec_length(const mol_seg_t *input) { return mol_unpack_number(input->ptr); } // Get the length of a DynVec. MOLECULE_API_DECORATOR mol_num_t mol_dynvec_length(const mol_seg_t *input) { if (input->size == MOL_NUM_T_SIZE) { return 0; } else { return (mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1; } } // Get the actual field count of a Table. MOLECULE_API_DECORATOR mol_num_t mol_table_actual_field_count(const mol_seg_t *input) { return mol_dynvec_length(input); } // If a Table has extra fields. MOLECULE_API_DECORATOR bool mol_table_has_extra_fields(const mol_seg_t *input, mol_num_t field_count) { return mol_table_actual_field_count(input) > field_count; } // Slice a segment for Array / Struct by offset. MOLECULE_API_DECORATOR mol_seg_t mol_slice_by_offset(const mol_seg_t *input, mol_num_t offset, mol_num_t size) { mol_seg_t seg; seg.ptr = input->ptr + offset; seg.size = size; return seg; } // Slice a segment for FixVec by index. MOLECULE_API_DECORATOR mol_seg_res_t mol_fixvec_slice_by_index( const mol_seg_t *input, mol_num_t item_size, mol_num_t item_index) { mol_seg_res_t res; mol_num_t item_count = mol_unpack_number(input->ptr); if (item_index >= item_count) { res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; } else { res.errno = MOL_OK; res.seg.ptr = input->ptr + MOL_NUM_T_SIZE + item_size * item_index; res.seg.size = item_size; } return res; } // Slice a segment for DynVec by index. MOLECULE_API_DECORATOR mol_seg_res_t mol_dynvec_slice_by_index(const mol_seg_t *input, mol_num_t item_index) { mol_seg_res_t res; mol_num_t total_size = mol_unpack_number(input->ptr); if (total_size == MOL_NUM_T_SIZE) { res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; } else { mol_num_t item_count = (mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1; if (item_index >= item_count) { res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; } else { mol_num_t item_start = mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 1)); if (item_index + 1 == item_count) { res.errno = MOL_OK; res.seg.ptr = input->ptr + item_start; res.seg.size = total_size - item_start; } else { mol_num_t item_end = mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 2)); res.errno = MOL_OK; res.seg.ptr = input->ptr + item_start; res.seg.size = item_end - item_start; } } } return res; } // Slice a segment for Table by index. MOLECULE_API_DECORATOR mol_seg_t mol_table_slice_by_index(const mol_seg_t *input, mol_num_t field_index) { mol_seg_res_t res = mol_dynvec_slice_by_index(input, field_index); return res.seg; } // Slice the raw bytes from a `vector ` (FixVec, with a header). MOLECULE_API_DECORATOR mol_seg_t mol_fixvec_slice_raw_bytes(const mol_seg_t *input) { mol_seg_t seg; seg.ptr = input->ptr + MOL_NUM_T_SIZE; seg.size = mol_unpack_number(input->ptr); return seg; } // Check if a segment(`part`) is contained by `total` MOLECULE_API_DECORATOR bool mol_contained_by(const mol_seg_t *part, const mol_seg_t *total) { if (part->ptr < total->ptr) { return MOL_ERR_OFFSET; } if ((part->ptr + part->size) > (total->ptr + total->size)) { return MOL_ERR_OFFSET; } return MOL_OK; } /* * Undef macros which are internal use only. */ #undef is_le #ifdef __DEFINE_MOLECULE_API_DECORATOR #undef MOLECULE_API_DECORATOR #undef __DEFINE_MOLECULE_API_DECORATOR #endif /* __DEFINE_MOLECULE_API_DECORATOR */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* MOLECULE_READER_H */