From 4a2228bb7638bfa85bfd7dc51746fa0a067140ff Mon Sep 17 00:00:00 2001
From: Alex <84599917+GyverLibs@users.noreply.github.com>
Date: Tue, 15 Feb 2022 15:37:06 +0300
Subject: [PATCH] upd
---
README.md | 38 +++++++++-
examples/testUtils/testUtils.ino | 83 ++++++++++++++++++++++
keywords.txt | 10 +++
library.properties | 2 +-
src/GParser.h | 6 +-
src/parseUtils.cpp | 118 +++++++++++++++++++++++++++++++
src/parseUtils.h | 47 ++++++++++++
7 files changed, 299 insertions(+), 5 deletions(-)
create mode 100644 examples/testUtils/testUtils.ino
create mode 100644 src/parseUtils.cpp
create mode 100644 src/parseUtils.h
diff --git a/README.md b/README.md
index fa3971a..f1499a4 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Foo](https://img.shields.io/badge/Version-1.0-brightgreen.svg?style=flat-square)](#versions)
+[![Foo](https://img.shields.io/badge/Version-1.1-brightgreen.svg?style=flat-square)](#versions)
[![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/)
[![Foo](https://img.shields.io/badge/%E2%82%BD$%E2%82%AC%20%D0%9D%D0%B0%20%D0%BF%D0%B8%D0%B2%D0%BE-%D1%81%20%D1%80%D1%8B%D0%B1%D0%BA%D0%BE%D0%B9-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/)
@@ -44,6 +44,7 @@ GParser (char* data, char newDiv = ',');
## Использование
+### Класс GParser
```cpp
void setDiv(char newDiv); // указать символ разделитель
void clear(); // освободить буфер
@@ -56,6 +57,38 @@ int parseInts(int* data); // распарсить на инты
int parseBytes(byte* data); // распарсить на байты
```
+### Отдельные функции парсинга
+См. пример **testUtils**
+
+```cpp
+// разделить список list с разделителем div на подстроки (см. пример)
+char* GP_splitList(char* list, char div = ',');
+
+// получить номер, под которым name входит в list с разделителем div. -1 если не входит
+int8_t GP_inList(char* name, char* list, char div = ',');
+
+// преобразовать int в строку (работает в 3-10 раз быстрее ltoa + основание)
+void GP_numToChar(int32_t n, char* buf, uint8_t base);
+
+// преобразовать float в строку
+void GP_floatToChar(double f, char *buf, uint8_t decimals);
+
+// преобразовать строку в число
+int32_t GP_charToNum(char* buf, uint8_t base);
+
+// преобразовать строку в float
+double GP_charToFloat(char* buf);
+
+// получить число под индексом idx в списке list с разделителем div
+int GP_numFromList(char* list, int idx, char div = ',');
+
+// переписать список list с разделителем div в массив чисел data размером size
+uint8_t GP_listToNum(char* list, int* data, uint8_t size, char div = ',');
+
+// преобразовать текстовый цвет (0x, #) в число
+uint32_t GP_decodeColor(char* hex);
+```
+
## Пример
Остальные примеры смотри в **examples**!
@@ -118,8 +151,9 @@ void loop() {
## Версии
- v1.0
+- v1.1 - добавлены отдельные инструменты для парсинга
## Баги и обратная связь
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
-Библиотека открыта для доработки и ваших **Pull Request**'ов!
+Библиотека открыта для доработки и ваших **Pull Request**'ов!
\ No newline at end of file
diff --git a/examples/testUtils/testUtils.ino b/examples/testUtils/testUtils.ino
new file mode 100644
index 0000000..eca0bdc
--- /dev/null
+++ b/examples/testUtils/testUtils.ino
@@ -0,0 +1,83 @@
+// тест утилит для парсинга
+#include
+
+void setup() {
+ Serial.begin(9600);
+
+ // список. Данные разделены запятой
+ char list[] = "123,456,789,abc,def";
+
+ // =====================
+ Serial.println("Split test");
+ char* p = list;
+ GP_splitList(NULL);
+ while ((p = GP_splitList(list)) != NULL) {
+ Serial.println(p);
+ }
+ Serial.println();
+
+ // =====================
+ Serial.println("InList test");
+ Serial.println(GP_inList("abc", list));
+ Serial.println(GP_inList("kek", list));
+ Serial.println();
+
+ // =====================
+ Serial.println("Num list test");
+ Serial.println(GP_numFromList(list, 2));
+ Serial.println();
+
+ // =====================
+ Serial.println("Array list test");
+ int data[3];
+ GP_listToNum(list, data, 3);
+ for (int i = 0; i < 3; i++) {
+ Serial.print(data[i]);
+ Serial.print(',');
+ }
+ Serial.println();
+ Serial.println();
+
+ // =====================
+ Serial.println("Num to char test");
+ char st[30];
+
+ GP_numToChar(0x123abc, st, HEX);
+ Serial.println(st);
+
+ GP_numToChar(123456, st, DEC);
+ Serial.println(st);
+
+ GP_numToChar(0b11100011, st, BIN);
+ Serial.println(st);
+
+ GP_floatToChar(3.1415, st, 3);
+ Serial.println(st);
+ Serial.println();
+
+ // =====================
+ Serial.println("Char to num test");
+ int32_t val;
+
+ val = GP_charToNum("AAFF", HEX);
+ Serial.println(val, HEX);
+
+ val = GP_charToNum("123456", DEC);
+ Serial.println(val, DEC);
+
+ val = GP_charToNum("11000011", BIN);
+ Serial.println(val, BIN);
+
+ float valf = GP_charToFloat("3.14");
+ Serial.println(valf);
+ Serial.println();
+
+ // =====================
+ Serial.println("Color test");
+ Serial.println(GP_decodeColor("0xFF22"), HEX);
+ Serial.println(GP_decodeColor("#FF22"), HEX);
+ Serial.println(GP_decodeColor("FF22"), HEX);
+}
+
+void loop() {
+}
diff --git a/keywords.txt b/keywords.txt
index 0ba220a..8fe1357 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -24,6 +24,16 @@ parseBytes KEYWORD2
buf KEYWORD2
str KEYWORD2
+GP_splitList KEYWORD2
+GP_inList KEYWORD2
+GP_numToChar KEYWORD2
+GP_floatToChar KEYWORD2
+GP_charToNum KEYWORD2
+GP_charToFloat KEYWORD2
+GP_numFromList KEYWORD2
+GP_listToNum KEYWORD2
+GP_decodeColor KEYWORD2
+
#######################################
# Constants (LITERAL1)
#######################################
\ No newline at end of file
diff --git a/library.properties b/library.properties
index c84578b..952c678 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=GParser
-version=1.0
+version=1.1
author=AlexGyver
maintainer=AlexGyver
sentence=Fast library for parsing cstring into substrings
diff --git a/src/GParser.h b/src/GParser.h
index cec4cfd..e857dc0 100644
--- a/src/GParser.h
+++ b/src/GParser.h
@@ -15,10 +15,12 @@
Версии:
v1.0 - релиз
+ v1.1 - добавлены отдельные инструменты для парсинга
*/
-#ifndef GParser_h
-#define GParser_h
+#ifndef _GParser_h
+#define _GParser_h
+#include "parseUtils.h"
class GParser {
public:
diff --git a/src/parseUtils.cpp b/src/parseUtils.cpp
new file mode 100644
index 0000000..6b4a9b8
--- /dev/null
+++ b/src/parseUtils.cpp
@@ -0,0 +1,118 @@
+#include "parseUtils.h"
+
+// разделить список list с разделителем div на подстроки
+char* GP_splitList(char* list, char div) {
+ static uint8_t prev, end;
+ if (list == NULL) prev = end = 0;
+ else {
+ if (prev) *(list + prev - 1) = div;
+ char* cur = strchr(list + prev, div);
+ if (cur) {
+ *cur = '\0';
+ uint8_t b = prev;
+ prev = cur - list + 1;
+ return list + b;
+ } else if (!end) {
+ end = 1;
+ return list + prev;
+ }
+ }
+ return NULL;
+}
+
+// получить номер, под которым name входит в list с разделителем div
+int8_t GP_inList(char* name, char* list, char div) {
+ char* str = list;
+ int8_t count = 0, pos = -1;
+ GP_splitList(NULL);
+ while ((str = GP_splitList(list, div)) != NULL) {
+ if (!strcmp(str, name)) pos = count;
+ count++;
+ }
+ return pos;
+}
+
+// преобразовать int в строку
+// DEC - 46, HEX/BIN - 17 (ltoa: BIN - 480, HEX - 125, DEC - 150)
+void GP_numToChar(int32_t n, char* buf, uint8_t base) {
+ uint8_t l = 2;
+ if (base != DEC) {
+ int32_t nn = n;
+ uint8_t b = (base == HEX) ? 4 : 1;
+ while (nn >>= b) l++;
+ char *str = &buf[l];
+ *--str = '\0';
+ do {
+ char c = n & (base - 1);
+ n >>= b;
+ *--str = (c < 10) ? (c + '0') : (c + 'A' - 10);
+ } while(n);
+ } else {
+ uint8_t s = 0;
+ if (n < 0) n = -n, s = 1;
+ int32_t nn = n;
+ while (nn /= base) l++;
+ char *str = &buf[l + s];
+ *--str = '\0';
+ do {
+ _GP_div10 res(n);
+ n = res.quot;
+ *--str = (res.rem < 10) ? (res.rem + '0') : (res.rem + 'A' - 10);
+ } while(n);
+ if (s) *--str = '-';
+ }
+}
+
+// преобразовать float в строку
+void GP_floatToChar(double f, char *buf, uint8_t decimals) {
+ dtostrf(f, decimals + 2, decimals, buf);
+}
+
+// преобразовать строку в число
+int32_t GP_charToNum(char* buf, uint8_t base) {
+ if (base == DEC) return atol(buf);
+ else return strtol(buf, NULL, base);
+}
+
+// преобразовать строку в float
+double GP_charToFloat(char* buf) {
+ return atof(buf);
+}
+
+// получить число под индексом idx в списке list с разделителем div
+int GP_numFromList(char* list, int idx, char div) {
+ uint8_t count = 0;
+ char* p = list;
+ while (1) {
+ if (count++ == idx) return atoi(p);
+ p = strchr(p, div);
+ if (!p++) break;
+ }
+ return 0;
+}
+
+// переписать список list с разделителем div в массив чисел data размером size
+uint8_t GP_listToNum(char* list, int* data, uint8_t size, char div) {
+ uint8_t count = 0;
+ char* offset = list;
+ while (1) {
+ if (count >= size) break;
+ data[count++] = atoi(offset);
+ offset = strchr(offset, div);
+ if (!offset++) break;
+ }
+ return count;
+}
+
+// преобразовать текстовый цвет (0x, #) в число
+uint32_t GP_decodeColor(char* hex) {
+ uint32_t val = 0;
+ uint8_t i = (hex[0] == '#') ? 1 : ((hex[1] == 'x') ? 2 : 0);
+ for (; i < strlen(hex); i++) {
+ val <<= 4;
+ uint8_t d = hex[i];
+ d -= (d <= '9') ? 48 : ((d <= 'F') ? 55 : 87);
+ val |= d;
+ }
+ return val;
+}
diff --git a/src/parseUtils.h b/src/parseUtils.h
new file mode 100644
index 0000000..c1e3733
--- /dev/null
+++ b/src/parseUtils.h
@@ -0,0 +1,47 @@
+#pragma once
+#include
+
+// разделить список list с разделителем div на подстроки (см. пример)
+char* GP_splitList(char* list, char div = ',');
+
+// получить номер, под которым name входит в list с разделителем div. -1 если не входит
+int8_t GP_inList(char* name, char* list, char div = ',');
+
+// преобразовать int в строку
+void GP_numToChar(int32_t n, char* buf, uint8_t base);
+
+// преобразовать float в строку
+void GP_floatToChar(double f, char *buf, uint8_t decimals);
+
+// преобразовать строку в число
+int32_t GP_charToNum(char* buf, uint8_t base);
+
+// преобразовать строку в float
+double GP_charToFloat(char* buf);
+
+// получить число под индексом idx в списке list с разделителем div
+int GP_numFromList(char* list, int idx, char div = ',');
+
+// переписать список list с разделителем div в массив чисел data размером size
+uint8_t GP_listToNum(char* list, int* data, uint8_t size, char div = ',');
+
+// преобразовать текстовый цвет (0x, #) в число
+uint32_t GP_decodeColor(char* hex);
+
+
+// http://we.easyelectronics.ru/Soft/preobrazuem-v-stroku-chast-1-celye-chisla.html
+struct _GP_div10 {
+ _GP_div10(uint32_t n) {
+ quot = n >> 1;
+ quot += quot >> 1;
+ quot += quot >> 4;
+ quot += quot >> 8;
+ quot += quot >> 16;
+ uint32_t qq = quot;
+ quot >>= 3;
+ rem = uint8_t(n - ((quot << 1) + (qq & ~7ul)));
+ if (rem > 9) rem -= 10, quot++;
+ }
+ uint32_t quot;
+ uint8_t rem;
+};
\ No newline at end of file