NativeEnumerated.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*-
  2. * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
  3. * Redistribution and modifications are permitted subject to BSD license.
  4. */
  5. /*
  6. * Read the NativeInteger.h for the explanation wrt. differences between
  7. * INTEGER and NativeInteger.
  8. * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
  9. * implementation deals with the standard (machine-specific) representation
  10. * of them instead of using the platform-independent buffer.
  11. */
  12. #include <asn_internal.h>
  13. #include <NativeEnumerated.h>
  14. /*
  15. * NativeEnumerated basic type description.
  16. */
  17. static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
  18. (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
  19. };
  20. asn_TYPE_operation_t asn_OP_NativeEnumerated = {
  21. NativeInteger_free,
  22. NativeInteger_print,
  23. NativeInteger_compare,
  24. NativeInteger_decode_ber,
  25. NativeInteger_encode_der,
  26. NativeInteger_decode_xer,
  27. NativeEnumerated_encode_xer,
  28. #ifdef ASN_DISABLE_OER_SUPPORT
  29. 0,
  30. 0,
  31. #else
  32. NativeEnumerated_decode_oer,
  33. NativeEnumerated_encode_oer,
  34. #endif /* ASN_DISABLE_OER_SUPPORT */
  35. #ifdef ASN_DISABLE_PER_SUPPORT
  36. 0,
  37. 0,
  38. #else
  39. NativeEnumerated_decode_uper,
  40. NativeEnumerated_encode_uper,
  41. #endif /* ASN_DISABLE_PER_SUPPORT */
  42. NativeEnumerated_random_fill,
  43. 0 /* Use generic outmost tag fetcher */
  44. };
  45. asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
  46. "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
  47. "ENUMERATED",
  48. &asn_OP_NativeEnumerated,
  49. asn_DEF_NativeEnumerated_tags,
  50. sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
  51. asn_DEF_NativeEnumerated_tags, /* Same as above */
  52. sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
  53. { 0, 0, asn_generic_no_constraint },
  54. 0, 0, /* No members */
  55. 0 /* No specifics */
  56. };
  57. asn_enc_rval_t
  58. NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
  59. int ilevel, enum xer_encoder_flags_e flags,
  60. asn_app_consume_bytes_f *cb, void *app_key) {
  61. const asn_INTEGER_specifics_t *specs =
  62. (const asn_INTEGER_specifics_t *)td->specifics;
  63. asn_enc_rval_t er;
  64. const long *native = (const long *)sptr;
  65. const asn_INTEGER_enum_map_t *el;
  66. (void)ilevel;
  67. (void)flags;
  68. if(!native) ASN__ENCODE_FAILED;
  69. el = INTEGER_map_value2enum(specs, *native);
  70. if(el) {
  71. er.encoded =
  72. asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
  73. if(er.encoded < 0) ASN__ENCODE_FAILED;
  74. ASN__ENCODED_OK(er);
  75. } else {
  76. ASN_DEBUG(
  77. "ASN.1 forbids dealing with "
  78. "unknown value of ENUMERATED type");
  79. ASN__ENCODE_FAILED;
  80. }
  81. }
  82. asn_dec_rval_t
  83. NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
  84. const asn_TYPE_descriptor_t *td,
  85. const asn_per_constraints_t *constraints,
  86. void **sptr, asn_per_data_t *pd) {
  87. const asn_INTEGER_specifics_t *specs = td->specifics;
  88. asn_dec_rval_t rval = { RC_OK, 0 };
  89. long *native = (long *)*sptr;
  90. const asn_per_constraint_t *ct;
  91. long value;
  92. (void)opt_codec_ctx;
  93. if(constraints) ct = &constraints->value;
  94. else if(td->encoding_constraints.per_constraints)
  95. ct = &td->encoding_constraints.per_constraints->value;
  96. else ASN__DECODE_FAILED; /* Mandatory! */
  97. if(!specs) ASN__DECODE_FAILED;
  98. if(!native) {
  99. native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
  100. if(!native) ASN__DECODE_FAILED;
  101. }
  102. ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
  103. if(ct->flags & APC_EXTENSIBLE) {
  104. int inext = per_get_few_bits(pd, 1);
  105. if(inext < 0) ASN__DECODE_STARVED;
  106. if(inext) ct = 0;
  107. }
  108. if(ct && ct->range_bits >= 0) {
  109. value = per_get_few_bits(pd, ct->range_bits);
  110. if(value < 0) ASN__DECODE_STARVED;
  111. if(value >= (specs->extension
  112. ? specs->extension - 1 : specs->map_count))
  113. ASN__DECODE_FAILED;
  114. } else {
  115. if(!specs->extension)
  116. ASN__DECODE_FAILED;
  117. /*
  118. * X.691, #10.6: normally small non-negative whole number;
  119. */
  120. value = uper_get_nsnnwn(pd);
  121. if(value < 0) ASN__DECODE_STARVED;
  122. value += specs->extension - 1;
  123. if(value >= specs->map_count)
  124. ASN__DECODE_FAILED;
  125. }
  126. *native = specs->value2enum[value].nat_value;
  127. ASN_DEBUG("Decoded %s = %ld", td->name, *native);
  128. return rval;
  129. }
  130. static int
  131. NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
  132. const asn_INTEGER_enum_map_t *a = ap;
  133. const asn_INTEGER_enum_map_t *b = bp;
  134. if(a->nat_value == b->nat_value)
  135. return 0;
  136. if(a->nat_value < b->nat_value)
  137. return -1;
  138. return 1;
  139. }
  140. asn_enc_rval_t
  141. NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
  142. const asn_per_constraints_t *constraints,
  143. const void *sptr, asn_per_outp_t *po) {
  144. const asn_INTEGER_specifics_t *specs =
  145. (const asn_INTEGER_specifics_t *)td->specifics;
  146. asn_enc_rval_t er;
  147. long native, value;
  148. const asn_per_constraint_t *ct;
  149. int inext = 0;
  150. asn_INTEGER_enum_map_t key;
  151. const asn_INTEGER_enum_map_t *kf;
  152. if(!sptr) ASN__ENCODE_FAILED;
  153. if(!specs) ASN__ENCODE_FAILED;
  154. if(constraints) ct = &constraints->value;
  155. else if(td->encoding_constraints.per_constraints)
  156. ct = &td->encoding_constraints.per_constraints->value;
  157. else ASN__ENCODE_FAILED; /* Mandatory! */
  158. ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
  159. er.encoded = 0;
  160. native = *(const long *)sptr;
  161. key.nat_value = native;
  162. kf = bsearch(&key, specs->value2enum, specs->map_count,
  163. sizeof(key), NativeEnumerated__compar_value2enum);
  164. if(!kf) {
  165. ASN_DEBUG("No element corresponds to %ld", native);
  166. ASN__ENCODE_FAILED;
  167. }
  168. value = kf - specs->value2enum;
  169. if(ct->range_bits >= 0) {
  170. int cmpWith = specs->extension
  171. ? specs->extension - 1 : specs->map_count;
  172. if(value >= cmpWith)
  173. inext = 1;
  174. }
  175. if(ct->flags & APC_EXTENSIBLE) {
  176. if(per_put_few_bits(po, inext, 1))
  177. ASN__ENCODE_FAILED;
  178. if(inext) ct = 0;
  179. } else if(inext) {
  180. ASN__ENCODE_FAILED;
  181. }
  182. if(ct && ct->range_bits >= 0) {
  183. if(per_put_few_bits(po, value, ct->range_bits))
  184. ASN__ENCODE_FAILED;
  185. ASN__ENCODED_OK(er);
  186. }
  187. if(!specs->extension)
  188. ASN__ENCODE_FAILED;
  189. /*
  190. * X.691, #10.6: normally small non-negative whole number;
  191. */
  192. ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
  193. value, specs->extension, inext,
  194. value - (inext ? (specs->extension - 1) : 0));
  195. if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
  196. ASN__ENCODE_FAILED;
  197. ASN__ENCODED_OK(er);
  198. }