libcsv_demo.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. #include <limits.h>
  8. /* libcsv */
  9. #include "libcsv.h"
  10. /* optparse */
  11. #include "optparse.h"
  12. #define PROGRAM_NAME "csvcheck"
  13. #define AUTHORS "Robert Gamble"
  14. static struct optparse_long longopts[] =
  15. {
  16. {"delimiter", 'd', OPTPARSE_REQUIRED},
  17. {"quote", 'q', OPTPARSE_REQUIRED},
  18. {"help", CHAR_MAX + 1, OPTPARSE_NONE},
  19. {NULL, 0, OPTPARSE_NONE}
  20. };
  21. /* The name this program was called with */
  22. char *program_name;
  23. /* The delimiter character */
  24. char delimiter = CSV_COMMA;
  25. /* The delimiter argument */
  26. char *delimiter_name;
  27. /* The quote character */
  28. char quote = CSV_QUOTE;
  29. /* The quote argument */
  30. char *quote_name;
  31. void usage(int status)
  32. {
  33. if (status != RT_EOK)
  34. fprintf (stderr, "Try `%s --help for more information.\n", program_name);
  35. else {
  36. printf("\
  37. Usage: %s [OPTION]... [FILE]...\n\
  38. Determine if file(s) are properly formed CSV files and display the position\n\
  39. of the first offending byte if not.\n\
  40. \n\
  41. ", program_name);
  42. printf("\
  43. -d, --delimiter=DELIM use DELIM as the delimiter instead of comma\n\
  44. -q, --quote=QUOTE_CHAR use QUOTE_CHAR as the quote character instead of\n\
  45. double quote\n\
  46. --help display this help and exit\n\
  47. ");
  48. }
  49. }
  50. void check_file(char *filename)
  51. {
  52. size_t pos = 0;
  53. char buf[1024];
  54. struct csv_parser p;
  55. FILE *fp;
  56. size_t bytes_read;
  57. size_t retval;
  58. if (csv_init(&p, CSV_STRICT | CSV_STRICT_FINI) != 0)
  59. {
  60. fprintf(stderr, "Failed to initialize csv parser\n");
  61. return;
  62. }
  63. csv_set_delim(&p, delimiter);
  64. csv_set_quote(&p, quote);
  65. if (filename == NULL || !strcmp(filename, "-"))
  66. {
  67. fp = stdin;
  68. }
  69. else
  70. {
  71. fp = fopen(filename, "rb");
  72. if (fp == NULL)
  73. {
  74. fprintf(stderr, "Failed to open file %s: %s\n", filename, strerror(errno));
  75. csv_free(&p);
  76. return;
  77. }
  78. }
  79. while ((bytes_read = fread(buf, 1, 1024, fp)) > 0)
  80. {
  81. if ((retval = csv_parse(&p, buf, bytes_read, NULL, NULL, NULL)) != bytes_read)
  82. {
  83. if (csv_error(&p) == CSV_EPARSE)
  84. {
  85. printf("%s: malformed at byte %lu\n", filename ? filename : "stdin", (unsigned long)pos + retval + 1);
  86. goto end;
  87. }
  88. else
  89. {
  90. printf("Error while processing %s: %s\n", filename ? filename : "stdin", csv_strerror(csv_error(&p)));
  91. goto end;
  92. }
  93. }
  94. pos += 1024;
  95. }
  96. if (csv_fini(&p, NULL, NULL, NULL) != 0)
  97. printf("%s: missing closing quote at end of input\n", filename ? filename : "stdin");
  98. else
  99. printf("%s well-formed\n", filename ? filename : "data is");
  100. end:
  101. fclose(fp);
  102. }
  103. int csvcheck(int argc, char *argv[])
  104. {
  105. int optc;
  106. int option_index;
  107. program_name = argv[0];
  108. struct optparse options;
  109. if(argc == 1)
  110. {
  111. usage(RT_EOK);
  112. return RT_EOK;
  113. }
  114. optparse_init(&options, argv);
  115. while ((optc = optparse_long(&options, longopts, &option_index)) != -1)
  116. {
  117. switch (optc)
  118. {
  119. case 'd':
  120. delimiter_name = options.optarg;
  121. if (strlen(delimiter_name) > 1)
  122. printf("delimiter must be exactly one byte long\n");
  123. else
  124. delimiter = delimiter_name[0];
  125. break;
  126. case 'q':
  127. quote_name = options.optarg;
  128. if (strlen(quote_name) > 1)
  129. printf("delimiter must be exactly one byte long\n");
  130. else
  131. quote = quote_name[0];
  132. break;
  133. case CHAR_MAX + 1:
  134. /* --help */
  135. usage(RT_EOK);
  136. return RT_EOK;
  137. default:
  138. usage(RT_ERROR);
  139. return RT_ERROR;
  140. }
  141. }
  142. if (options.optind < argc)
  143. {
  144. while (options.optind < argc)
  145. {
  146. check_file(argv[options.optind++]);
  147. }
  148. }
  149. else
  150. {
  151. /* Process from stdin */
  152. check_file(NULL);
  153. }
  154. return RT_EOK;
  155. }
  156. MSH_CMD_EXPORT(csvcheck, The command to check CSV files format based on the libcsv.);