hipack-roundtrip.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * hipack-roundtrip.c
  3. * Copyright (C) 2015 Adrian Perez <aperez@igalia.com>
  4. *
  5. * Distributed under terms of the MIT license.
  6. */
  7. #define _POSIX_C_SOURCE 2
  8. #include "../hipack.h"
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <errno.h>
  12. static void
  13. usage (const char *argv0, int code)
  14. {
  15. FILE *output = (code == EXIT_FAILURE) ? stderr : stdout;
  16. fprintf (output, "Usage: %s [-c] PATH\n", argv0);
  17. exit (code);
  18. }
  19. int
  20. main (int argc, char *argv[])
  21. {
  22. bool compact = false;
  23. int opt;
  24. while ((opt = getopt (argc, argv, "hc")) != -1) {
  25. switch (opt) {
  26. case 'c':
  27. compact = true;
  28. break;
  29. case 'h':
  30. usage (argv[0], EXIT_SUCCESS);
  31. break;
  32. default:
  33. usage (argv[0], EXIT_FAILURE);
  34. }
  35. }
  36. if (optind >= argc) {
  37. usage (argv[0], EXIT_FAILURE);
  38. }
  39. FILE *fp = fopen (argv[optind], "rb");
  40. if (!fp) {
  41. fprintf (stderr, "%s: Cannot open '%s' (%s)\n",
  42. argv[0], argv[optind], strerror (errno));
  43. return EXIT_FAILURE;
  44. }
  45. int retcode = EXIT_SUCCESS;
  46. hipack_reader_t reader = {
  47. .getchar = hipack_stdio_getchar,
  48. .getchar_data = fp,
  49. };
  50. hipack_dict_t *message1 = hipack_read (&reader);
  51. hipack_dict_t *message2 = NULL;
  52. if (!message1) {
  53. assert (reader.error);
  54. fprintf (stderr, "[pass 1] line %u, column %u: %s\n",
  55. reader.error_line, reader.error_column,
  56. (reader.error == HIPACK_READ_ERROR)
  57. ? strerror (errno) : reader.error);
  58. retcode = EXIT_FAILURE;
  59. goto cleanup;
  60. }
  61. fclose (fp);
  62. /* Create a temporary file and write the message to it. */
  63. fp = tmpfile ();
  64. hipack_writer_t writer = {
  65. .putchar = hipack_stdio_putchar,
  66. .putchar_data = fp,
  67. .indent = compact ? HIPACK_WRITER_COMPACT : HIPACK_WRITER_INDENTED,
  68. };
  69. if (hipack_write (&writer, message1)) {
  70. fprintf (stderr, "write error: %s\n", strerror (errno));
  71. retcode = EXIT_FAILURE;
  72. goto cleanup;
  73. }
  74. /* Re-read the dumped file. */
  75. rewind (fp);
  76. reader = (hipack_reader_t) {
  77. .getchar = hipack_stdio_getchar,
  78. .getchar_data = fp,
  79. };
  80. message2 = hipack_read (&reader);
  81. if (!message2) {
  82. assert (reader.error);
  83. fprintf (stderr, "[pass 2] line %u, column %u: %s\n",
  84. reader.error_line, reader.error_column,
  85. (reader.error == HIPACK_READ_ERROR)
  86. ? strerror (errno) : reader.error);
  87. retcode = EXIT_FAILURE;
  88. goto cleanup;
  89. }
  90. if (!hipack_dict_equal (message1, message2)) {
  91. fprintf (stderr, "Messages are different\n");
  92. retcode = EXIT_FAILURE;
  93. }
  94. cleanup:
  95. hipack_dict_free (message1);
  96. hipack_dict_free (message2);
  97. if (fp) fclose (fp);
  98. return retcode;
  99. }