From 01cf97e60f970490a94a56d8c82fca320e17fac5 Mon Sep 17 00:00:00 2001 From: Tadas Vilkeliskis Date: Sun, 3 Nov 2013 16:23:58 -0500 Subject: put parser into error state if callback returns non-zero --- src/csv_parser.c | 6 ++++++ src/csv_parser.h | 7 +++++-- tests/main.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/csv_parser.c b/src/csv_parser.c index 29f0529..b93713a 100644 --- a/src/csv_parser.c +++ b/src/csv_parser.c @@ -96,6 +96,7 @@ size_t csv_parser_execute(csv_parser_t *parser, parser->row, parser->col); if (r) { + parser->state = csvps_error; return parser->nread; } } @@ -112,6 +113,7 @@ size_t csv_parser_execute(csv_parser_t *parser, parser->row, parser->col); if (r) { + parser->state = csvps_error; return parser->nread; } } @@ -129,6 +131,7 @@ size_t csv_parser_execute(csv_parser_t *parser, parser->row, parser->col); if (r) { + parser->state = csvps_error; return parser->nread; } } @@ -142,6 +145,9 @@ size_t csv_parser_execute(csv_parser_t *parser, parser->state = csvps_line_start; } break; + case csvps_error: + return parser->nread; + break; default: assert(0 && "invalid parser state"); break; diff --git a/src/csv_parser.h b/src/csv_parser.h index 2e263a2..8c78e8b 100644 --- a/src/csv_parser.h +++ b/src/csv_parser.h @@ -37,7 +37,8 @@ typedef enum csv_parser_state_t { csvps_field_value, csvps_field_end, csvps_line_end_begin, - csvps_line_end + csvps_line_end, + csvps_error, } csv_parser_state_t; @@ -78,7 +79,9 @@ void csv_parser_init(csv_parser_t *parser); /** * Executes CSV parser on the given data. Returns number - * of bytes read. + * of bytes read. User should always check if parser state + * is ``csvps_error``. Parser will get into the error state + * if field callback returns a non-zero value. */ size_t csv_parser_execute(csv_parser_t *parser, const csv_parser_settings_t *settings, diff --git a/tests/main.c b/tests/main.c index 25d0a36..90863d8 100644 --- a/tests/main.c +++ b/tests/main.c @@ -121,6 +121,43 @@ int field_cb(csv_parser_t *parser, const char *data, size_t length, int row, int } +int field_error_cb(csv_parser_t *parser, const char *data, size_t length, int row, int col) +{ + return -1; +} + + +START_TEST(test_parser_error_state) +{ + csv_parser_t parser; + csv_parser_settings_t settings; + int i; + int nread; + const char *str = "a,v,b\n1,2"; + int len = strlen(str); + + csv_parser_state_t states_to_test[] = { + csvps_line_start, + csvps_field_start, + csvps_field_end, + csvps_line_end_begin, + csvps_line_end + }; + + settings.delimiter = ','; + settings.field_cb = field_error_cb; + + for (i = 0; i < 5; i++) { + csv_parser_state_t state = states_to_test[i]; + csv_parser_init(&parser); + parser.state = state; + nread = csv_parser_execute(&parser, &settings, str, len); + ck_assert(parser.state == csvps_error); + } +} +END_TEST + + START_TEST(test_parser_full) { csv_parser_t parser; @@ -202,6 +239,7 @@ int main(int argc, const char *argv[]) TCase *tc = tcase_create("parser"); tcase_add_test(tc, test_parser_full); tcase_add_test(tc, test_parser_chunked); + tcase_add_test(tc, test_parser_error_state); suite_add_tcase(s, tc); SRunner *sr = srunner_create(s); -- cgit v1.2.3