Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
d_string.h
1/*
2 * Copyright © 2019-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include <cctype>
22#include <cstdint>
23#include <cstring>
24
25extern "C" {
26#include "util/cfunctions.h"
27}
28
29[[gnu::always_inline]] static inline void intToString(int32_t number, char* buffer) {
30 intToString(number, buffer, 1);
31}
32
33bool memIsNumericChars(char const* mem, int32_t size);
34bool stringIsNumericChars(char const* str);
35
36char halfByteToHexChar(uint8_t thisHalfByte);
37void intToHex(uint32_t number, char* output, int32_t numChars = 8);
38uint32_t hexToInt(char const* string);
39uint32_t hexToIntFixedLength(char const* __restrict__ hexChars, int32_t length);
40
41void byteToHex(uint8_t number, char* buffer);
42uint8_t hexToByte(char const* firstChar);
43
44extern const char nothing;
45
46class String {
47public:
48 String() = default;
49 // String(String* otherString); // BEWARE - using this on stack instances sometimes just caused crashes and stuff.
50 // Made no sense. Instead, constructing then calling set() works
51 ~String();
52 void clear(bool destructing = false);
53 Error set(char const* newChars, int32_t newLength = -1);
54 void set(String const* otherString);
55 void beenCloned();
56 size_t getLength();
57 Error shorten(int32_t newLength);
58 Error concatenateAtPos(char const* newChars, int32_t pos, int32_t newCharsLength = -1);
59 Error concatenateInt(int32_t number, int32_t minNumDigits = 1);
60 Error setInt(int32_t number, int32_t minNumDigits = 1);
61 Error setChar(char newChar, int32_t pos);
62 Error concatenate(String* otherString);
63 Error concatenate(char const* newChars);
64 bool equals(char const* otherChars);
65 bool equalsCaseIrrespective(char const* otherChars);
66
67 inline bool contains(const char* otherChars) { return strstr(stringMemory, otherChars) != NULL; }
68 inline bool equals(String* otherString) {
69 if (stringMemory == otherString->stringMemory) {
70 return true; // Works if both lengths are 0, too
71 }
72 if (!stringMemory || !otherString->stringMemory) {
73 return false; // If just one is empty, then not equal
74 }
75 return equals(otherString->get());
76 }
77
78 inline bool equalsCaseIrrespective(String* otherString) {
79 if (stringMemory == otherString->stringMemory) {
80 return true; // Works if both lengths are 0, too
81 }
82 if (!stringMemory || !otherString->stringMemory) {
83 return false; // If just one is empty, then not equal
84 }
85 return equalsCaseIrrespective(otherString->get());
86 }
87
88 inline char const* get() {
89 if (!stringMemory) {
90 return &nothing;
91 }
92 return stringMemory;
93 }
94
95 inline bool isEmpty() { return !stringMemory; }
96
97private:
98 int32_t getNumReasons();
99 void setNumReasons(int32_t newNum);
100
101 char* stringMemory = nullptr;
102};
103
106class StringBuf {
107 // Not templated to optimize binary size.
108public:
109 StringBuf(char* buf, size_t capacity) : capacity_(capacity), buf_(buf) { memset(buf_, '\0', capacity_); }
110 // NOLINTBEGIN (*-suspicious-stringview-data-usage)
111#pragma GCC diagnostic push
112#pragma GCC diagnostic ignored "-Wstringop-overflow="
113 // this is fine, the second parameter in the min is the max we can safely copy and the first is to avoid using
114 // strcopy on a non null terminated string view
115 void append(std::string_view str) { ::strncat(buf_, str.data(), std::min(str.length(), capacity_ - size() - 1)); }
116#pragma GCC diagnostic pop
117 // NOLINTEND
118 void append(char c) { ::strncat(buf_, &c, 1); }
119 void removeSpaces() {
120 size_t removed = 0;
121 // upto size, not below it -- we want the null as well
122 for (size_t i = 0; i <= size(); i++) {
123 if (isspace(buf_[i])) {
124 removed++;
125 }
126 else {
127 buf_[i - removed] = buf_[i];
128 }
129 }
130 }
131 void clear() { buf_[0] = 0; }
132 void truncate(size_t newSize) {
133 if (newSize < capacity_) {
134 buf_[newSize] = '\0';
135 }
136 }
137
138 // TODO: Validate buffer size. These can overflow
139 void appendInt(int i, int minChars = 1) { intToString(i, buf_ + size(), minChars); }
140 void appendHex(int i, int minChars = 1) { intToHex(i, buf_ + size(), minChars); }
141 void appendFloat(float f, int32_t minDecimals, int32_t maxDecimals) {
142 floatToString(f, buf_ + size(), minDecimals, maxDecimals);
143 }
144
145 [[nodiscard]] char* data() { return buf_; }
146 [[nodiscard]] const char* data() const { return buf_; }
147 [[nodiscard]] const char* c_str() const { return buf_; }
148
149 [[nodiscard]] size_t capacity() const { return capacity_; }
150 [[nodiscard]] size_t size() const { return std::strlen(buf_); }
151 [[nodiscard]] size_t length() const { return std::strlen(buf_); }
152
153 [[nodiscard]] bool empty() const { return buf_[0] == '\0'; }
154
155 bool operator==(const char* rhs) const { return std::strcmp(buf_, rhs) == 0; }
156 bool operator==(const StringBuf& rhs) const { return std::strcmp(buf_, rhs.c_str()) == 0; }
157
158 operator std::string_view() const { return std::string_view{buf_}; }
159
160private:
161 size_t capacity_;
162 char* buf_;
163};
164
166#define DEF_STACK_STRING_BUF(name, capacity) \
167 char name##__buf[capacity] = {0}; \
168 StringBuf name = {name##__buf, capacity}