You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ucl_emitter_streamline.c 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* Copyright (c) 2014, Vsevolod Stakhov
  2. * All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. *
  12. * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  13. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  16. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include "ucl.h"
  27. #include "ucl_internal.h"
  28. #include "ucl_chartable.h"
  29. struct ucl_emitter_streamline_stack {
  30. bool is_array;
  31. bool empty;
  32. const ucl_object_t *obj;
  33. struct ucl_emitter_streamline_stack *next;
  34. };
  35. struct ucl_emitter_context_streamline {
  36. /* Inherited from the main context */
  37. /** Name of emitter (e.g. json, compact_json) */
  38. const char *name;
  39. /** Unique id (e.g. UCL_EMIT_JSON for standard emitters */
  40. int id;
  41. /** A set of output functions */
  42. const struct ucl_emitter_functions *func;
  43. /** A set of output operations */
  44. const struct ucl_emitter_operations *ops;
  45. /** Current amount of indent tabs */
  46. unsigned int indent;
  47. /** Top level object */
  48. const ucl_object_t *top;
  49. /** Optional comments */
  50. const ucl_object_t *comments;
  51. /* Streamline specific fields */
  52. struct ucl_emitter_streamline_stack *containers;
  53. };
  54. #define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx)
  55. struct ucl_emitter_context*
  56. ucl_object_emit_streamline_new (const ucl_object_t *obj,
  57. enum ucl_emitter emit_type,
  58. struct ucl_emitter_functions *emitter)
  59. {
  60. const struct ucl_emitter_context *ctx;
  61. struct ucl_emitter_context_streamline *sctx;
  62. ctx = ucl_emit_get_standard_context (emit_type);
  63. if (ctx == NULL) {
  64. return NULL;
  65. }
  66. sctx = calloc (1, sizeof (*sctx));
  67. if (sctx == NULL) {
  68. return NULL;
  69. }
  70. memcpy (sctx, ctx, sizeof (*ctx));
  71. sctx->func = emitter;
  72. sctx->top = obj;
  73. ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx,
  74. obj);
  75. return (struct ucl_emitter_context *)sctx;
  76. }
  77. void
  78. ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
  79. const ucl_object_t *obj)
  80. {
  81. struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
  82. struct ucl_emitter_streamline_stack *st, *top;
  83. bool print_key = false;
  84. /* Check top object presence */
  85. if (sctx->top == NULL) {
  86. sctx->top = obj;
  87. }
  88. top = sctx->containers;
  89. st = malloc (sizeof (*st));
  90. if (st != NULL) {
  91. if (top != NULL && !top->is_array) {
  92. print_key = true;
  93. }
  94. st->empty = true;
  95. st->obj = obj;
  96. if (obj != NULL && obj->type == UCL_ARRAY) {
  97. st->is_array = true;
  98. sctx->ops->ucl_emitter_start_array (ctx, obj, print_key);
  99. }
  100. else {
  101. st->is_array = false;
  102. sctx->ops->ucl_emitter_start_object (ctx, obj, print_key);
  103. }
  104. LL_PREPEND (sctx->containers, st);
  105. }
  106. }
  107. void
  108. ucl_object_emit_streamline_add_object (
  109. struct ucl_emitter_context *ctx, const ucl_object_t *obj)
  110. {
  111. struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
  112. bool is_array = false, is_first = false;
  113. if (sctx->containers != NULL) {
  114. if (sctx->containers->is_array) {
  115. is_array = true;
  116. }
  117. if (sctx->containers->empty) {
  118. is_first = true;
  119. sctx->containers->empty = false;
  120. }
  121. }
  122. sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array);
  123. }
  124. void
  125. ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)
  126. {
  127. struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
  128. struct ucl_emitter_streamline_stack *st;
  129. if (sctx->containers != NULL) {
  130. st = sctx->containers;
  131. if (st->is_array) {
  132. sctx->ops->ucl_emitter_end_array (ctx, st->obj);
  133. }
  134. else {
  135. sctx->ops->ucl_emitter_end_object (ctx, st->obj);
  136. }
  137. sctx->containers = st->next;
  138. free (st);
  139. }
  140. }
  141. void
  142. ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx)
  143. {
  144. struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
  145. while (sctx->containers != NULL) {
  146. ucl_object_emit_streamline_end_container (ctx);
  147. }
  148. free (sctx);
  149. }