muwerk mupplet Core Library
muwerk applets; mupplets: functional units that support specific hardware or reusable applications
Loading...
Searching...
No Matches
mupplet_core.h
1// mupplet_core.h - muwerk mupplet core library
2
3#pragma once
4
46#include "scheduler.h"
47
49namespace ustd {
50
51int8_t parseBoolean(String arg) {
63 arg.trim();
64 arg.toLowerCase();
65 if (arg == "on" || arg == "true") {
66 return 1;
67 } else if (arg == "0" || arg == "off" || arg == "false") {
68 return 0;
69 } else if (atoi(arg.c_str())) {
70 return 1;
71 } else {
72 return -1;
73 }
74}
75
76int16_t parseToken(String arg, const char **tokenList, int16_t defaultVal = -1) {
91 arg.trim();
92 arg.toLowerCase();
93 for (const char **pToken = tokenList; *pToken; pToken++) {
94 if (!strcmp(arg.c_str(), *pToken)) {
95 return pToken - tokenList;
96 }
97 }
98 return defaultVal;
99}
100
101long parseLong(String arg, long defaultVal) {
111 arg.trim();
112 if (arg.length() == 0) {
113 return defaultVal;
114 }
115 for (const char *pPtr = arg.c_str(); *pPtr; pPtr++) {
116 if (*pPtr < '0' || *pPtr > '9') {
117 if (pPtr == arg.c_str() && *pPtr != '-') {
118 return defaultVal;
119 }
120 }
121 }
122 return atol(arg.c_str());
123}
124
125long parseRangedLong(String arg, long minVal, long maxVal, long minDefaultVal, long maxDefaultVal) {
141 long val = parseLong(arg, minDefaultVal);
142 if (val == minDefaultVal) {
143 // maybe not a number?
144 return minDefaultVal;
145 } else if (val < minVal) {
146 return minDefaultVal;
147 } else if (val > maxVal) {
148 return maxDefaultVal;
149 } else {
150 return val;
151 }
152}
153
154double parseUnitLevel(String arg) {
164 double val = 0.0;
165 arg.trim();
166 arg.toLowerCase();
167
168 if (arg == "on" || arg == "true") {
169 return 1.0;
170 } else if (arg == "off" || arg == "false") {
171 return 0.0;
172 } else if (arg == "pct") {
173 arg = shift(arg);
174 val = atoi(arg.c_str()) / 100.0;
175 } else if (arg.endsWith("%")) {
176 arg.remove(arg.length() - 1);
177 val = atoi(arg.c_str()) / 100.0;
178 } else if (arg.indexOf('.') == -1) {
179 val = atoi(arg.c_str()) / 100.0;
180 } else {
181 val = atof(arg.c_str());
182 }
183 return val < 0.0 ? 0.0 : val > 1.0 ? 1.0
184 : val;
185}
186
187uint16_t countChars(String txt, char c) {
189 uint16_t n = 0;
190 for (uint16_t i = 0; i < txt.length(); i++) {
191 if (txt[i] == c) ++n;
192 }
193 return n;
194}
195
196bool getNthHexbyte(String hex, uint8_t ind, uint8_t *pVal) {
197 if (hex.length() < (uint16_t)((ind + 1) * 2)) return false;
198 if (pVal) {
199 *pVal = (uint8_t)strtol(hex.substring(ind * 2, ind * 2 + 2).c_str(), 0, 16);
200 return true;
201 } else
202 return false;
203}
204
205bool getNthInt(String arg, uint8_t ind, uint8_t *pVal) {
206 if (countChars(arg, ',') < ind) return false;
207 uint8_t i = 0, n = 0, p1 = 0, p2 = 0;
208 String carg = "," + arg + ",";
209 while (true) {
210 if (carg[i] == ',') {
211 if (n == ind + 1) {
212 p2 = i;
213 if (pVal) {
214 *pVal = strtol(carg.substring(p1, p2).c_str(), 0, 10);
215 return true;
216 } else
217 return false;
218 } else if (n == ind) {
219 p1 = i + 1;
220 }
221 ++n;
222 }
223 ++i;
224 if (i == carg.length()) return false;
225 }
226}
227
228bool parseColor(String arg, uint8_t *pr, uint8_t *pg, uint8_t *pb, uint8_t *pw = nullptr, uint8_t *pww = nullptr) {
248 String hex;
249 if (arg.startsWith("#")) {
250 hex = arg.substring(1);
251 } else if (arg.startsWith("0x")) {
252 hex = arg.substring(2);
253 } else if (arg.indexOf(',') != -1) {
254 uint16_t n = countChars(arg, ',');
255 if (n == 2) { // RGB
256 if (pr)
257 if (!getNthInt(arg, 0, pr)) return false;
258 if (pg)
259 if (!getNthInt(arg, 1, pg)) return false;
260 if (pb)
261 if (!getNthInt(arg, 2, pb)) return false;
262 } else if (n == 3) { // RGBW
263 if (pw)
264 if (!getNthInt(arg, 0, pw)) return false;
265 if (pr)
266 if (!getNthInt(arg, 1, pr)) return false;
267 if (pg)
268 if (!getNthInt(arg, 2, pg)) return false;
269 if (pb)
270 if (!getNthInt(arg, 3, pb)) return false;
271 } else if (n == 4) { // RGBWW
272 if (pww)
273 if (!getNthInt(arg, 0, pww)) return false;
274 if (pw)
275 if (!getNthInt(arg, 1, pw)) return false;
276 if (pr)
277 if (!getNthInt(arg, 2, pr)) return false;
278 if (pg)
279 if (!getNthInt(arg, 3, pg)) return false;
280 if (pb)
281 if (!getNthInt(arg, 4, pb)) return false;
282 } else
283 return false;
284 return true;
285 }
286 if (hex.length() == 6) {
287 if (pr)
288 if (!getNthHexbyte(hex, 0, pr)) return false;
289 if (pg)
290 if (!getNthHexbyte(hex, 1, pg)) return false;
291 if (pb)
292 if (!getNthHexbyte(hex, 2, pb)) return false;
293 } else if (hex.length() == 8) {
294 if (pw)
295 if (!getNthHexbyte(hex, 0, pw)) return false;
296 if (pr)
297 if (!getNthHexbyte(hex, 1, pr)) return false;
298 if (pg)
299 if (!getNthHexbyte(hex, 2, pg)) return false;
300 if (pb)
301 if (!getNthHexbyte(hex, 3, pb)) return false;
302 } else if (hex.length() == 10) {
303 if (pww)
304 if (!getNthHexbyte(hex, 0, pww)) return false;
305 if (pw)
306 if (!getNthHexbyte(hex, 1, pw)) return false;
307 if (pr)
308 if (!getNthHexbyte(hex, 2, pr)) return false;
309 if (pg)
310 if (!getNthHexbyte(hex, 3, pg)) return false;
311 if (pb)
312 if (!getNthHexbyte(hex, 4, pb)) return false;
313 } else
314 return false;
315 return true;
316}
317
318// clang-format off
335// clang-format on
336
337bool isAscii(String utf8string) {
343 for (unsigned int i = 0; i < utf8string.length(); i++) {
344 unsigned char c = utf8string[i];
345 if ((c & 0x80) != 0)
346 return false;
347 }
348 return true;
349}
350
351bool isNumber(String string, bool integer = false) {
359 return isNumber(string.c_str(), integer);
360}
361
362bool isNumber(const char *value, bool integer = false) {
370 if (!value) {
371 return false;
372 }
373 if (*value == '-') {
374 value++;
375 }
376 bool decimalpoint = false;
377 while (*value) {
378 if (*value < '0' || *value > '9') {
379 if (integer || decimalpoint || *value != '.') {
380 return false;
381 } else {
382 decimalpoint = true;
383 }
384 }
385 value++;
386 }
387 return true;
388}
389
390String utf8ToLatin(String utf8string, char invalid_char = '_') {
407 String latin = "";
408 unsigned char c, nc;
409 for (unsigned int i = 0; i < utf8string.length(); i++) {
410 c = utf8string[i];
411 if ((c & 0x80) == 0) { // 1 byte utf8
412 latin += (char)c;
413 continue;
414 } else {
415 if ((c & 0b11100000) == 0b11000000) { // 2 byte utf8
416 if (i < utf8string.length() - 1) {
417 nc = utf8string[i + 1];
418 switch (c) {
419 case 0xc2:
420 latin += (char)nc;
421 break;
422 case 0xc3:
423 nc += 0x40;
424 latin += (char)nc;
425 break;
426 default:
427 latin += (char)invalid_char;
428 break;
429 }
430 i += 1;
431 continue;
432 } else { // damaged utf8
433 latin += (char)invalid_char;
434 return latin;
435 }
436 } else {
437 if ((c & 0b11110000) == 0b11100000) { // 3 byte utf8
438 i += 2;
439 latin += (char)invalid_char;
440 continue;
441 } else {
442 if ((c & 0b11111000) == 0b11110000) { // 4 byte utf8
443 i += 3;
444 latin += (char)invalid_char;
445 continue;
446 } else { // damaged utf8
447 latin += (char)invalid_char;
448 return latin; // we can't continue parsing
449 }
450 }
451 }
452 }
453 }
454 return latin;
455}
456
457String latinToUtf8(String latin) {
465 String utf8str = "";
466 unsigned char c;
467 for (unsigned int i = 0; i < latin.length(); i++) {
468 c = latin[i];
469 if (c < 0x80)
470 utf8str += (char)c;
471 else {
472 if (c < 0xc0) {
473 utf8str += (char)0xc2;
474 utf8str += (char)c;
475 } else {
476 utf8str += (char)0xc3;
477 c -= 0x40;
478 utf8str += (char)c;
479 }
480 }
481 }
482 return utf8str;
483}
484
485/*
486const char *hdmap = "→←"
487 " 。「」、・ヲァィゥェォャュョッ"
488 "ーアイウエオカキクケコサシスセソ"
489 "タチツテトナニヌネノハヒフヘホマ"
490 "ミムメモヤユヨラリルレロワン゛゜"
491 "αäßεμσρg√⁻¹j˟₵₤ñö"
492 "pqΘ∞ΩüΣπx̅y不万円÷ █";
493*/
494class HD44780Charset {
495 public:
496 HD44780Charset(char *pLookupTable = nullptr) {
497 }
498
499 static String toHD_ASCII(String utf8string, char invalid_char = '_') {
517 String hdstr = "";
518 unsigned char c;
519 for (unsigned int i = 0; i < utf8string.length(); i++) {
520 c = utf8string[i];
521 Serial.println(c);
522 if ((c & 0x80) == 0) { // 1 byte utf8
523 if (c < 0x7e) { // and not 0x7e or 0x7f
524 if (strchr("gjpqy", c) != nullptr)
525 c += 0x80; // Use extended matrix for lowercase descenders.
526 hdstr += (char)c;
527 } else {
528 hdstr += (char)invalid_char;
529 }
530 continue;
531 } else {
532 if ((c & 0b11100000) == 0b11000000) { // 2 byte utf8
533 if (i < utf8string.length() - 1) {
534 hdstr += (char)invalid_char;
535 i += 1;
536 continue;
537 } else { // damaged utf8
538 hdstr += (char)invalid_char;
539 return hdstr;
540 }
541 } else {
542 if ((c & 0b11110000) == 0b11100000) { // 3 byte utf8
543 i += 2;
544 hdstr += (char)invalid_char;
545 continue;
546 } else {
547 if ((c & 0b11111000) == 0b11110000) { // 4 byte utf8
548 i += 3;
549 hdstr += (char)invalid_char;
550 continue;
551 } else { // damaged utf8
552 hdstr += (char)invalid_char;
553 return hdstr; // we can't continue parsing
554 }
555 }
556 }
557 }
558 }
559 return hdstr;
560 }
561
562 static String toUtf8(String hdstr, char invalid_char = '_') {
571 String utf8str = "";
572 unsigned char c;
573 for (unsigned int i = 0; i < hdstr.length(); i++) {
574 c = hdstr[i];
575 if (c < 0x7e)
576 utf8str += (char)c;
577 else {
578 char cf = (char)(c - 0x80);
579 if (strchr("gjpqy", cf) != nullptr)
580 utf8str += cf;
581 else
582 utf8str += (char)invalid_char;
583 }
584 }
585 return utf8str;
586 }
587};
588} // namespace ustd
The muwerk namespace.
Definition: home_assistant.h:10
long parseRangedLong(String arg, long minVal, long maxVal, long minDefaultVal, long maxDefaultVal)
Definition: mupplet_core.h:125
int8_t parseBoolean(String arg)
Definition: mupplet_core.h:51
long parseLong(String arg, long defaultVal)
Definition: mupplet_core.h:101
String utf8ToLatin(String utf8string, char invalid_char='_')
Definition: mupplet_core.h:390
double parseUnitLevel(String arg)
Definition: mupplet_core.h:154
String latinToUtf8(String latin)
Definition: mupplet_core.h:457
int16_t parseToken(String arg, const char **tokenList, int16_t defaultVal=-1)
Definition: mupplet_core.h:76
uint16_t countChars(String txt, char c)
Definition: mupplet_core.h:187
bool isAscii(String utf8string)
mupplet-core string encoding utilities
Definition: mupplet_core.h:337
bool parseColor(String arg, uint8_t *pr, uint8_t *pg, uint8_t *pb, uint8_t *pw=nullptr, uint8_t *pww=nullptr)
Definition: mupplet_core.h:228
bool isNumber(String string, bool integer=false)
Definition: mupplet_core.h:351