@@ -103,6 +103,255 @@ uint64_t ptk_bswap64(uint64_t value);
103103bool ptk_is_little_endian (void );
104104bool ptk_is_big_endian (void );
105105
106+
107+
108+ //=============================================================================
109+ // TYPE-SAFE SERIALIZATION API
110+ //=============================================================================
111+
112+ // Forward declarations for type-safe serialization
113+ typedef enum {
114+ PTK_BUF_TYPE_U8 = 1 , // uint8_t
115+ PTK_BUF_TYPE_U16 , // uint16_t
116+ PTK_BUF_TYPE_U32 , // uint32_t
117+ PTK_BUF_TYPE_U64 , // uint64_t
118+ PTK_BUF_TYPE_S8 , // int8_t
119+ PTK_BUF_TYPE_S16 , // int16_t
120+ PTK_BUF_TYPE_S32 , // int32_t
121+ PTK_BUF_TYPE_S64 , // int64_t
122+ PTK_BUF_TYPE_FLOAT , // float
123+ PTK_BUF_TYPE_DOUBLE , // double
124+ PTK_BUF_TYPE_SERIALIZABLE , // struct ptk_serializable*
125+ } ptk_buf_type_t ;
126+
127+ typedef enum { PTK_BUF_LITTLE_ENDIAN = 0 , PTK_BUF_BIG_ENDIAN = 1 } ptk_buf_endian_t ;
128+
129+ /**
130+ * Implementation function for type-safe serialization
131+ *
132+ * Moves the cursor forward by the size of the serialized data.
133+ *
134+ * @param buf Buffer to write to
135+ * @param endian Endianness for multi-byte values
136+ * @param count Number of fields to serialize
137+ * @param ... Alternating type_enum, value pairs
138+ * @return Error code
139+ */
140+ PTK_API extern ptk_err_t ptk_buf_serialize_impl (ptk_buf * buf , ptk_buf_endian_t endian , ptk_buf_size_t count , ...);
141+
142+ /**
143+ * Implementation function for type-safe deserialization
144+ *
145+ * Moves the cursor forward by the size of the deserialized data.
146+ *
147+ * Leaves the cursor unchanged if peek is true.
148+ *
149+ * Leaves the cursor unchanged if there is an error.
150+ *
151+ * @param buf Buffer to read from
152+ * @param peek Whether to peek (don't advance buffer position)
153+ * @param endian Endianness for multi-byte values
154+ * @param count Number of fields to deserialize
155+ * @param ... Alternating type_enum, pointer pairs
156+ * @return Error code
157+ */
158+ PTK_API extern ptk_err_t ptk_buf_deserialize_impl (ptk_buf * buf , bool peek , ptk_buf_endian_t endian , ptk_buf_size_t count , ...);
159+
160+ /* byte swap helpers */
161+
162+ /**
163+ * @brief swap the bytes in each 16-bit word
164+ *
165+ * @param value
166+ * @return ptk_u32_t
167+ */
168+ static inline ptk_u32_t ptk_buf_byte_swap_u32 (ptk_u32_t value ) {
169+ return ((value & 0x000000FF ) << 24 ) | ((value & 0x0000FF00 ) << 8 ) | ((value & 0x00FF0000 ) >> 8 )
170+ | ((value & 0xFF000000 ) >> 24 );
171+ }
172+
173+ static inline ptk_u64_t ptk_buf_byte_swap_u64 (ptk_u64_t value ) {
174+ return ((value & 0x00000000000000FFULL ) << 56 ) | ((value & 0x000000000000FF00ULL ) << 40 )
175+ | ((value & 0x0000000000FF0000ULL ) << 24 ) | ((value & 0x00000000FF000000ULL ) << 8 )
176+ | ((value & 0x000000FF00000000ULL ) >> 8 ) | ((value & 0x0000FF0000000000ULL ) >> 24 )
177+ | ((value & 0x00FF000000000000ULL ) >> 40 ) | ((value & 0xFF00000000000000ULL ) >> 56 );
178+ }
179+
180+ //=============================================================================
181+ // TYPE-SAFE SERIALIZATION MACROS
182+ //=============================================================================
183+
184+ /**
185+ * Map C types to type enumeration using _Generic
186+ */
187+ #define PTK_BUF_TYPE_OF (x ) \
188+ _Generic((x), \
189+ uint8_t: PTK_BUF_TYPE_U8, \
190+ uint16_t: PTK_BUF_TYPE_U16, \
191+ uint32_t: PTK_BUF_TYPE_U32, \
192+ uint64_t: PTK_BUF_TYPE_U64, \
193+ int8_t: PTK_BUF_TYPE_S8, \
194+ int16_t: PTK_BUF_TYPE_S16, \
195+ int32_t: PTK_BUF_TYPE_S32, \
196+ int64_t: PTK_BUF_TYPE_S64, \
197+ float: PTK_BUF_TYPE_FLOAT, \
198+ double: PTK_BUF_TYPE_DOUBLE, \
199+ ptk_serializable_t *: PTK_BUF_TYPE_SERIALIZABLE, \
200+ ptk_serializable_t: PTK_BUF_TYPE_SERIALIZABLE, \
201+ default: 0)
202+
203+ /**
204+ * For pointers, handle serializable objects specially, dereference others
205+ */
206+ #define PTK_BUF_TYPE_OF_PTR (ptr ) \
207+ _Generic((ptr), ptk_serializable_t * *: PTK_BUF_TYPE_SERIALIZABLE, default: PTK_BUF_TYPE_OF(*(ptr)))
208+
209+ //=============================================================================
210+ // ARGUMENT COUNTING MACROS
211+ //=============================================================================
212+
213+ /**
214+ * Count arguments (up to 64 arguments, so 32 fields max)
215+ */
216+ #define PTK_BUF_ARG_COUNT (...) \
217+ PTK_BUF_ARG_COUNT_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, \
218+ 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \
219+ 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
220+
221+ #define PTK_BUF_ARG_COUNT_IMPL (_1 , _2 , _3 , _4 , _5 , _6 , _7 , _8 , _9 , _10 , _11 , _12 , _13 , _14 , _15 , _16 , _17 , _18 , _19 , _20 , _21 , \
222+ _22 , _23 , _24 , _25 , _26 , _27 , _28 , _29 , _30 , _31 , _32 , _33 , _34 , _35 , _36 , _37 , _38 , _39 , _40 , \
223+ _41 , _42 , _43 , _44 , _45 , _46 , _47 , _48 , _49 , _50 , _51 , _52 , _53 , _54 , _55 , _56 , _57 , _58 , _59 , \
224+ _60 , _61 , _62 , _63 , _64 , N , ...) \
225+ N
226+
227+ //=============================================================================
228+ // TYPE ENUMERATION EXPANSION MACROS
229+ //=============================================================================
230+
231+ /**
232+ * Expand arguments to type, value pairs
233+ * For each argument, generate: PTK_BUF_TYPE_OF(arg), arg
234+ */
235+
236+ // 1 argument
237+ #define PTK_BUF_EXPAND_1 (a ) PTK_BUF_TYPE_OF(a), (a)
238+
239+ // 2 arguments
240+ #define PTK_BUF_EXPAND_2 (a , b ) PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b)
241+
242+ // 3 arguments
243+ #define PTK_BUF_EXPAND_3 (a , b , c ) PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c)
244+
245+ // 4 arguments
246+ #define PTK_BUF_EXPAND_4 (a , b , c , d ) \
247+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d)
248+
249+ // 5 arguments
250+ #define PTK_BUF_EXPAND_5 (a , b , c , d , e ) \
251+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d), PTK_BUF_TYPE_OF(e), (e)
252+
253+ // 6 arguments (EIP header size)
254+ #define PTK_BUF_EXPAND_6 (a , b , c , d , e , f ) \
255+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d), PTK_BUF_TYPE_OF(e), (e), \
256+ PTK_BUF_TYPE_OF(f), (f)
257+
258+ // 7 arguments
259+ #define PTK_BUF_EXPAND_7 (a , b , c , d , e , f , g ) \
260+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d), PTK_BUF_TYPE_OF(e), (e), \
261+ PTK_BUF_TYPE_OF(f), (f), PTK_BUF_TYPE_OF(g), (g)
262+
263+ // 8 arguments
264+ #define PTK_BUF_EXPAND_8 (a , b , c , d , e , f , g , h ) \
265+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d), PTK_BUF_TYPE_OF(e), (e), \
266+ PTK_BUF_TYPE_OF(f), (f), PTK_BUF_TYPE_OF(g), (g), PTK_BUF_TYPE_OF(h), (h)
267+
268+ // 10 arguments
269+ #define PTK_BUF_EXPAND_10 (a , b , c , d , e , f , g , h , i , j ) \
270+ PTK_BUF_TYPE_OF(a), (a), PTK_BUF_TYPE_OF(b), (b), PTK_BUF_TYPE_OF(c), (c), PTK_BUF_TYPE_OF(d), (d), PTK_BUF_TYPE_OF(e), (e), \
271+ PTK_BUF_TYPE_OF(f), (f), PTK_BUF_TYPE_OF(g), (g), PTK_BUF_TYPE_OF(h), (h), PTK_BUF_TYPE_OF(i), (i), PTK_BUF_TYPE_OF(j), \
272+ (j)
273+
274+ // Add more as needed up to 32 arguments...
275+
276+ /**
277+ * Select appropriate expansion macro based on argument count
278+ */
279+ #define PTK_BUF_EXPAND_SELECT (N ) PTK_BUF_EXPAND_##N
280+ #define PTK_BUF_EXPAND_DISPATCH (N ) PTK_BUF_EXPAND_SELECT(N)
281+ #define PTK_BUF_EXPAND (...) PTK_BUF_EXPAND_DISPATCH(PTK_BUF_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
282+
283+ //=============================================================================
284+ // POINTER TYPE ENUMERATION FOR DESERIALIZATION
285+ //=============================================================================
286+
287+ /**
288+ * Expand pointer arguments to type, pointer pairs
289+ * For each pointer argument, generate: PTK_BUF_TYPE_OF_PTR(ptr), ptr
290+ */
291+
292+ // 1 pointer
293+ #define PTK_BUF_EXPAND_PTR_1 (a ) PTK_BUF_TYPE_OF_PTR(a), (a)
294+
295+ // 2 pointers
296+ #define PTK_BUF_EXPAND_PTR_2 (a , b ) PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b)
297+
298+ // 3 pointers
299+ #define PTK_BUF_EXPAND_PTR_3 (a , b , c ) PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c)
300+
301+ // 4 pointers
302+ #define PTK_BUF_EXPAND_PTR_4 (a , b , c , d ) \
303+ PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c), PTK_BUF_TYPE_OF_PTR(d), (d)
304+
305+ // 5 pointers
306+ #define PTK_BUF_EXPAND_PTR_5 (a , b , c , d , e ) \
307+ PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c), PTK_BUF_TYPE_OF_PTR(d), (d), \
308+ PTK_BUF_TYPE_OF_PTR(e), (e)
309+
310+ // 6 pointers (EIP header size)
311+ #define PTK_BUF_EXPAND_PTR_6 (a , b , c , d , e , f ) \
312+ PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c), PTK_BUF_TYPE_OF_PTR(d), (d), \
313+ PTK_BUF_TYPE_OF_PTR(e), (e), PTK_BUF_TYPE_OF_PTR(f), (f)
314+
315+ // 7 pointers
316+ #define PTK_BUF_EXPAND_PTR_7 (a , b , c , d , e , f , g ) \
317+ PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c), PTK_BUF_TYPE_OF_PTR(d), (d), \
318+ PTK_BUF_TYPE_OF_PTR(e), (e), PTK_BUF_TYPE_OF_PTR(f), (f), PTK_BUF_TYPE_OF_PTR(g), (g)
319+
320+ // 8 pointers
321+ #define PTK_BUF_EXPAND_PTR_8 (a , b , c , d , e , f , g , h ) \
322+ PTK_BUF_TYPE_OF_PTR(a), (a), PTK_BUF_TYPE_OF_PTR(b), (b), PTK_BUF_TYPE_OF_PTR(c), (c), PTK_BUF_TYPE_OF_PTR(d), (d), \
323+ PTK_BUF_TYPE_OF_PTR(e), (e), PTK_BUF_TYPE_OF_PTR(f), (f), PTK_BUF_TYPE_OF_PTR(g), (g), PTK_BUF_TYPE_OF_PTR(h), (h)
324+
325+ // Add more as needed...
326+
327+ /**
328+ * Select appropriate pointer expansion macro
329+ */
330+ #define PTK_BUF_EXPAND_PTR_SELECT (N ) PTK_BUF_EXPAND_PTR_##N
331+ #define PTK_BUF_EXPAND_PTR_DISPATCH (N ) PTK_BUF_EXPAND_PTR_SELECT(N)
332+ #define PTK_BUF_EXPAND_PTR (...) PTK_BUF_EXPAND_PTR_DISPATCH(PTK_BUF_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
333+
334+ //=============================================================================
335+ // USER-FACING MACROS
336+ //=============================================================================
337+
338+ /**
339+ * Serialize variables to buffer with automatic type detection and counting
340+ *
341+ * Usage: ptk_buf_serialize(buffer, PTK_BUF_LITTLE_ENDIAN, var1, var2, var3, ...)
342+ */
343+ #define ptk_buf_serialize (buf , endian , ...) \
344+ ptk_buf_serialize_impl((buf), (endian), PTK_BUF_ARG_COUNT(__VA_ARGS__), PTK_BUF_EXPAND(__VA_ARGS__))
345+
346+ /**
347+ * Deserialize from buffer to variables with automatic type detection and counting
348+ *
349+ * Usage: ptk_buf_deserialize(buffer, false, PTK_BUF_LITTLE_ENDIAN, &var1, &var2, &var3, ...)
350+ */
351+ #define ptk_buf_deserialize (buf , peek , endian , ...) \
352+ ptk_buf_deserialize_impl((buf), (peek), (endian), PTK_BUF_ARG_COUNT(__VA_ARGS__), PTK_BUF_EXPAND_PTR(__VA_ARGS__))
353+
354+
106355#ifdef __cplusplus
107356}
108357#endif
0 commit comments