Skip to content

Commit 2033866

Browse files
committed
Parsing row by row (version 1.1.0)
1 parent 8f6024c commit 2033866

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed

CSV_Parser.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@ CSV_Parser::~CSV_Parser() {
109109
free(is_fmt_unsigned);
110110
}
111111

112+
// external function declaration for feeding characters to parser it must return a char
113+
extern char __attribute__((weak)) feedRowParser();
114+
char __attribute__((weak)) feedRowParser() { return '-'; }
115+
// external function declaration for checking if row parser finished parsing
116+
extern bool __attribute__((weak)) rowParserFinished();
117+
bool __attribute__((weak)) rowParserFinished() { return true; }
118+
// both functions above must be defined by the user, weak attribute is to avoid compilation
119+
// fail if the user doesn't define them
120+
121+
bool CSV_Parser::parseRow() {
122+
if (rowParserFinished())
123+
return false;
124+
rows_count = 0;
125+
while (!rowParserFinished() && rows_count == 0)
126+
*this << feedRowParser();
127+
// thanks to the line below the csv could end without '\n' and the last value
128+
// would still be parsed if the rowParserFinished() returns true
129+
if (rowParserFinished())
130+
parseLeftover();
131+
return rows_count > 0;
132+
}
133+
112134
#ifndef CSV_PARSER_DONT_IMPORT_SD
113135
bool CSV_Parser::readSDfile(const char *f_name) {
114136
// open the file. note that only one file can be open at a time,

CSV_Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ class CSV_Parser {
120120
#ifndef CSV_PARSER_DONT_IMPORT_SD
121121
bool readSDfile(const char *f_name);
122122
#endif
123+
124+
/** @brief Reads a single row provided by the user-defined functions: feedRowParser (returns char to be supplied) and rowParserFinished (returns whether all rows were parsed)
125+
@return true if row was parsed, false if not (e.g. if rowParserFinished() returned true)
126+
*/
127+
bool parseRow();
123128

124129
int getColumnsCount();
125130

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Headerless files
1212
* Custom delimiter
1313
* Custom quote character
14+
* Parsing row at a time
1415
* [Troubleshooting](#troubleshooting)
1516
* Checking if the file was parsed correctly
1617
* Platformio and SD library issue
@@ -289,6 +290,10 @@ Quote character is 5th parameter of the constructor. It's double quote (") by de
289290
CSV_Parser cp(csv_str, /*format*/ "sLdcfxs", /*has_header*/ true, /*delimiter*/ ',', /*quote_char*/ "'");
290291
```
291292

293+
### Parsing row at a time
294+
Large files often can't be stored in the limited memory of microcontrollers. For that reason it's possible to parse the file row by row.
295+
See the [parsing_row_by_row.ino](./examples/parsing_row_by_row/parsing_row_by_row.ino) example for more information. When deciding to parse row by row, it is suggested to not combine it with the default way of parsing. Please note that during row by row parsing the `cp.getRowsCount()` method will return 0 or 1 instead of the total number of previously parsed rows.
296+
292297

293298
## Troubleshooting
294299

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* parsing_row_by_row example for: https://github.com/michalmonday/CSV-Parser-for-Arduino
2+
3+
The user must define the following 2 functions/callbacks:
4+
- char feedRowParser()
5+
- bool rowParserFinished()
6+
7+
That is because cp.parseRow() calls these functions continuously "under the hood".
8+
9+
*/
10+
#include <CSV_Parser.h>
11+
/*
12+
This code prints:
13+
14+
Accessing values by column name:
15+
0. String = hello
16+
0. Number = 5
17+
18+
1. String = world
19+
1. Number = 10
20+
21+
22+
CSV_Parser content:
23+
rows_count = 0, cols_count = 2
24+
Header:
25+
my_strings | my_numbers
26+
Types:
27+
char* | int32_t
28+
Values:
29+
Memory occupied by values themselves = 22
30+
sizeof(CSV_Parser) = 25
31+
32+
33+
*/
34+
35+
36+
char * csv_str = "my_strings,my_numbers\r\n"
37+
"hello,5\r\n"
38+
"world,10\r\n";
39+
int csv_str_index = 0;
40+
41+
// This function is responsible for supplying characters to be parsed.
42+
// csv_str may be replaced with SD card reading code or any other
43+
// source of CSV text, like serial port or HTTP request
44+
char feedRowParser() {
45+
return csv_str[csv_str_index++];
46+
}
47+
48+
// This function must return true when the whole CSV file was supplied
49+
// to feedRowParser() function. It will make sure that cp.parseRow()
50+
// returns false when the end of CSV was reached.
51+
bool rowParserFinished() {
52+
return csv_str[csv_str_index] == 0;
53+
}
54+
55+
56+
/*
57+
Alternative way to write both of these functions:
58+
59+
bool csv_end_was_supplied = false;
60+
char feedRowParser() {
61+
if (csv_str_index >= strlen(csv_str)) {
62+
csv_end_was_supplied = true;
63+
return 0;
64+
}
65+
return csv_str[csv_str_index++];
66+
}
67+
68+
bool rowParserFinished() {
69+
return csv_end_was_supplied;
70+
}
71+
*/
72+
73+
void setup() {
74+
Serial.begin(115200);
75+
delay(5000);
76+
77+
CSV_Parser cp(/*format*/ "sL");
78+
79+
Serial.println("Accessing values by column name:");
80+
81+
// parseRow calls feedRowParser() continuously until it reads a
82+
// full row or until the rowParserFinished() returns true
83+
int row_index = 0;
84+
while (cp.parseRow()) {
85+
char *string = ((char**)cp["my_strings"])[0];
86+
int32_t number = ((int32_t*)cp["my_numbers"])[0];
87+
88+
// char *string = ((char**)cp[0])[0];
89+
// int32_t number = ((int32_t*)cp[1])[0];
90+
91+
Serial.print(String(row_index) + ". String = ");
92+
Serial.println(string);
93+
Serial.print(String(row_index) + ". Number = ");
94+
Serial.println(number, DEC);
95+
Serial.println();
96+
row_index++;
97+
}
98+
99+
Serial.println();
100+
cp.print();
101+
}
102+
103+
void loop() {
104+
105+
}

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=CSV Parser
2-
version=1.0.1
2+
version=1.1.0
33
author=Michal Borowski <[email protected]>
44
maintainer=Michal Borowski <[email protected]>
55
sentence=CSV Parser for Arduino.

0 commit comments

Comments
 (0)