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