Skip to content

Commit 691e49c

Browse files
committed
Bug fix (supplying char by char broke quotes parsing)
1 parent 5eac2fb commit 691e49c

File tree

3 files changed

+40
-32
lines changed

3 files changed

+40
-32
lines changed

CSV_Parser.cpp

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
//#include "mem_check.h" // COMMENT-OUT BEFORE UPLOAD
1010

11-
//Stream * CSV_Parser::debug_serial = &Serial;
11+
// Stream * CSV_Parser::debug_serial = &Serial;
1212

1313
/* Helper function useful for handling unsigned format specifiers. */
1414
char * CSV_Parser::strdup_ignoring_u(const char *s) {
@@ -189,25 +189,26 @@ char * CSV_Parser::parseStringValue(const char * s, int * chars_occupied) {
189189
if(*s != quote_char) {
190190
char * first_delim = strpbrk(s, delim_chars);
191191
int val_len = 0;
192-
if (first_delim || whole_csv_supplied) {
193-
if (first_delim) {
194-
val_len = first_delim - s;
195-
*chars_occupied = val_len + (*first_delim == delimiter) + strspn(first_delim, "\r\n");
196-
}
197-
else {
198-
val_len = strlen(s);
199-
*chars_occupied = val_len;
200-
}
201-
202-
//return strndup(s, *chars_occupied); // available for Esp8266 but not for Arduino :(
203-
char *str = (char*)malloc(val_len + 1);
204-
memcpy(str, s, val_len);
205-
str[val_len] = 0;
206-
return str;
192+
if (!first_delim && !whole_csv_supplied) {
193+
// delim_chars not found in string
194+
*chars_occupied = 0;
195+
return 0;
207196
}
208-
// delim_chars not found in string
209-
*chars_occupied = 0;
210-
return 0;
197+
198+
if (first_delim) {
199+
val_len = first_delim - s;
200+
*chars_occupied = val_len + (*first_delim == delimiter) + strspn(first_delim, "\r\n");
201+
}
202+
else {
203+
val_len = strlen(s);
204+
*chars_occupied = val_len;
205+
}
206+
207+
//return strndup(s, *chars_occupied); // available for Esp8266 but not for Arduino :(
208+
char *str = (char*)malloc(val_len + 1);
209+
memcpy(str, s, val_len);
210+
str[val_len] = 0;
211+
return str;
211212
}
212213

213214
/* If value is enclosed in double quotes. Being enclosed in double quotes automatically
@@ -224,6 +225,12 @@ char * CSV_Parser::parseStringValue(const char * s, int * chars_occupied) {
224225
len--;
225226
continue;
226227
}
228+
// only assume the current quote is the ending quote if the next character is a delimiter or a new line
229+
// WARNING: parseLeftover does not need such condition, "whole_csv_supplied" can be used to check if parseLeftover was used
230+
if (!whole_csv_supplied && !strpbrk(next_quote + 1, delim_chars)) {
231+
s = next_quote + 1;
232+
continue;
233+
}
227234
ending_quote_found = true;
228235

229236
*chars_occupied += next_quote - base;
@@ -417,21 +424,21 @@ void CSV_Parser::supplyChunk(const char *s) {
417424
if (leftover) {
418425
int leftover_len = strlen(leftover);
419426

420-
// If there's no leftover and first supplied char is '\n' then it could be the case that the last char was "\r",
421-
// so '\n' should be ignored.
422-
// The same applies to situation where " (quote char) was previously received and the supplied char is '\r'
423-
if (leftover_len == 0 && ignore_next_delimchar && (*s == '\n' || *s == '\r' || *s == delimiter)) {
424-
if(*s != '\r')
425-
ignore_next_delimchar = false;
426-
s++;
427-
}
428-
427+
// If there's no leftover and first supplied char is '\n' then it could be the case that the last char was "\r",
428+
// so '\n' should be ignored.
429+
// The same applies to situation where " (quote char) was previously received and the supplied char is '\r'
430+
if (leftover_len == 0 && ignore_next_delimchar && (*s == '\n' || *s == '\r' || *s == delimiter)) {
431+
if(*s != '\r')
432+
ignore_next_delimchar = false;
433+
s++;
434+
}
435+
429436
int s_len = strlen(s);
430437
//debug_serial->println("leftover_len = " + String(leftover_len) + ", s_len = " + String(s_len));
431438
leftover = (char*)realloc(leftover, leftover_len + s_len + 1);
432439

433-
//if (!leftover)
434-
// debug_serial->println("leftover realloc failed");
440+
//if (!leftover)
441+
// debug_serial->println("leftover realloc failed");
435442
strcat(leftover, s);
436443
s = leftover;
437444
//debug_serial->println("merged leftover = " + String(leftover));
@@ -440,7 +447,7 @@ void CSV_Parser::supplyChunk(const char *s) {
440447
int chars_occupied = 0;
441448
char * val = 0;
442449
while ((val = parseStringValue(s, &chars_occupied))) {
443-
//debug_serial->println("rows_count = " + String(rows_count) + ", current_col = " + String(current_col) + ", val = " + String(val));
450+
// debug_serial->println("rows_count = " + String(rows_count) + ", current_col = " + String(current_col) + ", val = " + String(val));
444451
if (fmt[current_col] != '-') {
445452
if (!header_parsed) {
446453
keys[current_col] = strdup_trimmed(val);

keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ printKeys KEYWORD2
1919
setDebugSerial KEYWORD2
2020
parseLeftover KEYWORD2
2121
readSDfile KEYWORD2
22+
parseRow KEYWORD2
2223

2324
######################################
2425
# Constants (LITERAL1)

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.2.2
2+
version=1.3.0
33
author=Michal Borowski <[email protected]>
44
maintainer=Michal Borowski <[email protected]>
55
sentence=CSV Parser for Arduino.

0 commit comments

Comments
 (0)