blob: aa248dc081e7aba1614fb39650c0244589a8b7d0 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*-
Lev Walkin9a6f65b2004-10-23 11:20:06 +00002 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
Lev Walkinf15320b2004-06-03 03:38:44 +00003 * Redistribution and modifications are permitted subject to BSD license.
4 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00005#include <asn_internal.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00006#include <BMPString.h>
Lev Walkin9a6f65b2004-10-23 11:20:06 +00007#include <UTF8String.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00008
9/*
10 * BMPString basic type description.
11 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070012static const ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
Lev Walkin188ed2c2004-09-13 08:31:01 +000013 (ASN_TAG_CLASS_UNIVERSAL | (30 << 2)), /* [UNIVERSAL 30] IMPLICIT ...*/
14 (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
Lev Walkinf15320b2004-06-03 03:38:44 +000015};
Lev Walkin3a4689a2006-11-24 11:20:27 +000016static asn_OCTET_STRING_specifics_t asn_DEF_BMPString_specs = {
17 sizeof(BMPString_t),
18 offsetof(BMPString_t, _asn_ctx),
19 ASN_OSUBV_U16 /* 16-bits character */
20};
21static asn_per_constraints_t asn_DEF_BMPString_constraints = {
22 { APC_CONSTRAINED, 16, 16, 0, 65535 },
23 { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
24 0, 0
25};
Lev Walkin5e033762004-09-29 13:26:15 +000026asn_TYPE_descriptor_t asn_DEF_BMPString = {
Lev Walkinf15320b2004-06-03 03:38:44 +000027 "BMPString",
Lev Walkindc06f6b2004-10-20 15:50:55 +000028 "BMPString",
Lev Walkina9cc46e2004-09-22 16:06:28 +000029 OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
30 BMPString_print,
Lev Walkinf15320b2004-06-03 03:38:44 +000031 asn_generic_no_constraint, /* No constraint by default */
Lev Walkin9a6f65b2004-10-23 11:20:06 +000032 OCTET_STRING_decode_ber,
33 OCTET_STRING_encode_der,
34 BMPString_decode_xer, /* Convert from UTF-8 */
35 BMPString_encode_xer, /* Convert to UTF-8 */
Lev Walkin3a4689a2006-11-24 11:20:27 +000036 OCTET_STRING_decode_uper,
37 OCTET_STRING_encode_uper,
Harald Welte0b57b082015-08-30 16:33:07 +020038 OCTET_STRING_decode_aper, /* Aligned PER decoder */
39 OCTET_STRING_encode_aper, /* Aligned PER encoder */
Lev Walkinf15320b2004-06-03 03:38:44 +000040 0, /* Use generic outmost tag fetcher */
Lev Walkin5e033762004-09-29 13:26:15 +000041 asn_DEF_BMPString_tags,
42 sizeof(asn_DEF_BMPString_tags)
43 / sizeof(asn_DEF_BMPString_tags[0]) - 1,
44 asn_DEF_BMPString_tags,
45 sizeof(asn_DEF_BMPString_tags)
46 / sizeof(asn_DEF_BMPString_tags[0]),
Lev Walkin3a4689a2006-11-24 11:20:27 +000047 &asn_DEF_BMPString_constraints,
Lev Walkin449f8322004-08-20 13:23:42 +000048 0, 0, /* No members */
Lev Walkin3a4689a2006-11-24 11:20:27 +000049 &asn_DEF_BMPString_specs
Lev Walkinf15320b2004-06-03 03:38:44 +000050};
51
52/*
53 * BMPString specific contents printer.
54 */
Lev Walkina9cc46e2004-09-22 16:06:28 +000055static ssize_t
56BMPString__dump(const BMPString_t *st,
Lev Walkinf15320b2004-06-03 03:38:44 +000057 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinf15320b2004-06-03 03:38:44 +000058 char scratch[128]; /* Scratchpad buffer */
Lev Walkina9cc46e2004-09-22 16:06:28 +000059 char *p = scratch;
60 ssize_t wrote = 0;
61 uint8_t *ch;
62 uint8_t *end;
Lev Walkinf15320b2004-06-03 03:38:44 +000063
Lev Walkina9cc46e2004-09-22 16:06:28 +000064 ch = st->buf;
65 end = (st->buf + st->size);
66 for(end--; ch < end; ch += 2) {
67 uint16_t wc = (ch[0] << 8) | ch[1]; /* 2 bytes */
Lev Walkinf15320b2004-06-03 03:38:44 +000068 if(sizeof(scratch) - (p - scratch) < 3) {
Lev Walkina9cc46e2004-09-22 16:06:28 +000069 wrote += p - scratch;
70 if(cb(scratch, p - scratch, app_key) < 0)
Lev Walkinf15320b2004-06-03 03:38:44 +000071 return -1;
72 p = scratch;
73 }
74 if(wc < 0x80) {
75 *p++ = (char)wc;
76 } else if(wc < 0x800) {
77 *p++ = 0xc0 | ((wc >> 6));
78 *p++ = 0x80 | ((wc & 0x3f));
79 } else {
80 *p++ = 0xe0 | ((wc >> 12));
81 *p++ = 0x80 | ((wc >> 6) & 0x3f);
82 *p++ = 0x80 | ((wc & 0x3f));
83 }
84 }
85
Lev Walkina9cc46e2004-09-22 16:06:28 +000086 wrote += p - scratch;
87 if(cb(scratch, p - scratch, app_key) < 0)
88 return -1;
89
90 return wrote;
Lev Walkinf15320b2004-06-03 03:38:44 +000091}
Lev Walkina9cc46e2004-09-22 16:06:28 +000092
Lev Walkin9a6f65b2004-10-23 11:20:06 +000093asn_dec_rval_t
94BMPString_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
95 asn_TYPE_descriptor_t *td, void **sptr,
Lev Walkin8c3b8542005-03-10 18:52:02 +000096 const char *opt_mname, const void *buf_ptr, size_t size) {
Lev Walkin9a6f65b2004-10-23 11:20:06 +000097 asn_dec_rval_t rc;
98
99 rc = OCTET_STRING_decode_xer_utf8(opt_codec_ctx, td, sptr, opt_mname,
100 buf_ptr, size);
101 if(rc.code == RC_OK) {
102 /*
103 * Now we have a whole string in UTF-8 format.
104 * Convert it into UCS-2.
105 */
106 uint32_t *wcs;
107 size_t wcs_len;
108 UTF8String_t *st;
109
110 assert(*sptr);
111 st = (UTF8String_t *)*sptr;
112 assert(st->buf);
113 wcs_len = UTF8String_to_wcs(st, 0, 0);
114
115 wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
116 if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
117 rc.code = RC_FAIL;
118 rc.consumed = 0;
119 return rc;
120 } else {
121 wcs[wcs_len] = 0; /* nul-terminate */
122 }
123
124 if(1) {
125 /* Swap byte order and trim encoding to 2 bytes */
126 uint32_t *wc = wcs;
Lev Walkinc7549b12006-09-17 01:27:44 +0000127 uint32_t *wc_end = wcs + wcs_len;
Lev Walkin9a6f65b2004-10-23 11:20:06 +0000128 uint16_t *dstwc = (uint16_t *)wcs;
129 for(; wc < wc_end; wc++, dstwc++) {
130 uint32_t wch = *wc;
131 if(wch > 0xffff) {
132 FREEMEM(wcs);
133 rc.code = RC_FAIL;
134 rc.consumed = 0;
135 return rc;
136 }
137 *((uint8_t *)dstwc + 0) = wch >> 8;
138 *((uint8_t *)dstwc + 1) = wch;
139 }
Lev Walkin529b39d2004-10-23 13:13:19 +0000140 dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
Lev Walkin9a6f65b2004-10-23 11:20:06 +0000141 if(!dstwc) {
142 FREEMEM(wcs);
143 rc.code = RC_FAIL;
144 rc.consumed = 0;
145 return rc;
146 } else {
Lev Walkin3a4689a2006-11-24 11:20:27 +0000147 dstwc[wcs_len] = 0; /* nul-terminate */
Lev Walkind2fab922013-12-07 10:58:10 -0800148 wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
Lev Walkin9a6f65b2004-10-23 11:20:06 +0000149 }
150 }
151
152 FREEMEM(st->buf);
153 st->buf = (uint8_t *)wcs;
154 st->size = 2 * wcs_len;
155 }
156 return rc;
157}
158
Lev Walkina9cc46e2004-09-22 16:06:28 +0000159asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000160BMPString_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000161 int ilevel, enum xer_encoder_flags_e flags,
162 asn_app_consume_bytes_f *cb, void *app_key) {
163 const BMPString_t *st = (const BMPString_t *)sptr;
164 asn_enc_rval_t er;
165
166 (void)ilevel;
167 (void)flags;
168
169 if(!st || !st->buf)
Lev Walkin7c1dc052016-03-14 03:08:15 -0700170 ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000171
172 er.encoded = BMPString__dump(st, cb, app_key);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700173 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000174
Lev Walkin7c1dc052016-03-14 03:08:15 -0700175 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000176}
177
178int
Lev Walkin5e033762004-09-29 13:26:15 +0000179BMPString_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000180 asn_app_consume_bytes_f *cb, void *app_key) {
181 const BMPString_t *st = (const BMPString_t *)sptr;
182
183 (void)td; /* Unused argument */
184 (void)ilevel; /* Unused argument */
185
Lev Walkin8e8078a2004-09-26 13:10:40 +0000186 if(!st || !st->buf)
187 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000188
189 if(BMPString__dump(st, cb, app_key) < 0)
190 return -1;
191
192 return 0;
193}
194