t/helper/test-json-writer.c: avoid using `strtok()`

Apply similar treatment as in the previous commit to remove usage of `strtok()` from the "oidmap" test helper. Each of the different commands that the "json-writer" helper accepts pops the next space-delimited token from the current line and interprets it as a string, integer, or double (with the exception of the very first token, which is the command itself). To accommodate this, split the line in place by the space character, and pass the corresponding string_list to each of the specialized `get_s()`, `get_i()`, and `get_d()` functions. `get_i()` and `get_d()` are thin wrappers around `get_s()` that convert their result into the appropriate type by either calling `strtol()` or `strtod()`, respectively. In `get_s()`, we mark the token as "consumed" by incrementing the `consumed_nr` counter, indicating how many tokens we have read up to that point. Because each of these functions needs the string-list parts, the number of tokens consumed, and the line number, these three are wrapped up in to a struct representing the line state. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Apr 24, 2023 at 18:20 UTC a2742f8c59dae6ef55895933e0950d61b6d03720
1 file changed +48 -28
t/helper/test-json-writer.c
+48 -28
@@ -1,5 +1,6 @@
1 #include "test-tool.h"
2 #include "json-writer.h"
3 +#include "string-list.h"
4
5 static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}";
6 static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}";
@@ -394,35 +395,41 @@ static int unit_tests(void)
395 return 0;
396 }
397
397 -static void get_s(int line_nr, char **s_in)
398 +struct line {
399 + struct string_list *parts;
400 + size_t consumed_nr;
401 + int nr;
402 +};
403 +
404 +static void get_s(struct line *line, char **s_in)
405 {
399 - *s_in = strtok(NULL, " ");
400 - if (!*s_in)
401 - die("line[%d]: expected: <s>", line_nr);
406 + if (line->consumed_nr > line->parts->nr)
407 + die("line[%d]: expected: <s>", line->nr);
408 + *s_in = line->parts->items[line->consumed_nr++].string;
409 }
410
404 -static void get_i(int line_nr, intmax_t *s_in)
411 +static void get_i(struct line *line, intmax_t *s_in)
412 {
413 char *s;
414 char *endptr;
415
409 - get_s(line_nr, &s);
416 + get_s(line, &s);
417
418 *s_in = strtol(s, &endptr, 10);
419 if (*endptr || errno == ERANGE)
413 - die("line[%d]: invalid integer value", line_nr);
420 + die("line[%d]: invalid integer value", line->nr);
421 }
422
416 -static void get_d(int line_nr, double *s_in)
423 +static void get_d(struct line *line, double *s_in)
424 {
425 char *s;
426 char *endptr;
427
421 - get_s(line_nr, &s);
428 + get_s(line, &s);
429
430 *s_in = strtod(s, &endptr);
431 if (*endptr || errno == ERANGE)
425 - die("line[%d]: invalid float value", line_nr);
432 + die("line[%d]: invalid float value", line->nr);
433 }
434
435 static int pretty;
@@ -453,6 +460,7 @@ static char *get_trimmed_line(char *buf, int buf_size)
460
461 static int scripted(void)
462 {
463 + struct string_list parts = STRING_LIST_INIT_NODUP;
464 struct json_writer jw = JSON_WRITER_INIT;
465 char buf[MAX_LINE_LENGTH];
466 char *line;
@@ -470,66 +478,77 @@ static int scripted(void)
478 die("expected first line to be 'object' or 'array'");
479
480 while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) {
481 + struct line state = { 0 };
482 char *verb;
483 char *key;
484 char *s_value;
485 intmax_t i_value;
486 double d_value;
487
479 - line_nr++;
488 + state.parts = &parts;
489 + state.nr = ++line_nr;
490 +
491 + /* break line into command and zero or more tokens */
492 + string_list_setlen(&parts, 0);
493 + string_list_split_in_place(&parts, line, " ", -1);
494 + string_list_remove_empty_items(&parts, 0);
495 +
496 + /* ignore empty lines */
497 + if (!parts.nr || !*parts.items[0].string)
498 + continue;
499
481 - verb = strtok(line, " ");
500 + verb = parts.items[state.consumed_nr++].string;
501
502 if (!strcmp(verb, "end")) {
503 jw_end(&jw);
504 }
505 else if (!strcmp(verb, "object-string")) {
487 - get_s(line_nr, &key);
488 - get_s(line_nr, &s_value);
506 + get_s(&state, &key);
507 + get_s(&state, &s_value);
508 jw_object_string(&jw, key, s_value);
509 }
510 else if (!strcmp(verb, "object-int")) {
492 - get_s(line_nr, &key);
493 - get_i(line_nr, &i_value);
511 + get_s(&state, &key);
512 + get_i(&state, &i_value);
513 jw_object_intmax(&jw, key, i_value);
514 }
515 else if (!strcmp(verb, "object-double")) {
497 - get_s(line_nr, &key);
498 - get_i(line_nr, &i_value);
499 - get_d(line_nr, &d_value);
516 + get_s(&state, &key);
517 + get_i(&state, &i_value);
518 + get_d(&state, &d_value);
519 jw_object_double(&jw, key, i_value, d_value);
520 }
521 else if (!strcmp(verb, "object-true")) {
503 - get_s(line_nr, &key);
522 + get_s(&state, &key);
523 jw_object_true(&jw, key);
524 }
525 else if (!strcmp(verb, "object-false")) {
507 - get_s(line_nr, &key);
526 + get_s(&state, &key);
527 jw_object_false(&jw, key);
528 }
529 else if (!strcmp(verb, "object-null")) {
511 - get_s(line_nr, &key);
530 + get_s(&state, &key);
531 jw_object_null(&jw, key);
532 }
533 else if (!strcmp(verb, "object-object")) {
515 - get_s(line_nr, &key);
534 + get_s(&state, &key);
535 jw_object_inline_begin_object(&jw, key);
536 }
537 else if (!strcmp(verb, "object-array")) {
519 - get_s(line_nr, &key);
538 + get_s(&state, &key);
539 jw_object_inline_begin_array(&jw, key);
540 }
541 else if (!strcmp(verb, "array-string")) {
523 - get_s(line_nr, &s_value);
542 + get_s(&state, &s_value);
543 jw_array_string(&jw, s_value);
544 }
545 else if (!strcmp(verb, "array-int")) {
527 - get_i(line_nr, &i_value);
546 + get_i(&state, &i_value);
547 jw_array_intmax(&jw, i_value);
548 }
549 else if (!strcmp(verb, "array-double")) {
531 - get_i(line_nr, &i_value);
532 - get_d(line_nr, &d_value);
550 + get_i(&state, &i_value);
551 + get_d(&state, &d_value);
552 jw_array_double(&jw, i_value, d_value);
553 }
554 else if (!strcmp(verb, "array-true"))
@@ -552,6 +571,7 @@ static int scripted(void)
571 printf("%s\n", jw.json.buf);
572
573 jw_release(&jw);
574 + string_list_clear(&parts, 0);
575 return 0;
576 }
577