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