/* 9p/internal.h - TODO * * Copyright (C) 2024 Luke T. Shumaker * SPDX-Licence-Identifier: AGPL-3.0-or-later */ #ifndef _9P_INTERNAL_H_ #define _9P_INTERNAL_H_ #include #include #include "9p/defs.h" /* C language *****************************************************************/ #define UNUSED(name) /* name __attribute__ ((unused)) */ /* vtables ********************************************************************/ typedef bool (*_checksize_fn_t)(uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra); typedef bool (*_unmarshal_fn_t)(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra, void *out); typedef bool (*_marshal_fn_t)(struct p9_ctx *ctx, void *val, uint8_t *out_net_bytes, uint32_t *mut_net_offset); struct msg_vtable { size_t unmarshal_basesize; _checksize_fn_t unmarshal_extrasize; _unmarshal_fn_t unmarshal; _marshal_fn_t marshal; }; struct version { struct msg_vtable msgs[0xFF]; }; extern struct version version_9P2000; /*extern struct version version_9P2000u; */ /* unmarshal utilities ********************************************************/ static inline uint8_t decode_u8le(uint8_t *in) { return in[0]; } static inline uint16_t decode_u16le(uint8_t *in) { return (((uint16_t)(in[0])) << 0) | (((uint16_t)(in[1])) << 8) ; } static inline uint32_t decode_u32le(uint8_t *in) { return (((uint32_t)(in[0])) << 0) | (((uint32_t)(in[1])) << 8) | (((uint32_t)(in[2])) << 16) | (((uint32_t)(in[3])) << 24) ; } static inline uint64_t decode_u64le(uint8_t *in) { return (((uint64_t)(in[0])) << 0) | (((uint64_t)(in[1])) << 8) | (((uint64_t)(in[2])) << 16) | (((uint64_t)(in[3])) << 24) | (((uint64_t)(in[4])) << 32) | (((uint64_t)(in[5])) << 40) | (((uint64_t)(in[6])) << 48) | (((uint64_t)(in[7])) << 56) ; } static inline bool is_valid_utf8_without_nul(uint8_t *str, size_t len) { uint8_t mask; uint8_t chlen; for (size_t pos = 0; pos < len;) { if ((str[pos] & 0b10000000) == 0b00000000) { mask = 0b01111111; chlen = 1; } else if ((str[pos] & 0b11100000) == 0b11000000) { mask = 0b00011111; chlen = 2; } else if ((str[pos] & 0b11110000) == 0b11100000) { mask = 0b00001111; chlen = 3; } else if ((str[pos] & 0b11111000) == 0b11110000) { mask = 0b00000111; chlen = 4; } else return false; if (pos + chlen > len || (str[pos] & mask) == 0) return false; switch (chlen) { case 4: if ((str[pos+3] & 0b11000000) != 0b10000000) return false; /* fallthrough */ case 3: if ((str[pos+2] & 0b11000000) != 0b10000000) return false; /* fallthrough */ case 2: if ((str[pos+1] & 0b11000000) != 0b10000000) return false; /* fallthrough */ } pos += chlen; } return true; } /* marshal utilities **********************************************************/ static inline void encode_u8le(uint8_t in, uint8_t *out) { out[0] = in; } static inline void encode_u16le(uint16_t in, uint8_t *out) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); } static inline void encode_u32le(uint32_t in, uint8_t *out) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); out[2] = (uint8_t)((in >> 16) & 0xFF); out[3] = (uint8_t)((in >> 24) & 0xFF); } static inline void encode_u64le(uint64_t in, uint8_t *out) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); out[2] = (uint8_t)((in >> 16) & 0xFF); out[3] = (uint8_t)((in >> 24) & 0xFF); out[4] = (uint8_t)((in >> 32) & 0xFF); out[5] = (uint8_t)((in >> 40) & 0xFF); out[6] = (uint8_t)((in >> 48) & 0xFF); out[7] = (uint8_t)((in >> 56) & 0xFF); } #endif /* _9P_INTERNAL_H_ */