ISSUE ID:- RICAPP-216
[ric-app/bouncer.git] / Bouncer / e2sm_kpm / lib / BMPString.c
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 <BMPString.h>
7 #include <UTF8String.h>
8
9 /*
10  * BMPString basic type description.
11  */
12 static const ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
13         (ASN_TAG_CLASS_UNIVERSAL | (30 << 2)),  /* [UNIVERSAL 30] IMPLICIT ...*/
14         (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))    /* ... OCTET STRING */
15 };
16 asn_OCTET_STRING_specifics_t asn_SPC_BMPString_specs = {
17         sizeof(BMPString_t),
18         offsetof(BMPString_t, _asn_ctx),
19         ASN_OSUBV_U16   /* 16-bits character */
20 };
21 static asn_per_constraints_t asn_DEF_BMPString_per_constraints = {
22         { APC_CONSTRAINED, 16, 16, 0, 65535 },
23         { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
24         0, 0
25 };
26 asn_TYPE_operation_t asn_OP_BMPString = {
27         OCTET_STRING_free,          /* Implemented in terms of OCTET STRING */
28         BMPString_print,
29         OCTET_STRING_compare,
30         OCTET_STRING_decode_ber,
31         OCTET_STRING_encode_der,
32         BMPString_decode_xer,           /* Convert from UTF-8 */
33         BMPString_encode_xer,           /* Convert to UTF-8 */
34 #ifdef  ASN_DISABLE_OER_SUPPORT
35         0,
36         0,
37 #else
38         OCTET_STRING_decode_oer,
39         OCTET_STRING_encode_oer,
40 #endif  /* ASN_DISABLE_OER_SUPPORT */
41 #ifdef  ASN_DISABLE_PER_SUPPORT
42         0,
43         0,
44         0,
45         0,
46 #else
47         OCTET_STRING_decode_uper,
48         OCTET_STRING_encode_uper,
49         OCTET_STRING_decode_aper,
50         OCTET_STRING_encode_aper,
51 #endif  /* ASN_DISABLE_PER_SUPPORT */
52         OCTET_STRING_random_fill,
53         0       /* Use generic outmost tag fetcher */
54 };
55 asn_TYPE_descriptor_t asn_DEF_BMPString = {
56         "BMPString",
57         "BMPString",
58         &asn_OP_BMPString,
59         asn_DEF_BMPString_tags,
60         sizeof(asn_DEF_BMPString_tags)
61           / sizeof(asn_DEF_BMPString_tags[0]) - 1,
62         asn_DEF_BMPString_tags,
63         sizeof(asn_DEF_BMPString_tags)
64           / sizeof(asn_DEF_BMPString_tags[0]),
65         { 0, &asn_DEF_BMPString_per_constraints, BMPString_constraint },
66         0, 0,   /* No members */
67         &asn_SPC_BMPString_specs
68 };
69
70 int
71 BMPString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
72                      asn_app_constraint_failed_f *ctfailcb, void *app_key) {
73     const BMPString_t *st = (const BMPString_t *)sptr;
74
75     if(st && st->buf) {
76         if(st->size & 1) {
77             ASN__CTFAIL(app_key, td, sptr,
78                         "%s: invalid size %" ASN_PRI_SIZE " not divisible by 2 (%s:%d)",
79                         td->name, st->size, __FILE__, __LINE__);
80             return -1;
81         }
82     } else {
83         ASN__CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name,
84                     __FILE__, __LINE__);
85         return -1;
86     }
87
88     return 0;
89 }
90
91 /*
92  * BMPString specific contents printer.
93  */
94 static ssize_t
95 BMPString__dump(const BMPString_t *st,
96                 asn_app_consume_bytes_f *cb, void *app_key) {
97         char scratch[128];                      /* Scratchpad buffer */
98         char *p = scratch;
99         ssize_t wrote = 0;
100         uint8_t *ch;
101         uint8_t *end;
102
103         ch = st->buf;
104         end = (st->buf + st->size);
105         for(end--; ch < end; ch += 2) {
106                 uint16_t wc = (ch[0] << 8) | ch[1];     /* 2 bytes */
107                 if(sizeof(scratch) - (p - scratch) < 3) {
108                         wrote += p - scratch;
109                         if(cb(scratch, p - scratch, app_key) < 0)
110                                 return -1;
111                         p = scratch;
112                 }
113                 if(wc < 0x80) {
114                         *p++ = (char)wc;
115                 } else if(wc < 0x800) {
116                         *p++ = 0xc0 | ((wc >> 6));
117                         *p++ = 0x80 | ((wc & 0x3f));
118                 } else {
119                         *p++ = 0xe0 | ((wc >> 12));
120                         *p++ = 0x80 | ((wc >> 6) & 0x3f);
121                         *p++ = 0x80 | ((wc & 0x3f));
122                 }
123         }
124
125         wrote += p - scratch;
126         if(cb(scratch, p - scratch, app_key) < 0)
127                 return -1;
128
129         return wrote;
130 }
131
132 asn_dec_rval_t
133 BMPString_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
134                      const asn_TYPE_descriptor_t *td, void **sptr,
135                      const char *opt_mname, const void *buf_ptr, size_t size) {
136     asn_dec_rval_t rc;
137
138         rc = OCTET_STRING_decode_xer_utf8(opt_codec_ctx, td, sptr, opt_mname,
139                 buf_ptr, size);
140         if(rc.code == RC_OK) {
141                 /*
142                  * Now we have a whole string in UTF-8 format.
143                  * Convert it into UCS-2.
144                  */
145                 uint32_t *wcs;
146                 size_t wcs_len;
147                 UTF8String_t *st;
148
149                 assert(*sptr);
150                 st = (UTF8String_t *)*sptr;
151                 assert(st->buf);
152                 wcs_len = UTF8String_to_wcs(st, 0, 0);
153
154                 wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
155                 if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
156                         rc.code = RC_FAIL;
157                         rc.consumed = 0;
158                         return rc;
159                 } else {
160                         wcs[wcs_len] = 0;       /* nul-terminate */
161                 }
162
163                 if(1) {
164                         /* Swap byte order and trim encoding to 2 bytes */
165                         uint32_t *wc = wcs;
166                         uint32_t *wc_end = wcs + wcs_len;
167                         uint16_t *dstwc = (uint16_t *)wcs;
168                         for(; wc < wc_end; wc++, dstwc++) {
169                                 uint32_t wch = *wc;
170                                 if(wch > 0xffff) {
171                                         FREEMEM(wcs);
172                                         rc.code = RC_FAIL;
173                                         rc.consumed = 0;
174                                         return rc;
175                                 }
176                                 *((uint8_t *)dstwc + 0) = wch >> 8;
177                                 *((uint8_t *)dstwc + 1) = wch;
178                         }
179                         dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
180                         if(!dstwc) {
181                                 FREEMEM(wcs);
182                                 rc.code = RC_FAIL;
183                                 rc.consumed = 0;
184                                 return rc;
185                         } else {
186                                 dstwc[wcs_len] = 0;     /* nul-terminate */
187                                 wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
188                         }
189                 }
190
191                 FREEMEM(st->buf);
192                 st->buf = (uint8_t *)wcs;
193                 st->size = 2 * wcs_len;
194         }
195         return rc;
196 }
197
198 asn_enc_rval_t
199 BMPString_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
200                      int ilevel, enum xer_encoder_flags_e flags,
201                      asn_app_consume_bytes_f *cb, void *app_key) {
202     const BMPString_t *st = (const BMPString_t *)sptr;
203         asn_enc_rval_t er = {0,0,0};
204
205         (void)ilevel;
206         (void)flags;
207
208         if(!st || !st->buf)
209                 ASN__ENCODE_FAILED;
210
211         er.encoded = BMPString__dump(st, cb, app_key);
212         if(er.encoded < 0) ASN__ENCODE_FAILED;
213
214         ASN__ENCODED_OK(er);
215 }
216
217 int
218 BMPString_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
219                 asn_app_consume_bytes_f *cb, void *app_key) {
220     const BMPString_t *st = (const BMPString_t *)sptr;
221
222         (void)td;       /* Unused argument */
223         (void)ilevel;   /* Unused argument */
224
225         if(!st || !st->buf)
226                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
227
228         if(BMPString__dump(st, cb, app_key) < 0)
229                 return -1;
230
231         return 0;
232 }
233