aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTadas Vilkeliskis <vilkeliskis.t@gmail.com>2013-11-03 16:23:58 -0500
committerTadas Vilkeliskis <vilkeliskis.t@gmail.com>2013-11-03 16:23:58 -0500
commit01cf97e60f970490a94a56d8c82fca320e17fac5 (patch)
tree2eacf7fd2f800bc04c06eb383e07b731ef7fb0a9
parent4cd6b4d5045b5d3530b27159edca64479a5c346c (diff)
put parser into error state if callback returns non-zero
-rw-r--r--src/csv_parser.c6
-rw-r--r--src/csv_parser.h7
-rw-r--r--tests/main.c38
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);