Skip to content

Commit

Permalink
upd
Browse files Browse the repository at this point in the history
  • Loading branch information
GyverLibs committed Feb 15, 2022
1 parent fdf3f63 commit 4a2228b
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 5 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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/)

Expand Down Expand Up @@ -44,6 +44,7 @@ GParser (char* data, char newDiv = ',');
<a id="usage"></a>
## Использование
### Класс GParser
```cpp
void setDiv(char newDiv); // указать символ разделитель
void clear(); // освободить буфер
Expand All @@ -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);
```
<a id="example"></a>
## Пример
Остальные примеры смотри в **examples**!
Expand Down Expand Up @@ -118,8 +151,9 @@ void loop() {
<a id="versions"></a>
## Версии
- v1.0
- v1.1 - добавлены отдельные инструменты для парсинга

<a id="feedback"></a>
## Баги и обратная связь
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
Библиотека открыта для доработки и ваших **Pull Request**'ов!
Библиотека открыта для доработки и ваших **Pull Request**'ов!
83 changes: 83 additions & 0 deletions examples/testUtils/testUtils.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// тест утилит для парсинга
#include <GParser.h>

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() {
}
10 changes: 10 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
#######################################
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=GParser
version=1.0
version=1.1
author=AlexGyver <alex@alexgyver.ru>
maintainer=AlexGyver <alex@alexgyver.ru>
sentence=Fast library for parsing cstring into substrings
Expand Down
6 changes: 4 additions & 2 deletions src/GParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
118 changes: 118 additions & 0 deletions src/parseUtils.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
47 changes: 47 additions & 0 deletions src/parseUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once
#include <Arduino.h>

// разделить список 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;
};

0 comments on commit 4a2228b

Please sign in to comment.