DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
hex.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 hex.h
6 * @brief Tiny no-stdlib hex encode / decode / nibble helpers (one shared copy).
7 *
8 * Hex was open-coded in ~10 places (CSRF token, WebDAV %XX, provisioning, audit-log
9 * hash, device-id, HTTP auth, OAuth2 percent-encode). These header-only inline
10 * helpers are the single home for it, mirroring numparse.h - no `<stdlib.h>`,
11 * no heap, and zero link cost when unused.
12 *
13 * @author Douglas Quigg (dstroy0)
14 * @date 2026
15 */
16
17#ifndef DETERMINISTICESPASYNCWEBSERVER_DET_HEX_H
18#define DETERMINISTICESPASYNCWEBSERVER_DET_HEX_H
19
20#include <stddef.h>
21#include <stdint.h>
22
23/** @brief Nibble 0..15 -> hex char (lowercase, or uppercase when @p upper). */
24inline char det_hex_digit(int nibble, bool upper = false)
25{
26 const char *H = upper ? "0123456789ABCDEF" : "0123456789abcdef";
27 return H[nibble & 0xF];
28}
29
30/** @brief Hex digit -> 0..15, or -1 if @p c is not a hex digit (either case). */
31inline int det_hex_val(char c)
32{
33 if (c >= '0' && c <= '9')
34 return c - '0';
35 if (c >= 'a' && c <= 'f')
36 return c - 'a' + 10;
37 if (c >= 'A' && c <= 'F')
38 return c - 'A' + 10;
39 return -1;
40}
41
42/**
43 * @brief Encode @p n bytes as 2*n hex chars + NUL into @p out (needs cap >= 2*n+1).
44 * @param upper uppercase A-F when true, else lowercase a-f.
45 */
46inline void det_hex_encode(const uint8_t *in, size_t n, char *out, bool upper = false)
47{
48 const char *H = upper ? "0123456789ABCDEF" : "0123456789abcdef";
49 for (size_t i = 0; i < n; i++)
50 {
51 out[2 * i] = H[(in[i] >> 4) & 0xF];
52 out[2 * i + 1] = H[in[i] & 0xF];
53 }
54 out[2 * n] = '\0';
55}
56
57/**
58 * @brief Decode exactly @p hexlen hex chars into @p out (hexlen/2 bytes).
59 * @return byte count, or -1 on odd length / overflow (> @p out_cap) / non-hex input.
60 */
61inline int det_hex_decode(const char *in, size_t hexlen, uint8_t *out, size_t out_cap)
62{
63 if ((hexlen % 2) != 0 || (hexlen / 2) > out_cap)
64 return -1;
65 for (size_t i = 0; i < hexlen; i += 2)
66 {
67 int hi = det_hex_val(in[i]);
68 int lo = det_hex_val(in[i + 1]);
69 if (hi < 0 || lo < 0)
70 return -1;
71 out[i / 2] = (uint8_t)((hi << 4) | lo);
72 }
73 return (int)(hexlen / 2);
74}
75
76#endif // DETERMINISTICESPASYNCWEBSERVER_DET_HEX_H
char det_hex_digit(int nibble, bool upper=false)
Nibble 0..15 -> hex char (lowercase, or uppercase when upper).
Definition hex.h:24
int det_hex_decode(const char *in, size_t hexlen, uint8_t *out, size_t out_cap)
Decode exactly hexlen hex chars into out (hexlen/2 bytes).
Definition hex.h:61
int det_hex_val(char c)
Hex digit -> 0..15, or -1 if c is not a hex digit (either case).
Definition hex.h:31
void det_hex_encode(const uint8_t *in, size_t n, char *out, bool upper=false)
Encode n bytes as 2*n hex chars + NUL into out (needs cap >= 2*n+1).
Definition hex.h:46