cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
ota_version.h
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
23
24#ifndef OTA_VERSION_H
25#define OTA_VERSION_H
26
27#include <stdbool.h>
28#include <stddef.h>
29#include <stdio.h>
30
32#define OTA_VERSION_PARTS 4U
33
35#define OTA_VERSION_MAX 32U
36
48static inline void ota_version_parse(const char *s,
49 unsigned long out[OTA_VERSION_PARTS])
50{
51 for (size_t i = 0U; i < OTA_VERSION_PARTS; i++) { out[i] = 0UL; }
52 if (s == NULL) { return; }
53
54 size_t i = 0U;
55 if ((s[0] == 'v') || (s[0] == 'V')) { i = 1U; }
56
57 size_t part = 0U;
58 bool any = false; /* digits seen in the current component */
59 for (; (i < OTA_VERSION_MAX) && (s[i] != '\0'); i++) {
60 const char c = s[i];
61 if ((c >= '0') && (c <= '9')) {
62 /* Clamp rather than wrap: a component this large is junk, and
63 * "compares as very large" beats "compares as whatever the
64 * overflow happened to leave behind". */
65 if (out[part] < 100000000UL) {
66 out[part] = (out[part] * 10UL) + (unsigned long)(c - '0');
67 }
68 any = true;
69 } else if (c == '.') {
70 /* A dot with no digits before it ends the number entirely — ".."
71 * and a leading dot are malformed, not zero-valued components. */
72 if (!any) { break; }
73 part++;
74 any = false;
75 if (part >= OTA_VERSION_PARTS) { break; }
76 } else {
77 break; /* pre-release or build suffix: ignored */
78 }
79 }
80}
81
90static inline int ota_version_cmp(const char *a, const char *b)
91{
92 unsigned long va[OTA_VERSION_PARTS];
93 unsigned long vb[OTA_VERSION_PARTS];
94 ota_version_parse(a, va);
95 ota_version_parse(b, vb);
96
97 for (size_t i = 0U; i < OTA_VERSION_PARTS; i++) {
98 if (va[i] != vb[i]) { return (va[i] < vb[i]) ? -1 : 1; }
99 }
100 return 0;
101}
102
104#define OTA_VERSION_SHOWN_MAX (OTA_VERSION_MAX + 2U)
105
122static inline const char *ota_version_display(const char *v, char *buf, size_t n)
123{
124 if ((buf == NULL) || (n == 0U)) { return ""; }
125 if (v == NULL) { v = ""; }
126
127 const bool numeric = (v[0] >= '0') && (v[0] <= '9');
128 (void)snprintf(buf, n, "%s%s", numeric ? "v" : "", v);
129 return buf;
130}
131
132#endif /* OTA_VERSION_H */
static void ota_version_parse(const char *s, unsigned long out[OTA_VERSION_PARTS])
Read up to OTA_VERSION_PARTS dotted numbers out of s.
Definition ota_version.h:48
#define OTA_VERSION_MAX
Longest version string looked at, matching esp_app_desc_t::version.
Definition ota_version.h:35
static int ota_version_cmp(const char *a, const char *b)
Order two version strings.
Definition ota_version.h:90
#define OTA_VERSION_PARTS
Numeric components compared; the rest of the string is ignored.
Definition ota_version.h:32
static const char * ota_version_display(const char *v, char *buf, size_t n)
The display form of a version: 1.0.0 reads as v1.0.0 on screen.