ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
endian.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file endian.h
6 * @brief Fixed-width integer serializers into a raw @c uint8_t* buffer - one source of truth.
7 *
8 * Every binary codec (ADS, AMQP, C37.118, NetFlow, WAL, SHA-1/256, NTLMSSP/SMB2, ...) had its own
9 * byte-for-byte copy of these little-/big-endian pack/unpack helpers under a different local name
10 * (@c put16le / @c put16 / @c wr16 / @c store_be32 / @c put_u32 ...). They now live here once.
11 *
12 * Writers return the number of bytes written (2/4/8) so a caller can advance an offset; a caller that
13 * only needs the side effect simply ignores the return. Readers assume @p p has at least the width in
14 * range - callers bounds-check the buffer, as the hand-rolled copies did.
15 *
16 * Header-only and pure (only @c <stdint.h> / @c <stddef.h>) so it is host-testable and identical on
17 * device + host, and carries zero link cost when unused.
18 *
19 * @author Douglas Quigg (dstroy0)
20 * @date 2026
21 */
22
23#ifndef PROTOCORE_ENDIAN_H
24#define PROTOCORE_ENDIAN_H
25
26#include <stddef.h>
27#include <stdint.h>
28
29// --- little-endian ------------------------------------------------------------------------------
30
31/** @brief Write @p v little-endian at @p p. @return 2. */
32inline size_t pc_wr16le(uint8_t *p, uint16_t v)
33{
34 p[0] = (uint8_t)v;
35 p[1] = (uint8_t)(v >> 8);
36 return 2;
37}
38
39/** @brief Write @p v little-endian at @p p. @return 4. */
40inline size_t pc_wr32le(uint8_t *p, uint32_t v)
41{
42 p[0] = (uint8_t)v;
43 p[1] = (uint8_t)(v >> 8);
44 p[2] = (uint8_t)(v >> 16);
45 p[3] = (uint8_t)(v >> 24);
46 return 4;
47}
48
49/** @brief Write @p v little-endian at @p p. @return 8. */
50inline size_t pc_wr64le(uint8_t *p, uint64_t v)
51{
52 for (int i = 0; i < 8; i++)
53 {
54 p[i] = (uint8_t)(v >> (8 * i));
55 }
56 return 8;
57}
58
59/** @brief Read a little-endian u16 at @p p. */
60inline uint16_t pc_rd16le(const uint8_t *p)
61{
62 return (uint16_t)((uint16_t)p[0] | ((uint16_t)p[1] << 8));
63}
64
65/** @brief Read a little-endian u32 at @p p. */
66inline uint32_t pc_rd32le(const uint8_t *p)
67{
68 return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
69}
70
71/** @brief Read a little-endian u64 at @p p. */
72inline uint64_t pc_rd64le(const uint8_t *p)
73{
74 uint64_t v = 0;
75 for (int i = 0; i < 8; i++)
76 {
77 v |= (uint64_t)p[i] << (8 * i);
78 }
79 return v;
80}
81
82// --- big-endian (network order) -----------------------------------------------------------------
83
84/** @brief Write @p v big-endian at @p p. @return 2. */
85inline size_t pc_wr16be(uint8_t *p, uint16_t v)
86{
87 p[0] = (uint8_t)(v >> 8);
88 p[1] = (uint8_t)v;
89 return 2;
90}
91
92/** @brief Write @p v big-endian at @p p. @return 4. */
93inline size_t pc_wr32be(uint8_t *p, uint32_t v)
94{
95 p[0] = (uint8_t)(v >> 24);
96 p[1] = (uint8_t)(v >> 16);
97 p[2] = (uint8_t)(v >> 8);
98 p[3] = (uint8_t)v;
99 return 4;
100}
101
102/** @brief Write @p v big-endian at @p p. @return 8. */
103inline size_t pc_wr64be(uint8_t *p, uint64_t v)
104{
105 for (int i = 0; i < 8; i++)
106 {
107 p[i] = (uint8_t)(v >> (8 * (7 - i)));
108 }
109 return 8;
110}
111
112/** @brief Read a big-endian u16 at @p p. */
113inline uint16_t pc_rd16be(const uint8_t *p)
114{
115 return (uint16_t)(((uint16_t)p[0] << 8) | (uint16_t)p[1]);
116}
117
118/** @brief Read a big-endian u32 at @p p. */
119inline uint32_t pc_rd32be(const uint8_t *p)
120{
121 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
122}
123
124/** @brief Read a big-endian u64 at @p p. */
125inline uint64_t pc_rd64be(const uint8_t *p)
126{
127 uint64_t v = 0;
128 for (int i = 0; i < 8; i++)
129 {
130 v = (v << 8) | p[i];
131 }
132 return v;
133}
134
135#endif // PROTOCORE_ENDIAN_H
size_t pc_wr64be(uint8_t *p, uint64_t v)
Write v big-endian at p.
Definition endian.h:103
uint32_t pc_rd32be(const uint8_t *p)
Read a big-endian u32 at p.
Definition endian.h:119
size_t pc_wr64le(uint8_t *p, uint64_t v)
Write v little-endian at p.
Definition endian.h:50
uint64_t pc_rd64le(const uint8_t *p)
Read a little-endian u64 at p.
Definition endian.h:72
uint64_t pc_rd64be(const uint8_t *p)
Read a big-endian u64 at p.
Definition endian.h:125
uint32_t pc_rd32le(const uint8_t *p)
Read a little-endian u32 at p.
Definition endian.h:66
size_t pc_wr16be(uint8_t *p, uint16_t v)
Write v big-endian at p.
Definition endian.h:85
size_t pc_wr32le(uint8_t *p, uint32_t v)
Write v little-endian at p.
Definition endian.h:40
uint16_t pc_rd16le(const uint8_t *p)
Read a little-endian u16 at p.
Definition endian.h:60
uint16_t pc_rd16be(const uint8_t *p)
Read a big-endian u16 at p.
Definition endian.h:113
size_t pc_wr16le(uint8_t *p, uint16_t v)
Write v little-endian at p.
Definition endian.h:32
size_t pc_wr32be(uint8_t *p, uint32_t v)
Write v big-endian at p.
Definition endian.h:93