+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
- * All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <UTF8String.h>
-
-/*
- * UTF8String basic type description.
- */
-static const ber_tlv_tag_t asn_DEF_UTF8String_tags[] = {
- (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), /* [UNIVERSAL 12] IMPLICIT ...*/
- (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), /* ... OCTET STRING */
-};
-asn_TYPE_operation_t asn_OP_UTF8String = {
- OCTET_STRING_free,
- UTF8String_print,
- OCTET_STRING_compare,
- OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
- OCTET_STRING_encode_der,
- OCTET_STRING_decode_xer_utf8,
- OCTET_STRING_encode_xer_utf8,
-#ifdef ASN_DISABLE_OER_SUPPORT
- 0,
- 0,
-#else
- OCTET_STRING_decode_oer,
- OCTET_STRING_encode_oer,
-#endif /* ASN_DISABLE_OER_SUPPORT */
-#ifdef ASN_DISABLE_PER_SUPPORT
- 0,
- 0,
- 0,
- 0,
-#else
- OCTET_STRING_decode_uper,
- OCTET_STRING_encode_uper,
- OCTET_STRING_decode_aper,
- OCTET_STRING_encode_aper,
-#endif /* ASN_DISABLE_PER_SUPPORT */
- UTF8String_random_fill,
- 0 /* Use generic outmost tag fetcher */
-};
-asn_TYPE_descriptor_t asn_DEF_UTF8String = {
- "UTF8String",
- "UTF8String",
- &asn_OP_UTF8String,
- asn_DEF_UTF8String_tags,
- sizeof(asn_DEF_UTF8String_tags)
- / sizeof(asn_DEF_UTF8String_tags[0]) - 1,
- asn_DEF_UTF8String_tags,
- sizeof(asn_DEF_UTF8String_tags)
- / sizeof(asn_DEF_UTF8String_tags[0]),
- { 0, 0, UTF8String_constraint },
- 0, 0, /* No members */
- 0 /* No specifics */
-};
-
-/*
- * This is the table of length expectations.
- * The second half of this table is only applicable to the long sequences.
- */
-static const int UTF8String_ht[2][16] = {
- { /* 0x0 ... 0x7 */
- /* 0000..0111 */
- 1, 1, 1, 1, 1, 1, 1, 1,
- /* 1000..1011(0), 1100..1101(2), 1110(3), 1111(-1) */
- 0, 0, 0, 0, 2, 2, 3, -1 },
- { /* 0xF0 .. 0xF7 */
- /* 11110000..11110111 */
- 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 6, 6, -1, -1 }
-};
-static const int32_t UTF8String_mv[7] = { 0, 0,
- 0x00000080,
- 0x00000800,
- 0x00010000,
- 0x00200000,
- 0x04000000
-};
-
-/* Internal aliases for return codes */
-#define U8E_TRUNC -1 /* UTF-8 sequence truncated */
-#define U8E_ILLSTART -2 /* Illegal UTF-8 sequence start */
-#define U8E_NOTCONT -3 /* Continuation expectation failed */
-#define U8E_NOTMIN -4 /* Not minimal length encoding */
-#define U8E_EINVAL -5 /* Invalid arguments */
-
-int
-UTF8String_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
- asn_app_constraint_failed_f *ctfailcb, void *app_key) {
- ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
- switch(len) {
- case U8E_EINVAL:
- ASN__CTFAIL(app_key, td, sptr,
- "%s: value not given", td->name);
- break;
- case U8E_TRUNC:
- ASN__CTFAIL(app_key, td, sptr,
- "%s: truncated UTF-8 sequence (%s:%d)",
- td->name, __FILE__, __LINE__);
- break;
- case U8E_ILLSTART:
- ASN__CTFAIL(app_key, td, sptr,
- "%s: UTF-8 illegal start of encoding (%s:%d)",
- td->name, __FILE__, __LINE__);
- break;
- case U8E_NOTCONT:
- ASN__CTFAIL(app_key, td, sptr,
- "%s: UTF-8 not continuation (%s:%d)",
- td->name, __FILE__, __LINE__);
- break;
- case U8E_NOTMIN:
- ASN__CTFAIL(app_key, td, sptr,
- "%s: UTF-8 not minimal sequence (%s:%d)",
- td->name, __FILE__, __LINE__);
- break;
- }
- return (len < 0) ? -1 : 0;
-}
-
-static ssize_t
-UTF8String__process(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
- size_t length;
- uint8_t *buf = st->buf;
- uint8_t *end = buf + st->size;
- uint32_t *dstend = dst + dstlen;
-
- for(length = 0; buf < end; length++) {
- int ch = *buf;
- uint8_t *cend;
- int32_t value;
- int want;
-
- /* Compute the sequence length */
- want = UTF8String_ht[0][ch >> 4];
- switch(want) {
- case -1:
- /* Second half of the table, long sequence */
- want = UTF8String_ht[1][ch & 0x0F];
- if(want != -1) break;
- /* Fall through */
- case 0:
- return U8E_ILLSTART;
- }
-
- /* assert(want >= 1 && want <= 6) */
-
- /* Check character sequence length */
- if(buf + want > end) return U8E_TRUNC;
-
- value = ch & (0xff >> want);
- cend = buf + want;
- for(buf++; buf < cend; buf++) {
- ch = *buf;
- if(ch < 0x80 || ch > 0xbf) return U8E_NOTCONT;
- value = (value << 6) | (ch & 0x3F);
- }
- if(value < UTF8String_mv[want])
- return U8E_NOTMIN;
- if(dst < dstend)
- *dst++ = value; /* Record value */
- }
-
- if(dst < dstend) *dst = 0; /* zero-terminate */
-
- return length;
-}
-
-
-ssize_t
-UTF8String_length(const UTF8String_t *st) {
- if(st && st->buf) {
- return UTF8String__process(st, 0, 0);
- } else {
- return U8E_EINVAL;
- }
-}
-
-size_t
-UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
- if(st && st->buf) {
- ssize_t ret = UTF8String__process(st, dst, dstlen);
- return (ret < 0) ? 0 : ret;
- } else {
- return 0;
- }
-}
-
-int
-UTF8String_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
- asn_app_consume_bytes_f *cb, void *app_key) {
- const UTF8String_t *st = (const UTF8String_t *)sptr;
-
- (void)td; /* Unused argument */
- (void)ilevel; /* Unused argument */
-
- if(st && st->buf) {
- return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
- } else {
- return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
- }
-}
-
-
-/*
- * Biased function for randomizing UTF-8 sequences.
- */
-static size_t
-UTF8String__random_char(uint8_t *b, size_t size) {
- static const struct rnd_value {
- const char *value;
- size_t size;
- } values[] = {{"\0", 1},
- {"\x01", 1},
- {"\x7f", 1},
- {"\xc2\xa2", 2},
- {"\xe2\x82\xac", 3},
- {"\xf0\x90\x8d\x88", 4},
- {"\xf4\x8f\xbf\xbf", 4}};
-
- const struct rnd_value *v;
- size_t max_idx = 0;
-
- switch(size) {
- case 0:
- assert(size != 0);
- return 0;
- case 1:
- max_idx = 2;
- break;
- case 2:
- max_idx = 3;
- break;
- default:
- case 4:
- max_idx = sizeof(values) / sizeof(values[0]) - 1;
- break;
- }
-
- v = &values[asn_random_between(0, max_idx)];
- memcpy(b, v->value, v->size);
- return v->size;
-}
-
-asn_random_fill_result_t
-UTF8String_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
- const asn_encoding_constraints_t *constraints,
- size_t max_length) {
- asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
- asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
- asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
- uint8_t *buf;
- uint8_t *bend;
- uint8_t *b;
- size_t rnd_len;
- size_t idx;
- UTF8String_t *st;
-
- if(max_length == 0 && !*sptr) return result_skipped;
-
- /* Figure out how far we should go */
- rnd_len = OCTET_STRING_random_length_constrained(td, constraints,
- max_length / 4);
-
- buf = CALLOC(4, rnd_len + 1);
- if(!buf) return result_failed;
-
- bend = &buf[4 * rnd_len];
-
- for(b = buf, idx = 0; idx < rnd_len; idx++) {
- b += UTF8String__random_char(b, (bend - b));
- }
- *(uint8_t *)b = 0;
-
- if(*sptr) {
- st = *sptr;
- FREEMEM(st->buf);
- } else {
- st = (OCTET_STRING_t *)(*sptr = CALLOC(1, sizeof(UTF8String_t)));
- if(!st) {
- FREEMEM(buf);
- return result_failed;
- }
- }
-
- st->buf = buf;
- st->size = b - buf;
-
- assert(UTF8String_length(st) == (ssize_t)rnd_len);
-
- return result_ok;
-}