xer_encoder.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*-
  2. * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
  3. * Redistribution and modifications are permitted subject to BSD license.
  4. */
  5. #include <asn_internal.h>
  6. #include <stdio.h>
  7. #include <errno.h>
  8. /*
  9. * The XER encoder of any type. May be invoked by the application.
  10. */
  11. asn_enc_rval_t
  12. xer_encode(const asn_TYPE_descriptor_t *td, const void *sptr,
  13. enum xer_encoder_flags_e xer_flags, asn_app_consume_bytes_f *cb,
  14. void *app_key) {
  15. asn_enc_rval_t er = {0, 0, 0};
  16. asn_enc_rval_t tmper;
  17. const char *mname;
  18. size_t mlen;
  19. int xcan = (xer_flags & XER_F_CANONICAL) ? 1 : 2;
  20. if(!td || !sptr) goto cb_failed;
  21. mname = td->xml_tag;
  22. mlen = strlen(mname);
  23. ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
  24. tmper = td->op->xer_encoder(td, sptr, 1, xer_flags, cb, app_key);
  25. if(tmper.encoded == -1) return tmper;
  26. er.encoded += tmper.encoded;
  27. ASN__CALLBACK3("</", 2, mname, mlen, ">\n", xcan);
  28. ASN__ENCODED_OK(er);
  29. cb_failed:
  30. ASN__ENCODE_FAILED;
  31. }
  32. /*
  33. * This is a helper function for xer_fprint, which directs all incoming data
  34. * into the provided file descriptor.
  35. */
  36. static int
  37. xer__print2fp(const void *buffer, size_t size, void *app_key) {
  38. FILE *stream = (FILE *)app_key;
  39. if(fwrite(buffer, 1, size, stream) != size)
  40. return -1;
  41. return 0;
  42. }
  43. int
  44. xer_fprint(FILE *stream, const asn_TYPE_descriptor_t *td, const void *sptr) {
  45. asn_enc_rval_t er;
  46. if(!stream) stream = stdout;
  47. if(!td || !sptr)
  48. return -1;
  49. er = xer_encode(td, sptr, XER_F_BASIC, xer__print2fp, stream);
  50. if(er.encoded == -1)
  51. return -1;
  52. return fflush(stream);
  53. }
  54. struct xer_buffer {
  55. char *buffer;
  56. size_t buffer_size;
  57. size_t allocated_size;
  58. };
  59. static int
  60. xer__buffer_append(const void *buffer, size_t size, void *app_key) {
  61. struct xer_buffer *xb = app_key;
  62. while(xb->buffer_size + size + 1 > xb->allocated_size) {
  63. size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64);
  64. char *new_buf = MALLOC(new_size);
  65. if(!new_buf) return -1;
  66. if (xb->buffer) {
  67. memcpy(new_buf, xb->buffer, xb->buffer_size);
  68. }
  69. FREEMEM(xb->buffer);
  70. xb->buffer = new_buf;
  71. xb->allocated_size = new_size;
  72. }
  73. memcpy(xb->buffer + xb->buffer_size, buffer, size);
  74. xb->buffer_size += size;
  75. xb->buffer[xb->buffer_size] = '\0';
  76. return 0;
  77. }
  78. enum xer_equivalence_e
  79. xer_equivalent(const struct asn_TYPE_descriptor_s *td, const void *struct1,
  80. const void *struct2, FILE *opt_debug_stream) {
  81. struct xer_buffer xb1 = {0, 0, 0};
  82. struct xer_buffer xb2 = {0, 0, 0};
  83. asn_enc_rval_t e1, e2;
  84. asn_dec_rval_t rval;
  85. void *sptr = NULL;
  86. if(!td || !struct1 || !struct2) {
  87. if(opt_debug_stream) {
  88. if(!td) fprintf(opt_debug_stream, "Type descriptor missing\n");
  89. if(!struct1) fprintf(opt_debug_stream, "Structure 1 missing\n");
  90. if(!struct2) fprintf(opt_debug_stream, "Structure 2 missing\n");
  91. }
  92. return XEQ_FAILURE;
  93. }
  94. e1 = xer_encode(td, struct1, XER_F_BASIC, xer__buffer_append, &xb1);
  95. if(e1.encoded == -1) {
  96. if(opt_debug_stream) {
  97. fprintf(stderr, "XER Encoding of %s failed\n", td->name);
  98. }
  99. FREEMEM(xb1.buffer);
  100. return XEQ_ENCODE1_FAILED;
  101. }
  102. e2 = xer_encode(td, struct2, XER_F_BASIC, xer__buffer_append, &xb2);
  103. if(e2.encoded == -1) {
  104. if(opt_debug_stream) {
  105. fprintf(stderr, "XER Encoding of %s failed\n", td->name);
  106. }
  107. FREEMEM(xb1.buffer);
  108. FREEMEM(xb2.buffer);
  109. return XEQ_ENCODE1_FAILED;
  110. }
  111. if(xb1.buffer_size != xb2.buffer_size
  112. || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) {
  113. if(opt_debug_stream) {
  114. fprintf(opt_debug_stream,
  115. "Structures XER-encoded into different byte streams:\n=== "
  116. "Structure 1 ===\n%s\n=== Structure 2 ===\n%s\n",
  117. xb1.buffer, xb2.buffer);
  118. }
  119. FREEMEM(xb1.buffer);
  120. FREEMEM(xb2.buffer);
  121. return XEQ_DIFFERENT;
  122. } else {
  123. if(opt_debug_stream) {
  124. fprintf(opt_debug_stream,
  125. "Both structures encoded into the same XER byte stream "
  126. "of size %" ASN_PRI_SIZE ":\n%s",
  127. xb1.buffer_size, xb1.buffer);
  128. }
  129. }
  130. rval = xer_decode(NULL, td, (void **)&sptr, xb1.buffer,
  131. xb1.buffer_size);
  132. switch(rval.code) {
  133. case RC_OK:
  134. break;
  135. case RC_WMORE:
  136. if(opt_debug_stream) {
  137. fprintf(opt_debug_stream,
  138. "Structure %s XER decode unexpectedly requires "
  139. "more data:\n%s\n",
  140. td->name, xb1.buffer);
  141. }
  142. /* Fall through */
  143. case RC_FAIL:
  144. default:
  145. if(opt_debug_stream) {
  146. fprintf(opt_debug_stream,
  147. "Structure %s XER decoding resulted in failure.\n",
  148. td->name);
  149. }
  150. ASN_STRUCT_FREE(*td, sptr);
  151. FREEMEM(xb1.buffer);
  152. FREEMEM(xb2.buffer);
  153. return XEQ_DECODE_FAILED;
  154. }
  155. if(rval.consumed != xb1.buffer_size
  156. && ((rval.consumed > xb1.buffer_size)
  157. || xer_whitespace_span(xb1.buffer + rval.consumed,
  158. xb1.buffer_size - rval.consumed)
  159. != (xb1.buffer_size - rval.consumed))) {
  160. if(opt_debug_stream) {
  161. fprintf(opt_debug_stream,
  162. "Round-trip decode of %s required less bytes (%" ASN_PRI_SIZE ") than "
  163. "encoded (%" ASN_PRI_SIZE ")\n",
  164. td->name, rval.consumed, xb1.buffer_size);
  165. }
  166. ASN_STRUCT_FREE(*td, sptr);
  167. FREEMEM(xb1.buffer);
  168. FREEMEM(xb2.buffer);
  169. return XEQ_ROUND_TRIP_FAILED;
  170. }
  171. /*
  172. * Reuse xb2 to encode newly decoded structure.
  173. */
  174. FREEMEM(xb2.buffer);
  175. memset(&xb2, 0, sizeof(xb2));
  176. e2 = xer_encode(td, sptr, XER_F_BASIC, xer__buffer_append, &xb2);
  177. if(e2.encoded == -1) {
  178. if(opt_debug_stream) {
  179. fprintf(stderr, "XER Encoding of round-trip decode of %s failed\n",
  180. td->name);
  181. }
  182. ASN_STRUCT_FREE(*td, sptr);
  183. FREEMEM(xb1.buffer);
  184. FREEMEM(xb2.buffer);
  185. return XEQ_ROUND_TRIP_FAILED;
  186. }
  187. ASN_STRUCT_FREE(*td, sptr);
  188. sptr = 0;
  189. if(xb1.buffer_size != xb2.buffer_size
  190. || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) {
  191. if(opt_debug_stream) {
  192. fprintf(opt_debug_stream,
  193. "XER Encoding of round-trip decode of %s resulted in "
  194. "different byte stream:\n"
  195. "=== Original ===\n%s\n"
  196. "=== Round-tripped ===\n%s\n",
  197. xb1.buffer, xb2.buffer, td->name);
  198. }
  199. FREEMEM(xb1.buffer);
  200. FREEMEM(xb2.buffer);
  201. return XEQ_ROUND_TRIP_FAILED;
  202. }
  203. FREEMEM(xb1.buffer);
  204. FREEMEM(xb2.buffer);
  205. return XEQ_SUCCESS;
  206. }