aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-07-20 00:03:44 +0200
committerHarald Welte <laforge@gnumonks.org>2010-07-20 00:03:44 +0200
commitec0e217b0647eb798576a7d3366b39c159c00624 (patch)
tree88404309798e2fac2844b4e76224b6ad1d7c5375
parentb1e3ee75318536dac0a91817c5e4d35d61893ba6 (diff)
Update to asn1c official repository svn trunk r1409
-rw-r--r--include/asn1c/INTEGER.h4
-rw-r--r--include/asn1c/Makefile.am2
-rw-r--r--include/asn1c/NativeReal.h4
-rw-r--r--include/asn1c/OCTET_STRING.h8
-rw-r--r--include/asn1c/REAL.h2
-rw-r--r--include/asn1c/asn_internal.h20
-rw-r--r--include/asn1c/asn_system.h29
-rw-r--r--include/asn1c/ber_decoder.h1
-rw-r--r--include/asn1c/der_encoder.h1
-rw-r--r--include/asn1c/per_decoder.h14
-rw-r--r--include/asn1c/per_encoder.h24
-rw-r--r--include/asn1c/per_opentype.h22
-rw-r--r--include/asn1c/per_support.h31
-rw-r--r--src/ANY.c2
-rw-r--r--src/BIT_STRING.c9
-rw-r--r--src/BMPString.c19
-rw-r--r--src/BOOLEAN.c2
-rw-r--r--src/GeneralString.c3
-rw-r--r--src/GeneralizedTime.c23
-rw-r--r--src/GraphicString.c3
-rw-r--r--src/IA5String.c14
-rw-r--r--src/INTEGER.c157
-rw-r--r--src/ISO646String.c11
-rw-r--r--src/Makefile.am2
-rw-r--r--src/NativeEnumerated.c11
-rw-r--r--src/NativeInteger.c32
-rw-r--r--src/NativeReal.c73
-rw-r--r--src/NumericString.c36
-rw-r--r--src/OBJECT_IDENTIFIER.c10
-rw-r--r--src/OCTET_STRING.c451
-rw-r--r--src/ObjectDescriptor.c3
-rw-r--r--src/PrintableString.c68
-rw-r--r--src/REAL.c32
-rw-r--r--src/RELATIVE-OID.c4
-rw-r--r--src/T61String.c3
-rw-r--r--src/TeletexString.c141
-rw-r--r--src/UTCTime.c12
-rw-r--r--src/UTF8String.c13
-rw-r--r--src/UniversalString.c17
-rw-r--r--src/VideotexString.c3
-rw-r--r--src/VisibleString.c16
-rw-r--r--src/constr_CHOICE.c53
-rw-r--r--src/constr_SEQUENCE.c244
-rw-r--r--src/constr_SET.c12
-rw-r--r--src/constr_SET_OF.c15
-rw-r--r--src/per_decoder.c38
-rw-r--r--src/per_encoder.c136
-rw-r--r--src/per_opentype.c373
-rw-r--r--src/per_support.c133
49 files changed, 1962 insertions, 374 deletions
diff --git a/include/asn1c/INTEGER.h b/include/asn1c/INTEGER.h
index 62832b1..8411bfc 100644
--- a/include/asn1c/INTEGER.h
+++ b/include/asn1c/INTEGER.h
@@ -30,6 +30,8 @@ typedef struct asn_INTEGER_specifics_s {
int map_count; /* Elements in either map */
int extension; /* This map is extensible */
int strict_enumeration; /* Enumeration set is fixed */
+ int field_width; /* Size of native integer */
+ int field_unsigned; /* Signed=0, unsigned=1 */
} asn_INTEGER_specifics_t;
asn_struct_print_f INTEGER_print;
@@ -51,7 +53,9 @@ per_type_encoder_f INTEGER_encode_uper;
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
*/
int asn_INTEGER2long(const INTEGER_t *i, long *l);
+int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
int asn_long2INTEGER(INTEGER_t *i, long l);
+int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
/*
* Convert the integer value into the corresponding enumeration map entry.
diff --git a/include/asn1c/Makefile.am b/include/asn1c/Makefile.am
index 81b654d..899ad78 100644
--- a/include/asn1c/Makefile.am
+++ b/include/asn1c/Makefile.am
@@ -1,3 +1,3 @@
asn1cdir = $(includedir)/asn1c
-asn1c_HEADERS = ANY.h asn_application.h asn_codecs.h asn_codecs_prim.h asn_internal.h asn_SEQUENCE_OF.h asn_SET_OF.h asn_system.h ber_decoder.h ber_tlv_length.h ber_tlv_tag.h BIT_STRING.h BMPString.h BOOLEAN.h constraints.h constr_CHOICE.h constr_SEQUENCE.h constr_SEQUENCE_OF.h constr_SET.h constr_SET_OF.h constr_TYPE.h der_encoder.h ENUMERATED.h GeneralizedTime.h GeneralString.h GraphicString.h IA5String.h INTEGER.h ISO646String.h NativeEnumerated.h NativeInteger.h NativeReal.h NULL.h NumericString.h ObjectDescriptor.h OBJECT_IDENTIFIER.h OCTET_STRING.h per_decoder.h per_encoder.h per_support.h PrintableString.h REAL.h RELATIVE-OID.h T61String.h TeletexString.h UniversalString.h UTCTime.h UTF8String.h VideotexString.h VisibleString.h xer_decoder.h xer_encoder.h xer_support.h
+asn1c_HEADERS = ANY.h asn_application.h asn_codecs.h asn_codecs_prim.h asn_internal.h asn_SEQUENCE_OF.h asn_SET_OF.h asn_system.h ber_decoder.h ber_tlv_length.h ber_tlv_tag.h BIT_STRING.h BMPString.h BOOLEAN.h constraints.h constr_CHOICE.h constr_SEQUENCE.h constr_SEQUENCE_OF.h constr_SET.h constr_SET_OF.h constr_TYPE.h der_encoder.h ENUMERATED.h GeneralizedTime.h GeneralString.h GraphicString.h IA5String.h INTEGER.h ISO646String.h NativeEnumerated.h NativeInteger.h NativeReal.h NULL.h NumericString.h ObjectDescriptor.h OBJECT_IDENTIFIER.h OCTET_STRING.h per_decoder.h per_encoder.h per_support.h PrintableString.h REAL.h RELATIVE-OID.h T61String.h TeletexString.h UniversalString.h UTCTime.h UTF8String.h VideotexString.h VisibleString.h xer_decoder.h xer_encoder.h xer_support.h per_opentype.h
diff --git a/include/asn1c/NativeReal.h b/include/asn1c/NativeReal.h
index 1f5266c..68a81d9 100644
--- a/include/asn1c/NativeReal.h
+++ b/include/asn1c/NativeReal.h
@@ -6,7 +6,7 @@
* This type differs from the standard REAL in that it is modelled using
* the fixed machine type (double), so it can hold only values of
* limited precision. There is no explicit type (i.e., NativeReal_t).
- * Use of this type is normally enabled by -fnative-integers.
+ * Use of this type is normally enabled by -fnative-types.
*/
#ifndef ASN_TYPE_NativeReal_H
#define ASN_TYPE_NativeReal_H
@@ -25,6 +25,8 @@ ber_type_decoder_f NativeReal_decode_ber;
der_type_encoder_f NativeReal_encode_der;
xer_type_decoder_f NativeReal_decode_xer;
xer_type_encoder_f NativeReal_encode_xer;
+per_type_decoder_f NativeReal_decode_uper;
+per_type_encoder_f NativeReal_encode_uper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/OCTET_STRING.h b/include/asn1c/OCTET_STRING.h
index 5150161..8df9a18 100644
--- a/include/asn1c/OCTET_STRING.h
+++ b/include/asn1c/OCTET_STRING.h
@@ -70,7 +70,13 @@ typedef struct asn_OCTET_STRING_specifics_s {
int struct_size; /* Size of the structure */
int ctx_offset; /* Offset of the asn_struct_ctx_t member */
- int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */
+ enum asn_OS_Subvariant {
+ ASN_OSUBV_ANY, /* The open type (ANY) */
+ ASN_OSUBV_BIT, /* BIT STRING */
+ ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */
+ ASN_OSUBV_U16, /* 16-bit character (BMPString) */
+ ASN_OSUBV_U32 /* 32-bit character (UniversalString) */
+ } subvariant;
} asn_OCTET_STRING_specifics_t;
#ifdef __cplusplus
diff --git a/include/asn1c/REAL.h b/include/asn1c/REAL.h
index 28ccf28..af3e84c 100644
--- a/include/asn1c/REAL.h
+++ b/include/asn1c/REAL.h
@@ -19,6 +19,8 @@ extern asn_TYPE_descriptor_t asn_DEF_REAL;
asn_struct_print_f REAL_print;
xer_type_decoder_f REAL_decode_xer;
xer_type_encoder_f REAL_encode_xer;
+per_type_decoder_f REAL_decode_uper;
+per_type_encoder_f REAL_encode_uper;
/***********************************
* Some handy conversion routines. *
diff --git a/include/asn1c/asn_internal.h b/include/asn1c/asn_internal.h
index 67f055a..249d7ef 100644
--- a/include/asn1c/asn_internal.h
+++ b/include/asn1c/asn_internal.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -20,7 +20,7 @@ extern "C" {
#endif
/* Environment version might be used to avoid running with the old library */
-#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */
+#define ASN1C_ENVIRONMENT_VERSION 922 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */
#define CALLOC(nmemb, size) calloc(nmemb, size)
@@ -35,10 +35,17 @@ int get_asn1c_environment_version(void); /* Run-time version */
#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */
#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */
#ifdef __GNUC__
-#define ASN_DEBUG(fmt, args...) do { \
- fprintf(stderr, fmt, ##args); \
- fprintf(stderr, " (%s:%d)\n", \
- __FILE__, __LINE__); \
+#ifdef ASN_THREAD_SAFE
+#define asn_debug_indent 0
+#else /* !ASN_THREAD_SAFE */
+int asn_debug_indent;
+#endif /* ASN_THREAD_SAFE */
+#define ASN_DEBUG(fmt, args...) do { \
+ int adi = asn_debug_indent; \
+ while(adi--) fprintf(stderr, " "); \
+ fprintf(stderr, fmt, ##args); \
+ fprintf(stderr, " (%s:%d)\n", \
+ __FILE__, __LINE__); \
} while(0)
#else /* !__GNUC__ */
void ASN_DEBUG_f(const char *fmt, ...);
@@ -70,6 +77,7 @@ static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
int __nl = ((nl) != 0); \
int __i; \
if(__nl) _ASN_CALLBACK("\n", 1); \
+ if(__level < 0) __level = 0; \
for(__i = 0; __i < __level; __i++) \
_ASN_CALLBACK(" ", 4); \
er.encoded += __nl + 4 * __level; \
diff --git a/include/asn1c/asn_system.h b/include/asn1c/asn_system.h
index d7ebdaa..0a9b092 100644
--- a/include/asn1c/asn_system.h
+++ b/include/asn1c/asn_system.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2004, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
@@ -16,20 +17,27 @@
#include <stdlib.h> /* For *alloc(3) */
#include <string.h> /* For memcpy(3) */
#include <sys/types.h> /* For size_t */
+#include <limits.h> /* For LONG_MAX */
#include <stdarg.h> /* For va_start */
#include <stddef.h> /* for offsetof and ptrdiff_t */
#ifdef WIN32
#include <malloc.h>
-#include <stdint.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
+/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
+#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \
+ | (((l) << 16) & 0xff0000) \
+ | (((l) << 8) & 0xff00) \
+ | ((l) & 0xff))
+
#ifdef _MSC_VER /* MSVS.Net */
#ifndef __cplusplus
#define inline __inline
#endif
+#ifndef ASSUMESTDTYPES /* Standard types have been defined elsewhere */
#define ssize_t SSIZE_T
typedef char int8_t;
typedef short int16_t;
@@ -37,6 +45,7 @@ typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
+#endif /* ASSUMESTDTYPES */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <float.h>
@@ -44,6 +53,8 @@ typedef unsigned int uint32_t;
#define finite _finite
#define copysign _copysign
#define ilogb _logb
+#else /* !_MSC_VER */
+#include <stdint.h>
#endif /* _MSC_VER */
#else /* !WIN32 */
@@ -74,6 +85,9 @@ typedef unsigned int uint32_t;
#endif /* defined(sun) */
#endif
+#include <netinet/in.h> /* for ntohl() */
+#define sys_ntohl(foo) ntohl(foo)
+
#endif /* defined(__vxworks) */
#endif /* WIN32 */
@@ -82,12 +96,23 @@ typedef unsigned int uint32_t;
#ifndef GCC_PRINTFLIKE
#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
#endif
+#ifndef GCC_NOTUSED
+#define GCC_NOTUSED __attribute__((unused))
+#endif
#else
#ifndef GCC_PRINTFLIKE
#define GCC_PRINTFLIKE(fmt,var) /* nothing */
#endif
+#ifndef GCC_NOTUSED
+#define GCC_NOTUSED
+#endif
#endif
+/* Figure out if thread safety is requested */
+#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))
+#define ASN_THREAD_SAFE
+#endif /* Thread safety */
+
#ifndef offsetof /* If not defined by <stddef.h> */
#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
#endif /* offsetof */
diff --git a/include/asn1c/ber_decoder.h b/include/asn1c/ber_decoder.h
index 768133b..9fe2e89 100644
--- a/include/asn1c/ber_decoder.h
+++ b/include/asn1c/ber_decoder.h
@@ -17,6 +17,7 @@ struct asn_codec_ctx_s; /* Forward declaration */
/*
* The BER decoder of any type.
* This function may be invoked directly from the application.
+ * The der_encode() function (der_encoder.h) is an opposite to ber_decode().
*/
asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
diff --git a/include/asn1c/der_encoder.h b/include/asn1c/der_encoder.h
index 4e2fb06..61431c6 100644
--- a/include/asn1c/der_encoder.h
+++ b/include/asn1c/der_encoder.h
@@ -15,6 +15,7 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* The DER encoder of any type. May be invoked by the application.
+ * The ber_decode() function (ber_decoder.h) is an opposite of der_encode().
*/
asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
diff --git a/include/asn1c/per_decoder.h b/include/asn1c/per_decoder.h
index 26aaf59..8397a54 100644
--- a/include/asn1c/per_decoder.h
+++ b/include/asn1c/per_decoder.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2005, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_DECODER_H_
@@ -15,7 +15,19 @@ extern "C" {
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
+ * Unaligned PER decoder of a "complete encoding" as per X.691#10.1.
+ * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
+ */
+asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
+ struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
+ void **struct_ptr, /* Pointer to a target structure's pointer */
+ const void *buffer, /* Data to be decoded */
+ size_t size /* Size of data buffer */
+ );
+
+/*
* Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This call returns the number of BITS read from the stream. Beware.
*/
asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
diff --git a/include/asn1c/per_encoder.h b/include/asn1c/per_encoder.h
index 9ac130b..95a6506 100644
--- a/include/asn1c/per_encoder.h
+++ b/include/asn1c/per_encoder.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2006, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_ENCODER_H_
@@ -16,6 +16,9 @@ struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This function returns the number of encoded bits in the .encoded
+ * field of the return value. Use the following formula to convert to bytes:
+ * bytes = ((.encoded + 7) / 8)
*/
asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
@@ -23,7 +26,11 @@ asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *app_key /* Arbitrary callback argument */
);
-/* A variant of uper_encode() which encodes data into the existing buffer */
+/*
+ * A variant of uper_encode() which encodes data into the existing buffer
+ * WARNING: This function returns the number of encoded bits in the .encoded
+ * field of the return value.
+ */
asn_enc_rval_t uper_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
@@ -31,6 +38,19 @@ asn_enc_rval_t uper_encode_to_buffer(
size_t buffer_size /* Initial buffer size (max) */
);
+/*
+ * A variant of uper_encode_to_buffer() which allocates buffer itself.
+ * Returns the number of bytes in the buffer or -1 in case of failure.
+ * WARNING: This function produces a "Production of the complete encoding",
+ * with length of at least one octet. Contrast this to precise bit-packing
+ * encoding of uper_encode() and uper_encode_to_buffer().
+ */
+ssize_t uper_encode_to_new_buffer(
+ struct asn_TYPE_descriptor_s *type_descriptor,
+ asn_per_constraints_t *constraints,
+ void *struct_ptr, /* Structure to be encoded */
+ void **buffer_r /* Buffer allocated and returned */
+);
/*
* Type of the generic PER encoder function.
diff --git a/include/asn1c/per_opentype.h b/include/asn1c/per_opentype.h
new file mode 100644
index 0000000..facfaa6
--- /dev/null
+++ b/include/asn1c/per_opentype.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _PER_OPENTYPE_H_
+#define _PER_OPENTYPE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
+
+int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
+
+int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PER_OPENTYPE_H_ */
diff --git a/include/asn1c/per_support.h b/include/asn1c/per_support.h
index 420bb83..7cb1a0c 100644
--- a/include/asn1c/per_support.h
+++ b/include/asn1c/per_support.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_SUPPORT_H_
@@ -29,15 +30,20 @@ typedef struct asn_per_constraint_s {
typedef struct asn_per_constraints_s {
asn_per_constraint_t value;
asn_per_constraint_t size;
+ int (*value2code)(unsigned int value);
+ int (*code2value)(unsigned int code);
} asn_per_constraints_t;
/*
* This structure describes a position inside an incoming PER bit stream.
*/
typedef struct asn_per_data_s {
- const uint8_t *buffer; /* Pointer to the octet stream */
- size_t nboff; /* Bit offset to the meaningful bit */
- size_t nbits; /* Number of bits in the stream */
+ const uint8_t *buffer; /* Pointer to the octet stream */
+ size_t nboff; /* Bit offset to the meaningful bit */
+ size_t nbits; /* Number of bits in the stream */
+ size_t moved; /* Number of bits moved through this bit stream */
+ int (*refill)(struct asn_per_data_s *);
+ void *refill_key;
} asn_per_data_t;
/*
@@ -47,6 +53,9 @@ typedef struct asn_per_data_s {
*/
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
+/* Undo the immediately preceeding "get_few_bits" operation */
+void per_get_undo(asn_per_data_t *per_data, int get_nbits);
+
/*
* Extract a large number of bits from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
@@ -63,10 +72,18 @@ ssize_t uper_get_length(asn_per_data_t *pd,
int *repeat);
/*
+ * Get the normally small length "n".
+ */
+ssize_t uper_get_nslength(asn_per_data_t *pd);
+
+/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
+/* Non-thread-safe debugging function, don't use it */
+char *per_data_string(asn_per_data_t *pd);
+
/*
* This structure supports forming PER output.
*/
@@ -94,6 +111,12 @@ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
/*
+ * Put the normally small length "n" to the Unaligned PER stream.
+ * Returns 0 or -1.
+ */
+int uper_put_nslength(asn_per_outp_t *po, size_t length);
+
+/*
* Put the normally small non-negative whole number.
*/
int uper_put_nsnnwn(asn_per_outp_t *po, int n);
diff --git a/src/ANY.c b/src/ANY.c
index 612238b..0ad60d0 100644
--- a/src/ANY.c
+++ b/src/ANY.c
@@ -9,7 +9,7 @@
static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs = {
sizeof(ANY_t),
offsetof(ANY_t, _asn_ctx),
- 2 /* Special indicator that this is an ANY type */
+ ASN_OSUBV_ANY
};
asn_TYPE_descriptor_t asn_DEF_ANY = {
"ANY",
diff --git a/src/BIT_STRING.c b/src/BIT_STRING.c
index 6469d4f..9b98271 100644
--- a/src/BIT_STRING.c
+++ b/src/BIT_STRING.c
@@ -15,7 +15,7 @@ static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
sizeof(BIT_STRING_t),
offsetof(BIT_STRING_t, _asn_ctx),
- 1, /* Special indicator that this is a BIT STRING type */
+ ASN_OSUBV_BIT
};
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
"BIT STRING",
@@ -50,14 +50,15 @@ BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
if(st && st->buf) {
- if(st->size == 1 && st->bits_unused) {
- _ASN_CTFAIL(app_key, td,
+ if((st->size == 0 && st->bits_unused)
+ || st->bits_unused < 0 || st->bits_unused > 7) {
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: invalid padding byte (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
diff --git a/src/BMPString.c b/src/BMPString.c
index d6a9308..072bd07 100644
--- a/src/BMPString.c
+++ b/src/BMPString.c
@@ -13,6 +13,16 @@ static ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (30 << 2)), /* [UNIVERSAL 30] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_OCTET_STRING_specifics_t asn_DEF_BMPString_specs = {
+ sizeof(BMPString_t),
+ offsetof(BMPString_t, _asn_ctx),
+ ASN_OSUBV_U16 /* 16-bits character */
+};
+static asn_per_constraints_t asn_DEF_BMPString_constraints = {
+ { APC_CONSTRAINED, 16, 16, 0, 65535 },
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_BMPString = {
"BMPString",
"BMPString",
@@ -23,7 +33,8 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
OCTET_STRING_encode_der,
BMPString_decode_xer, /* Convert from UTF-8 */
BMPString_encode_xer, /* Convert to UTF-8 */
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
@@ -31,9 +42,9 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
/ sizeof(asn_DEF_BMPString_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_BMPString_constraints,
0, 0, /* No members */
- 0 /* No specifics */
+ &asn_DEF_BMPString_specs
};
/*
@@ -131,7 +142,7 @@ BMPString_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
rc.consumed = 0;
return rc;
} else {
- dstwc[2 * wcs_len] = 0;
+ dstwc[wcs_len] = 0; /* nul-terminate */
wcs = (uint32_t *)dstwc;
}
}
diff --git a/src/BOOLEAN.c b/src/BOOLEAN.c
index bb4697c..2c2bbcf 100644
--- a/src/BOOLEAN.c
+++ b/src/BOOLEAN.c
@@ -257,7 +257,7 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
switch(per_get_few_bits(pd, 1)) {
case 1: *st = 1; break;
case 0: *st = 0; break;
- case -1: default: _ASN_DECODE_FAILED;
+ case -1: default: _ASN_DECODE_STARVED;
}
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
diff --git a/src/GeneralString.c b/src/GeneralString.c
index 55bb664..01b606b 100644
--- a/src/GeneralString.c
+++ b/src/GeneralString.c
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralString_tags,
sizeof(asn_DEF_GeneralString_tags)
diff --git a/src/GeneralizedTime.c b/src/GeneralizedTime.c
index f864d83..9d683ef 100644
--- a/src/GeneralizedTime.c
+++ b/src/GeneralizedTime.c
@@ -105,10 +105,13 @@ static long GMTOFF(struct tm a){
tzold = getenv("TZ"); \
if(tzold) { \
size_t tzlen = strlen(tzold); \
- if(tzlen < sizeof(tzoldbuf)) \
+ if(tzlen < sizeof(tzoldbuf)) { \
tzold = memcpy(tzoldbuf, tzold, tzlen + 1); \
- else \
- tzold = strdup(tzold); /* Ignore error */ \
+ } else { \
+ char *dupptr = tzold; \
+ tzold = MALLOC(tzlen + 1); \
+ if(tzold) memcpy(tzold, dupptr, tzlen + 1); \
+ } \
setenv("TZ", "UTC", 1); \
} \
tzset(); \
@@ -147,6 +150,11 @@ static ber_tlv_tag_t asn_DEF_GeneralizedTime_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_per_constraints_t asn_DEF_GeneralizedTime_constraints = {
+ { APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
"GeneralizedTime",
"GeneralizedTime",
@@ -157,7 +165,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
GeneralizedTime_encode_der,
OCTET_STRING_decode_xer_utf8,
GeneralizedTime_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
@@ -165,7 +174,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
/ sizeof(asn_DEF_GeneralizedTime_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_GeneralizedTime_constraints,
0, 0, /* No members */
0 /* No specifics */
};
@@ -184,7 +193,7 @@ GeneralizedTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
errno = EPERM; /* Just an unlikely error code */
tloc = asn_GT2time(st, 0, 0);
if(tloc == -1 && errno != EPERM) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: Invalid time format: %s (%s:%d)",
td->name, strerror(errno), __FILE__, __LINE__);
return -1;
@@ -657,7 +666,7 @@ asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value,
int ret;
gmtoff %= 86400;
ret = snprintf(p, buf_size - size, "%+03ld%02ld",
- gmtoff / 3600, labs(gmtoff % 3600));
+ gmtoff / 3600, labs(gmtoff % 3600) / 60);
if(ret != 5) {
FREEMEM(buf);
errno = EINVAL;
diff --git a/src/GraphicString.c b/src/GraphicString.c
index 135cd73..7d59d52 100644
--- a/src/GraphicString.c
+++ b/src/GraphicString.c
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_GraphicString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
- 0, 0,
+ OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags)
diff --git a/src/IA5String.c b/src/IA5String.c
index 5c000b0..02ecd3e 100644
--- a/src/IA5String.c
+++ b/src/IA5String.c
@@ -12,6 +12,11 @@ static ber_tlv_tag_t asn_DEF_IA5String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), /* [UNIVERSAL 22] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_per_constraints_t asn_DEF_IA5String_constraints = {
+ { APC_CONSTRAINED, 7, 7, 0, 0x7f }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_IA5String = {
"IA5String",
"IA5String",
@@ -22,7 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
@@ -30,7 +36,7 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
/ sizeof(asn_DEF_IA5String_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_IA5String_constraints,
0, 0, /* No members */
0 /* No specifics */
};
@@ -49,7 +55,7 @@ IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
*/
for(; buf < end; buf++) {
if(*buf > 0x7F) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value byte %ld out of range: "
"%d > 127 (%s:%d)",
td->name,
@@ -60,7 +66,7 @@ IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
}
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
diff --git a/src/INTEGER.c b/src/INTEGER.c
index 9c8b9ed..f016131 100644
--- a/src/INTEGER.c
+++ b/src/INTEGER.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -158,7 +158,9 @@ INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_by
} else {
scrsize = sizeof(scratch);
scr = scratch;
- ret = snprintf(scr, scrsize, "%ld", accum);
+ ret = snprintf(scr, scrsize,
+ (specs && specs->field_unsigned)
+ ?"%lu":"%ld", accum);
}
assert(ret > 0 && (size_t)ret < scrsize);
return (cb(scr, ret, app_key) < 0) ? -1 : ret;
@@ -334,8 +336,8 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
} state = ST_SKIPSPACE;
if(chunk_size)
- ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x",
- chunk_size, *lstart, lstop[-1]);
+ ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
+ (long)chunk_size, *lstart, lstop[-1]);
/*
* We may have received a tag here. It will be processed inline.
@@ -384,7 +386,7 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
case ST_HEXDIGIT2:
value += (lv - 0x30);
state = ST_HEXCOLON;
- st->buf[st->size++] = value;
+ st->buf[st->size++] = (uint8_t)value;
continue;
case ST_HEXCOLON:
return XPBD_BROKEN_ENCODING;
@@ -467,7 +469,7 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
case ST_HEXDIGIT2:
value += lv - ((lv < 0x61) ? 0x41 : 0x61);
value += 10;
- st->buf[st->size++] = value;
+ st->buf[st->size++] = (uint8_t)value;
state = ST_HEXCOLON;
continue;
case ST_DIGITS:
@@ -554,6 +556,7 @@ INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
asn_dec_rval_t
INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
INTEGER_t *st = (INTEGER_t *)*sptr;
asn_per_constraint_t *ct;
@@ -576,6 +579,8 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
FREEMEM(st->buf);
+ st->buf = 0;
+ st->size = 0;
if(ct) {
if(ct->flags & APC_SEMI_CONSTRAINED) {
st->buf = (uint8_t *)CALLOC(1, 2);
@@ -586,11 +591,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
st->buf = (uint8_t *)MALLOC(1 + size + 1);
if(!st->buf) _ASN_DECODE_FAILED;
st->size = size;
- } else {
- st->size = 0;
}
- } else {
- st->size = 0;
}
/* X.691, #12.2.2 */
@@ -598,12 +599,24 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* #10.5.6 */
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
if(ct->range_bits >= 0) {
- long value = per_get_few_bits(pd, ct->range_bits);
- if(value < 0) _ASN_DECODE_STARVED;
+ long value;
+ if(ct->range_bits == 32) {
+ long lhalf;
+ value = per_get_few_bits(pd, 16);
+ if(value < 0) _ASN_DECODE_STARVED;
+ lhalf = per_get_few_bits(pd, 16);
+ if(lhalf < 0) _ASN_DECODE_STARVED;
+ value = (value << 16) | lhalf;
+ } else {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ }
ASN_DEBUG("Got value %ld + low %ld",
value, ct->lower_bound);
value += ct->lower_bound;
- if(asn_long2INTEGER(st, value))
+ if((specs && specs->field_unsigned)
+ ? asn_ulong2INTEGER(st, value)
+ : asn_long2INTEGER(st, value))
_ASN_DECODE_FAILED;
return rval;
}
@@ -649,6 +662,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_enc_rval_t
INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
INTEGER_t *st = (INTEGER_t *)sptr;
const uint8_t *buf;
@@ -665,21 +679,41 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
if(ct) {
int inext = 0;
- if(asn_INTEGER2long(st, &value))
- _ASN_ENCODE_FAILED;
- /* Check proper range */
- if(ct->flags & APC_SEMI_CONSTRAINED) {
- if(value < ct->lower_bound)
- inext = 1;
- } else if(ct->range_bits >= 0) {
- if(value < ct->lower_bound
- || value > ct->upper_bound)
- inext = 1;
+ if(specs && specs->field_unsigned) {
+ unsigned long uval;
+ if(asn_INTEGER2ulong(st, &uval))
+ _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(uval < (unsigned long)ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(uval < (unsigned long)ct->lower_bound
+ || uval > (unsigned long)ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
+ uval, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ value = uval;
+ } else {
+ if(asn_INTEGER2long(st, &value))
+ _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(value < ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(value < ct->lower_bound
+ || value > ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
+ value, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
}
- ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
- value, st->buf[0], st->size,
- ct->lower_bound, ct->upper_bound,
- inext ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
_ASN_ENCODE_FAILED;
@@ -695,9 +729,17 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
/* #10.5.6 */
ASN_DEBUG("Encoding integer with range %d bits",
ct->range_bits);
- if(per_put_few_bits(po, value - ct->lower_bound,
+ if(ct->range_bits == 32) {
+ /* TODO: extend to >32 bits */
+ long v = value - ct->lower_bound;
+ if(per_put_few_bits(po, v >> 1, 31)
+ || per_put_few_bits(po, v, 1))
+ _ASN_ENCODE_FAILED;
+ } else {
+ if(per_put_few_bits(po, value - ct->lower_bound,
ct->range_bits))
- _ASN_ENCODE_FAILED;
+ _ASN_ENCODE_FAILED;
+ }
_ASN_ENCODED_OK(er);
}
@@ -780,6 +822,63 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
}
int
+asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
+ uint8_t *b, *end;
+ unsigned long l;
+ size_t size;
+
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ b = iptr->buf;
+ size = iptr->size;
+ end = b + size;
+
+ /* If all extra leading bytes are zeroes, ignore them */
+ for(; size > sizeof(unsigned long); b++, size--) {
+ if(*b) {
+ /* Value won't fit unsigned long */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Conversion engine */
+ for(l = 0; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
+asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
+ uint8_t *buf;
+ uint8_t *end;
+ uint8_t *b;
+ int shr;
+
+ if(value <= LONG_MAX)
+ return asn_long2INTEGER(st, value);
+
+ buf = (uint8_t *)MALLOC(1 + sizeof(value));
+ if(!buf) return -1;
+
+ end = buf + (sizeof(value) + 1);
+ buf[0] = 0;
+ for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
+ *b = (uint8_t)(value >> shr);
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = 1 + sizeof(value);
+
+ return 0;
+}
+
+int
asn_long2INTEGER(INTEGER_t *st, long value) {
uint8_t *buf, *bp;
uint8_t *p;
diff --git a/src/ISO646String.c b/src/ISO646String.c
index d164aa7..d6ded0e 100644
--- a/src/ISO646String.c
+++ b/src/ISO646String.c
@@ -12,6 +12,11 @@ static ber_tlv_tag_t asn_DEF_ISO646String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_per_constraints_t asn_DEF_ISO646String_constraints = {
+ { APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_ISO646String = {
"ISO646String",
"ISO646String",
@@ -22,7 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
@@ -30,8 +36,7 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
/ sizeof(asn_DEF_ISO646String_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_ISO646String_constraints,
0, 0, /* No members */
0 /* No specifics */
};
-
diff --git a/src/Makefile.am b/src/Makefile.am
index 4451f65..dcad645 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,5 +8,5 @@ AM_CFLAGS = -fPIC -Wall
lib_LTLIBRARIES = libasn1c.la
-libasn1c_la_SOURCES = ANY.c constraints.c GeneralizedTime.c NumericString.c T61String.c asn_codecs_prim.c constr_CHOICE.c GeneralString.c ObjectDescriptor.c TeletexString.c asn_SEQUENCE_OF.c constr_SEQUENCE.c GraphicString.c OBJECT_IDENTIFIER.c UniversalString.c asn_SET_OF.c constr_SEQUENCE_OF.c IA5String.c OCTET_STRING.c UTCTime.c ber_decoder.c constr_SET.c INTEGER.c per_decoder.c UTF8String.c ber_tlv_length.c constr_SET_OF.c ISO646String.c per_encoder.c VideotexString.c ber_tlv_tag.c constr_TYPE.c NativeEnumerated.c per_support.c VisibleString.c BIT_STRING.c NativeInteger.c PrintableString.c xer_decoder.c BMPString.c der_encoder.c NativeReal.c REAL.c xer_encoder.c BOOLEAN.c ENUMERATED.c NULL.c RELATIVE-OID.c xer_support.c
+libasn1c_la_SOURCES = ANY.c constraints.c GeneralizedTime.c NumericString.c T61String.c asn_codecs_prim.c constr_CHOICE.c GeneralString.c ObjectDescriptor.c TeletexString.c asn_SEQUENCE_OF.c constr_SEQUENCE.c GraphicString.c OBJECT_IDENTIFIER.c UniversalString.c asn_SET_OF.c constr_SEQUENCE_OF.c IA5String.c OCTET_STRING.c UTCTime.c ber_decoder.c constr_SET.c INTEGER.c per_decoder.c UTF8String.c ber_tlv_length.c constr_SET_OF.c ISO646String.c per_encoder.c VideotexString.c ber_tlv_tag.c constr_TYPE.c NativeEnumerated.c per_support.c VisibleString.c BIT_STRING.c NativeInteger.c PrintableString.c xer_decoder.c BMPString.c der_encoder.c NativeReal.c REAL.c xer_encoder.c BOOLEAN.c ENUMERATED.c NULL.c RELATIVE-OID.c xer_support.c per_opentype.c
diff --git a/src/NativeEnumerated.c b/src/NativeEnumerated.c
index e3af1ca..1554220 100644
--- a/src/NativeEnumerated.c
+++ b/src/NativeEnumerated.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
@@ -177,9 +177,9 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
- if(per_put_few_bits(po, inext, 0))
+ if(per_put_few_bits(po, inext, 1))
_ASN_ENCODE_FAILED;
- ct = 0;
+ if(inext) ct = 0;
} else if(inext) {
_ASN_ENCODE_FAILED;
}
@@ -196,7 +196,10 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
/*
* X.691, #10.6: normally small non-negative whole number;
*/
- if(uper_put_nsnnwn(po, value - (specs->extension - 1)))
+ ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
+ value, specs->extension, inext,
+ value - (inext ? (specs->extension - 1) : 0));
+ if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
_ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
diff --git a/src/NativeInteger.c b/src/NativeInteger.c
index 34599f6..abdb71a 100644
--- a/src/NativeInteger.c
+++ b/src/NativeInteger.c
@@ -48,6 +48,7 @@ asn_dec_rval_t
NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
long *native = (long *)*nint_ptr;
asn_dec_rval_t rval;
ber_tlv_len_t length;
@@ -105,7 +106,9 @@ NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
tmp.size = length;
- if(asn_INTEGER2long(&tmp, &l)) {
+ if((specs&&specs->field_unsigned)
+ ? asn_INTEGER2ulong(&tmp, &l)
+ : asn_INTEGER2long(&tmp, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
@@ -145,7 +148,7 @@ NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
/* Prepare a fake INTEGER */
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
- *p = native;
+ *p = (uint8_t)native;
tmp.buf = buf;
tmp.size = sizeof(buf);
@@ -167,6 +170,7 @@ asn_dec_rval_t
NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
INTEGER_t st;
void *st_ptr = (void *)&st;
@@ -182,7 +186,9 @@ NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
opt_mname, buf_ptr, size);
if(rval.code == RC_OK) {
long l;
- if(asn_INTEGER2long(&st, &l)) {
+ if((specs&&specs->field_unsigned)
+ ? asn_INTEGER2ulong(&st, &l)
+ : asn_INTEGER2long(&st, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
} else {
@@ -205,6 +211,7 @@ asn_enc_rval_t
NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit int */
asn_enc_rval_t er;
const long *native = (const long *)sptr;
@@ -214,7 +221,9 @@ NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
if(!native) _ASN_ENCODE_FAILED;
- er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native);
+ er.encoded = snprintf(scratch, sizeof(scratch),
+ (specs && specs->field_unsigned)
+ ? "%lu" : "%ld", *native);
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|| cb(scratch, er.encoded, app_key) < 0)
_ASN_ENCODE_FAILED;
@@ -227,6 +236,7 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
@@ -244,7 +254,9 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
if(rval.code == RC_OK) {
- if(asn_INTEGER2long(&tmpint, native))
+ if((specs&&specs->field_unsigned)
+ ? asn_INTEGER2ulong(&tmpint, native)
+ : asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
@@ -258,6 +270,7 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_enc_rval_t
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
long native;
INTEGER_t tmpint;
@@ -269,7 +282,9 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
- if(asn_long2INTEGER(&tmpint, native))
+ if((specs&&specs->field_unsigned)
+ ? asn_ulong2INTEGER(&tmpint, native)
+ : asn_long2INTEGER(&tmpint, native))
_ASN_ENCODE_FAILED;
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
@@ -282,6 +297,7 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
int
NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
const long *native = (const long *)sptr;
char scratch[32]; /* Enough for 64-bit int */
int ret;
@@ -290,7 +306,9 @@ NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
(void)ilevel; /* Unused argument */
if(native) {
- ret = snprintf(scratch, sizeof(scratch), "%ld", *native);
+ ret = snprintf(scratch, sizeof(scratch),
+ (specs && specs->field_unsigned)
+ ? "%lu" : "%ld", *native);
assert(ret > 0 && (size_t)ret < sizeof(scratch));
return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
} else {
diff --git a/src/NativeReal.c b/src/NativeReal.c
index 2b8ec16..a1ff91e 100644
--- a/src/NativeReal.c
+++ b/src/NativeReal.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
@@ -12,6 +12,7 @@
#include <asn_internal.h>
#include <NativeReal.h>
#include <REAL.h>
+#include <OCTET_STRING.h>
/*
* NativeReal basic type description.
@@ -29,7 +30,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
NativeReal_encode_der,
NativeReal_decode_xer,
NativeReal_encode_xer,
- 0, 0,
+ NativeReal_decode_uper,
+ NativeReal_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeReal_tags,
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
@@ -157,7 +159,74 @@ NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
return erval;
}
+/*
+ * Decode REAL type using PER.
+ */
+asn_dec_rval_t
+NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **dbl_ptr, asn_per_data_t *pd) {
+ double *Dbl = (double *)*dbl_ptr;
+ asn_dec_rval_t rval;
+ REAL_t tmp;
+ void *ptmp = &tmp;
+ int ret;
+
+ (void)constraints;
+
+ /*
+ * If the structure is not there, allocate it.
+ */
+ if(Dbl == NULL) {
+ *dbl_ptr = CALLOC(1, sizeof(*Dbl));
+ Dbl = (double *)*dbl_ptr;
+ if(Dbl == NULL)
+ _ASN_DECODE_FAILED;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+ rval = OCTET_STRING_decode_uper(opt_codec_ctx, td, NULL,
+ &ptmp, pd);
+ if(rval.code != RC_OK) {
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ return rval;
+ }
+
+ ret = asn_REAL2double(&tmp, Dbl);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ if(ret) _ASN_DECODE_FAILED;
+ return rval;
+}
+
+/*
+ * Encode the NativeReal using the OCTET STRING PER encoder.
+ */
+asn_enc_rval_t
+NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ double Dbl = *(const double *)sptr;
+ asn_enc_rval_t erval;
+ REAL_t tmp;
+
+ (void)constraints;
+
+ /* Prepare a temporary clean structure */
+ memset(&tmp, 0, sizeof(tmp));
+
+ if(asn_double2REAL(&tmp, Dbl))
+ _ASN_ENCODE_FAILED;
+
+ /* Encode a DER REAL */
+ erval = OCTET_STRING_encode_uper(td, NULL, &tmp, po);
+ if(erval.encoded == -1)
+ erval.structure_ptr = sptr;
+
+ /* Free possibly allocated members of the temporary structure */
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+
+ return erval;
+}
/*
* Decode the chunk of XML text encoding REAL.
diff --git a/src/NumericString.c b/src/NumericString.c
index cef64ea..50fe449 100644
--- a/src/NumericString.c
+++ b/src/NumericString.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
@@ -12,6 +12,31 @@ static ber_tlv_tag_t asn_DEF_NumericString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (18 << 2)), /* [UNIVERSAL 18] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static int asn_DEF_NumericString_v2c(unsigned int value) {
+ switch(value) {
+ case 0x20: return 0;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+ case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
+ return value - (0x30 - 1);
+ }
+ return -1;
+}
+static int asn_DEF_NumericString_c2v(unsigned int code) {
+ if(code > 0) {
+ if(code <= 10)
+ return code + (0x30 - 1);
+ else
+ return -1;
+ } else {
+ return 0x20;
+ }
+}
+static asn_per_constraints_t asn_DEF_NumericString_constraints = {
+ { APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ asn_DEF_NumericString_v2c,
+ asn_DEF_NumericString_c2v
+};
asn_TYPE_descriptor_t asn_DEF_NumericString = {
"NumericString",
"NumericString",
@@ -22,7 +47,8 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
@@ -30,7 +56,7 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
/ sizeof(asn_DEF_NumericString_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_NumericString_constraints,
0, 0, /* No members */
0 /* No specifics */
};
@@ -55,7 +81,7 @@ NumericString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
continue;
}
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value byte %ld (%d) "
"not in NumericString alphabet (%s:%d)",
td->name,
@@ -65,7 +91,7 @@ NumericString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
return -1;
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
diff --git a/src/OBJECT_IDENTIFIER.c b/src/OBJECT_IDENTIFIER.c
index b1666dc..0d7043e 100644
--- a/src/OBJECT_IDENTIFIER.c
+++ b/src/OBJECT_IDENTIFIER.c
@@ -4,6 +4,7 @@
*/
#include <asn_internal.h>
#include <OBJECT_IDENTIFIER.h>
+#include <OCTET_STRING.h>
#include <limits.h> /* for CHAR_BIT */
#include <errno.h>
@@ -23,7 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
der_encode_primitive,
OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
@@ -44,14 +46,14 @@ OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
if(st && st->buf) {
if(st->size < 1) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: at least one numerical value "
"expected (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -63,7 +65,7 @@ OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int
OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
- unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */
+ unsigned LE GCC_NOTUSED = 1; /* Little endian (x86) */
uint8_t *arcend = arcbuf + arclen; /* End of arc */
unsigned int cache = 0; /* No more than 14 significant bits */
unsigned char *rvbuf = (unsigned char *)rvbufp;
diff --git a/src/OCTET_STRING.c b/src/OCTET_STRING.c
index 3a83bd9..584def8 100644
--- a/src/OCTET_STRING.c
+++ b/src/OCTET_STRING.c
@@ -17,10 +17,12 @@ static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
sizeof(OCTET_STRING_t),
offsetof(OCTET_STRING_t, _asn_ctx),
- 0
+ ASN_OSUBV_STR
};
-static asn_per_constraint_t asn_DEF_OCTET_STRING_constraint = {
- APC_SEMI_CONSTRAINED, -1, -1, 0, 0
+static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
+ { APC_CONSTRAINED, 8, 8, 0, 255 },
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
+ 0, 0
};
asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
"OCTET STRING", /* Canonical name */
@@ -103,15 +105,6 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
} while(0)
/*
- * Internal variant of the OCTET STRING.
- */
-typedef enum OS_type {
- _TT_GENERIC = 0, /* Just a random OCTET STRING */
- _TT_BIT_STRING = 1, /* BIT STRING type, a special case */
- _TT_ANY = 2 /* ANY type, a special case too */
-} OS_type_e;
-
-/*
* The main reason why ASN.1 is still alive is that too much time and effort
* is necessary for learning it more or less adequately, thus creating a gut
* necessity to demonstrate that aquired skill everywhere afterwards.
@@ -185,11 +178,11 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
struct _stack *stck; /* Expectations stack structure */
struct _stack_el *sel = 0; /* Stack element */
int tlv_constr;
- OS_type_e type_variant = (OS_type_e)specs->subvariant;
+ enum asn_OS_Subvariant type_variant = specs->subvariant;
ASN_DEBUG("Decoding %s as %s (frame %ld)",
td->name,
- (type_variant == _TT_GENERIC) ?
+ (type_variant == ASN_OSUBV_STR) ?
"OCTET STRING" : "OS-SpecialCase",
(long)size);
@@ -230,7 +223,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
* Jump into stackless primitive decoding.
*/
_CH_PHASE(ctx, 3);
- if(type_variant == _TT_ANY && tag_mode != 1)
+ if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
APPEND(buf_ptr, rval.consumed);
ADVANCE(rval.consumed);
goto phase3;
@@ -309,7 +302,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
- if(type_variant == _TT_ANY
+ if(type_variant == ASN_OSUBV_ANY
&& (tag_mode != 1 || sel->cont_level))
APPEND("\0\0", 2);
@@ -334,10 +327,10 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
* depending on ASN.1 type being decoded.
*/
switch(type_variant) {
- case _TT_BIT_STRING:
+ case ASN_OSUBV_BIT:
/* X.690: 8.6.4.1, NOTE 2 */
/* Fall through */
- case _TT_GENERIC:
+ case ASN_OSUBV_STR:
default:
if(sel) {
int level = sel->cont_level;
@@ -352,7 +345,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
/* else, Fall through */
}
/* Fall through */
- case _TT_ANY:
+ case ASN_OSUBV_ANY:
expected_tag = tlv_tag;
break;
}
@@ -397,7 +390,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
} else {
sel->left = tlv_len;
}
- if(type_variant == _TT_ANY
+ if(type_variant == ASN_OSUBV_ANY
&& (tag_mode != 1 || sel->cont_level))
APPEND(buf_ptr, tlvl);
sel->got += tlvl;
@@ -431,7 +424,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
len = ((ber_tlv_len_t)size < sel->left)
? (ber_tlv_len_t)size : sel->left;
if(len > 0) {
- if(type_variant == _TT_BIT_STRING
+ if(type_variant == ASN_OSUBV_BIT
&& sel->bits_chopped == 0) {
/* Put the unused-bits-octet away */
st->bits_unused = *(const uint8_t *)buf_ptr;
@@ -464,7 +457,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
if(size < (size_t)ctx->left) {
if(!size) RETURN(RC_WMORE);
- if(type_variant == _TT_BIT_STRING && !ctx->context) {
+ if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
st->bits_unused = *(const uint8_t *)buf_ptr;
ctx->left--;
ADVANCE(1);
@@ -475,7 +468,7 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
ADVANCE(size);
RETURN(RC_WMORE);
} else {
- if(type_variant == _TT_BIT_STRING
+ if(type_variant == ASN_OSUBV_BIT
&& !ctx->context && ctx->left) {
st->bits_unused = *(const uint8_t *)buf_ptr;
ctx->left--;
@@ -502,14 +495,14 @@ OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
/*
* BIT STRING-specific processing.
*/
- if(type_variant == _TT_BIT_STRING && st->size) {
+ if(type_variant == ASN_OSUBV_BIT && st->size) {
/* Finalize BIT STRING: zero out unused bits. */
st->buf[st->size-1] &= 0xff << st->bits_unused;
}
ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
(long)consumed_myself, td->name,
- (type_variant == _TT_GENERIC) ? (char *)st->buf : "<data>",
+ (type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "<data>",
(long)st->size);
@@ -528,7 +521,7 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
BIT_STRING_t *st = (BIT_STRING_t *)sptr;
- OS_type_e type_variant = (OS_type_e)specs->subvariant;
+ enum asn_OS_Subvariant type_variant = specs->subvariant;
int fix_last_byte = 0;
ASN_DEBUG("%s %s as OCTET STRING",
@@ -537,10 +530,11 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
/*
* Write tags.
*/
- if(type_variant != _TT_ANY || tag_mode == 1) {
+ if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
er.encoded = der_write_tags(td,
- (type_variant == _TT_BIT_STRING) + st->size,
- tag_mode, type_variant == _TT_ANY, tag, cb, app_key);
+ (type_variant == ASN_OSUBV_BIT) + st->size,
+ tag_mode, type_variant == ASN_OSUBV_ANY, tag,
+ cb, app_key);
if(er.encoded == -1) {
er.failed_type = td;
er.structure_ptr = sptr;
@@ -548,19 +542,19 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
}
} else {
/* Disallow: [<tag>] IMPLICIT ANY */
- assert(type_variant != _TT_ANY || tag_mode != -1);
+ assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
er.encoded = 0;
}
if(!cb) {
- er.encoded += (type_variant == _TT_BIT_STRING) + st->size;
+ er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
_ASN_ENCODED_OK(er);
}
/*
* Prepare to deal with the last octet of BIT STRING.
*/
- if(type_variant == _TT_BIT_STRING) {
+ if(type_variant == ASN_OSUBV_BIT) {
uint8_t b = st->bits_unused & 0x07;
if(b && st->size) fix_last_byte = 1;
_ASN_CALLBACK(&b, 1);
@@ -595,7 +589,7 @@ OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
uint8_t *end;
size_t i;
- if(!st || !st->buf)
+ if(!st || (!st->buf && st->size))
_ASN_ENCODE_FAILED;
er.encoded = 0;
@@ -751,7 +745,7 @@ OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
(void)ilevel; /* Unused argument */
(void)flags; /* Unused argument */
- if(!st || !st->buf)
+ if(!st || (!st->buf && st->size))
_ASN_ENCODE_FAILED;
buf = st->buf;
@@ -1197,6 +1191,135 @@ OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
OCTET_STRING__convert_entrefs);
}
+static int
+OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
+ size_t units, unsigned int bpc, unsigned int unit_bits,
+ long lb, long ub, asn_per_constraints_t *pc) {
+ uint8_t *end = buf + units * bpc;
+
+ ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
+ (int)units, lb, ub, unit_bits);
+
+ /* X.691: 27.5.4 */
+ if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ /* Decode without translation */
+ lb = 0;
+ } else if(pc && pc->code2value) {
+ if(unit_bits > 16)
+ return 1; /* FATAL: can't have constrained
+ * UniversalString with more than
+ * 16 million code points */
+ for(; buf < end; buf += bpc) {
+ int value;
+ int code = per_get_few_bits(po, unit_bits);
+ if(code < 0) return -1; /* WMORE */
+ value = pc->code2value(code);
+ if(value < 0) {
+ ASN_DEBUG("Code %d (0x%02x) is"
+ " not in map (%ld..%ld)",
+ code, code, lb, ub);
+ return 1; /* FATAL */
+ }
+ switch(bpc) {
+ case 1: *buf = value; break;
+ case 2: buf[0] = value >> 8; buf[1] = value; break;
+ case 4: buf[0] = value >> 24; buf[1] = value >> 16;
+ buf[2] = value >> 8; buf[3] = value; break;
+ }
+ }
+ return 0;
+ }
+
+ /* Shortcut the no-op copying to the aligned structure */
+ if(lb == 0 && (unit_bits == 8 * bpc)) {
+ return per_get_many_bits(po, buf, 0, unit_bits * units);
+ }
+
+ for(; buf < end; buf += bpc) {
+ int code = per_get_few_bits(po, unit_bits);
+ int ch = code + lb;
+ if(code < 0) return -1; /* WMORE */
+ if(ch > ub) {
+ ASN_DEBUG("Code %d is out of range (%ld..%ld)",
+ ch, lb, ub);
+ return 1; /* FATAL */
+ }
+ switch(bpc) {
+ case 1: *buf = ch; break;
+ case 2: buf[0] = ch >> 8; buf[1] = ch; break;
+ case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
+ buf[2] = ch >> 8; buf[3] = ch; break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
+ size_t units, unsigned int bpc, unsigned int unit_bits,
+ long lb, long ub, asn_per_constraints_t *pc) {
+ const uint8_t *end = buf + units * bpc;
+
+ ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
+ (int)units, lb, ub, unit_bits, bpc);
+
+ /* X.691: 27.5.4 */
+ if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ /* Encode as is */
+ lb = 0;
+ } else if(pc && pc->value2code) {
+ for(; buf < end; buf += bpc) {
+ int code;
+ uint32_t value;
+ switch(bpc) {
+ case 1: value = *(const uint8_t *)buf; break;
+ case 2: value = (buf[0] << 8) | buf[1]; break;
+ case 4: value = (buf[0] << 24) | (buf[1] << 16)
+ | (buf[2] << 8) | buf[3]; break;
+ default: return -1;
+ }
+ code = pc->value2code(value);
+ if(code < 0) {
+ ASN_DEBUG("Character %d (0x%02x) is"
+ " not in map (%ld..%ld)",
+ *buf, *buf, lb, ub);
+ return -1;
+ }
+ if(per_put_few_bits(po, code, unit_bits))
+ return -1;
+ }
+ }
+
+ /* Shortcut the no-op copying to the aligned structure */
+ if(lb == 0 && (unit_bits == 8 * bpc)) {
+ return per_put_many_bits(po, buf, unit_bits * units);
+ }
+
+ for(ub -= lb; buf < end; buf += bpc) {
+ int ch;
+ uint32_t value;
+ switch(bpc) {
+ case 1: value = *(const uint8_t *)buf; break;
+ case 2: value = (buf[0] << 8) | buf[1]; break;
+ case 4: value = (buf[0] << 24) | (buf[1] << 16)
+ | (buf[2] << 8) | buf[3]; break;
+ default: return -1;
+ }
+ ch = value - lb;
+ if(ch < 0 || ch > ub) {
+ ASN_DEBUG("Character %d (0x%02x)"
+ " is out of range (%ld..%ld)",
+ *buf, *buf, lb, ub + lb);
+ return -1;
+ }
+ if(per_put_few_bits(po, ch, unit_bits))
+ return -1;
+ }
+
+ return 0;
+}
+
asn_dec_rval_t
OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
@@ -1205,18 +1328,62 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
- asn_per_constraint_t *ct = constraints ? &constraints->size
- : (td->per_constraints
- ? &td->per_constraints->size
- : &asn_DEF_OCTET_STRING_constraint);
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
asn_dec_rval_t rval = { RC_OK, 0 };
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
ssize_t consumed_myself = 0;
int repeat;
- int unit_bits = (specs->subvariant != 1) * 7 + 1;
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
(void)opt_codec_ctx;
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+
+ switch(specs->subvariant) {
+ default:
+ case ASN_OSUBV_ANY:
+ ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
+ RETURN(RC_FAIL);
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ break;
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_CHAR;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ break;
+ }
+
/*
* Allocate the string.
*/
@@ -1225,24 +1392,26 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(!st) RETURN(RC_FAIL);
}
- ASN_DEBUG("PER Decoding %s %ld .. %ld bits %d",
- ct->flags & APC_EXTENSIBLE ? "extensible" : "fixed",
- ct->lower_bound, ct->upper_bound, ct->effective_bits);
+ ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
+ csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
+ csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
- if(ct->flags & APC_EXTENSIBLE) {
+ if(csiz->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) RETURN(RC_WMORE);
- if(inext) ct = &asn_DEF_OCTET_STRING_constraint;
- consumed_myself = 0;
+ if(inext) {
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ unit_bits = canonical_unit_bits;
+ }
}
- if(ct->effective_bits >= 0
- && (!st->buf || st->size < ct->upper_bound)) {
+ if(csiz->effective_bits >= 0) {
FREEMEM(st->buf);
- if(unit_bits == 1) {
- st->size = (ct->upper_bound + 7) >> 3;
+ if(bpc) {
+ st->size = csiz->upper_bound * bpc;
} else {
- st->size = ct->upper_bound;
+ st->size = (csiz->upper_bound + 7) >> 3;
}
st->buf = (uint8_t *)MALLOC(st->size + 1);
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
@@ -1251,46 +1420,70 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
- if(ct->effective_bits == 0) {
- int ret = per_get_many_bits(pd, st->buf, 0,
- unit_bits * ct->upper_bound);
+ if(csiz->effective_bits == 0) {
+ int ret;
+ if(bpc) {
+ ASN_DEBUG("Encoding OCTET STRING size %ld",
+ csiz->upper_bound);
+ ret = OCTET_STRING_per_get_characters(pd, st->buf,
+ csiz->upper_bound, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ASN_DEBUG("Encoding BIT STRING size %ld",
+ csiz->upper_bound);
+ ret = per_get_many_bits(pd, st->buf, 0,
+ unit_bits * csiz->upper_bound);
+ }
if(ret < 0) RETURN(RC_WMORE);
- consumed_myself += unit_bits * ct->upper_bound;
+ consumed_myself += unit_bits * csiz->upper_bound;
st->buf[st->size] = 0;
- if(unit_bits == 1 && (ct->upper_bound & 0x7))
- st->bits_unused = 8 - (ct->upper_bound & 0x7);
+ if(bpc == 0) {
+ int ubs = (csiz->upper_bound & 0x7);
+ st->bits_unused = ubs ? 8 - ubs : 0;
+ }
RETURN(RC_OK);
}
st->size = 0;
do {
+ ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
- len_bits = uper_get_length(pd, ct->effective_bits, &repeat);
- if(len_bits < 0) RETURN(RC_WMORE);
- len_bits += ct->lower_bound;
+ raw_len = uper_get_length(pd, csiz->effective_bits, &repeat);
+ if(raw_len < 0) RETURN(RC_WMORE);
+ raw_len += csiz->lower_bound;
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
- (long)ct->effective_bits, (long)len_bits,
+ (long)csiz->effective_bits, (long)raw_len,
repeat ? "repeat" : "once", td->name);
- if(unit_bits == 1) {
+ if(bpc) {
+ len_bytes = raw_len * bpc;
+ len_bits = len_bytes * unit_bits;
+ } else {
+ len_bits = raw_len;
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7)
st->bits_unused = 8 - (len_bits & 0x7);
/* len_bits be multiple of 16K if repeat is set */
- } else {
- len_bytes = len_bits;
- len_bits = len_bytes << 3;
}
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
- ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
+ if(bpc) {
+ ret = OCTET_STRING_per_get_characters(pd,
+ &st->buf[st->size], raw_len, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ret = per_get_many_bits(pd, &st->buf[st->size],
+ 0, len_bits);
+ }
if(ret < 0) RETURN(RC_WMORE);
st->size += len_bytes;
} while(repeat);
@@ -1306,41 +1499,87 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
- asn_per_constraint_t *ct = constraints ? &constraints->size
- : (td->per_constraints
- ? &td->per_constraints->size
- : &asn_DEF_OCTET_STRING_constraint);
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
- int unit_bits = (specs->subvariant != 1) * 7 + 1;
- asn_enc_rval_t er;
- int ct_extensible = ct->flags & APC_EXTENSIBLE;
+ asn_enc_rval_t er = { 0, 0, 0 };
int inext = 0; /* Lies not within extension root */
- int sizeinunits = st->size;
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
+ unsigned int sizeinunits;
const uint8_t *buf;
int ret;
-
- if(!st || !st->buf)
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ int ct_extensible;
+
+ if(!st || (!st->buf && st->size))
_ASN_ENCODE_FAILED;
- if(unit_bits == 1) {
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+ ct_extensible = csiz->flags & APC_EXTENSIBLE;
+
+ switch(specs->subvariant) {
+ default:
+ case ASN_OSUBV_ANY:
+ _ASN_ENCODE_FAILED;
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
sizeinunits, st->bits_unused);
- sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
+ break;
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_CHAR;
+ sizeinunits = st->size;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ sizeinunits = st->size / 2;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ sizeinunits = st->size / 4;
+ break;
}
ASN_DEBUG("Encoding %s into %d units of %d bits"
- " (%d..%d, effective %d)%s",
+ " (%ld..%ld, effective %d)%s",
td->name, sizeinunits, unit_bits,
- ct->lower_bound, ct->upper_bound,
- ct->effective_bits, ct_extensible ? " EXT" : "");
+ csiz->lower_bound, csiz->upper_bound,
+ csiz->effective_bits, ct_extensible ? " EXT" : "");
- /* Figure out wheter size lies within PER visible consrtaint */
+ /* Figure out wheter size lies within PER visible constraint */
- if(ct->effective_bits >= 0) {
- if(sizeinunits < ct->lower_bound
- || sizeinunits > ct->upper_bound) {
+ if(csiz->effective_bits >= 0) {
+ if((int)sizeinunits < csiz->lower_bound
+ || (int)sizeinunits > csiz->upper_bound) {
if(ct_extensible) {
- ct = &asn_DEF_OCTET_STRING_constraint;
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ unit_bits = canonical_unit_bits;
inext = 1;
} else
_ASN_ENCODE_FAILED;
@@ -1358,14 +1597,21 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
- if(ct->effective_bits >= 0) {
+ if(csiz->effective_bits >= 0) {
ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
- st->size, sizeinunits - ct->lower_bound,
- ct->effective_bits);
- ret = per_put_few_bits(po, sizeinunits - ct->lower_bound,
- ct->effective_bits);
+ st->size, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
+ ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
if(ret) _ASN_ENCODE_FAILED;
- ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits);
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, st->buf,
+ sizeinunits, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, st->buf,
+ sizeinunits * unit_bits);
+ }
if(ret) _ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
@@ -1383,15 +1629,22 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
ssize_t maySave = uper_put_length(po, sizeinunits);
if(maySave < 0) _ASN_ENCODE_FAILED;
- ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
+ ASN_DEBUG("Encoding %ld of %ld",
+ (long)maySave, (long)sizeinunits);
- ret = per_put_many_bits(po, buf, maySave * unit_bits);
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, buf,
+ maySave, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, buf, maySave * unit_bits);
+ }
if(ret) _ASN_ENCODE_FAILED;
- if(unit_bits == 1)
- buf += maySave >> 3;
+ if(bpc)
+ buf += maySave * bpc;
else
- buf += maySave;
+ buf += maySave >> 3;
sizeinunits -= maySave;
assert(!(maySave & 0x07) || !sizeinunits);
}
@@ -1412,7 +1665,8 @@ OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
(void)td; /* Unused argument */
- if(!st || !st->buf) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
+ if(!st || (!st->buf && st->size))
+ return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
/*
* Dump the contents of the buffer in hexadecimal.
@@ -1448,7 +1702,7 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
- if(st && st->buf) {
+ if(st && (st->buf || !st->size)) {
return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
@@ -1472,6 +1726,7 @@ OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
if(st->buf) {
FREEMEM(st->buf);
+ st->buf = 0;
}
/*
diff --git a/src/ObjectDescriptor.c b/src/ObjectDescriptor.c
index 44cb5f6..cd8e8a3 100644
--- a/src/ObjectDescriptor.c
+++ b/src/ObjectDescriptor.c
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags)
diff --git a/src/PrintableString.c b/src/PrintableString.c
index f588083..c8ee3ae 100644
--- a/src/PrintableString.c
+++ b/src/PrintableString.c
@@ -1,17 +1,52 @@
/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * 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 <PrintableString.h>
/*
+ * ASN.1:1984 (X.409)
+ */
+static int _PrintableString_alphabet[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */
+ 1, 0, 0, 0, 0, 0, 0, 2, 3, 4, 0, 5, 6, 7, 8, 9, /* . '() +,-./ */
+10,11,12,13,14,15,16,17,18,19,20, 0, 0,21, 0,22, /* 0123456789: = ? */
+ 0,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, /* ABCDEFGHIJKLMNO */
+38,39,40,41,42,43,44,45,46,47,48, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ */
+ 0,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, /* abcdefghijklmno */
+64,65,66,67,68,69,70,71,72,73,74, 0, 0, 0, 0, 0, /* pqrstuvwxyz */
+};
+static int _PrintableString_code2value[74] = {
+32,39,40,41,43,44,45,46,47,48,49,50,51,52,53,54,
+55,56,57,58,61,63,65,66,67,68,69,70,71,72,73,74,
+75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
+97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
+113,114,115,116,117,118,119,120,121,122};
+
+/*
* PrintableString basic type description.
*/
static ber_tlv_tag_t asn_DEF_PrintableString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)), /* [UNIVERSAL 19] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static int asn_DEF_PrintableString_v2c(unsigned int value) {
+ return _PrintableString_alphabet[value > 255 ? 0 : value] - 1;
+}
+static int asn_DEF_PrintableString_c2v(unsigned int code) {
+ if(code < 74)
+ return _PrintableString_code2value[code];
+ return -1;
+}
+static asn_per_constraints_t asn_DEF_PrintableString_constraints = {
+ { APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ asn_DEF_PrintableString_v2c,
+ asn_DEF_PrintableString_c2v
+};
asn_TYPE_descriptor_t asn_DEF_PrintableString = {
"PrintableString",
"PrintableString",
@@ -22,7 +57,8 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
@@ -30,34 +66,12 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
/ sizeof(asn_DEF_PrintableString_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_PrintableString_constraints,
0, 0, /* No members */
0 /* No specifics */
};
-/*
- * ASN.1:1984 (X.409)
- */
-static int _PrintableString_alphabet[256] = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* ' */
-0x41, 0x42, 0x00, 0x43, 0x44, 0x45, 0x46, 0x47, /* ( ) + , - . / */
-0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, /* 0 1 2 3 4 5 6 7 */
-0x3d, 0x3e, 0x48, 0x00, 0x00, 0x49, 0x00, 0x4a, /* 8 9 : = ? */
-0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A B C D E F G */
-0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* H I J K L M N O */
-0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* P Q R S T U V W */
-0x18, 0x19, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, /* X Y Z */
-0x00, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, /* a b c d e f g */
-0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* h i j k l m n o */
-0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, /* p q r s t u v w */
-0x32, 0x33, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, /* x y z */
-};
-
int
PrintableString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
@@ -73,7 +87,7 @@ PrintableString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
*/
for(; buf < end; buf++) {
if(!_PrintableString_alphabet[*buf]) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value byte %ld (%d) "
"not in PrintableString alphabet "
"(%s:%d)",
@@ -85,7 +99,7 @@ PrintableString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
}
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
diff --git a/src/REAL.c b/src/REAL.c
index 51098c0..5e93ac8 100644
--- a/src/REAL.c
+++ b/src/REAL.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#if defined(__alpha)
@@ -12,12 +12,13 @@
#include <math.h>
#include <errno.h>
#include <REAL.h>
+#include <OCTET_STRING.h>
#undef INT_MAX
#define INT_MAX ((int)(((unsigned int)-1) >> 1))
#if !(defined(NAN) || defined(INFINITY))
-static volatile double real_zero __attribute__ ((unused)) = 0.0;
+static volatile double real_zero GCC_NOTUSED = 0.0;
#endif
#ifndef NAN
#define NAN (real_zero/real_zero)
@@ -42,7 +43,8 @@ asn_TYPE_descriptor_t asn_DEF_REAL = {
der_encode_primitive,
REAL_decode_xer,
REAL_encode_xer,
- 0, 0,
+ REAL_decode_uper,
+ REAL_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_REAL_tags,
sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
@@ -341,6 +343,20 @@ REAL_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
buf_ptr, size, REAL__xer_body_decode);
}
+asn_dec_rval_t
+REAL_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_decode_uper(opt_codec_ctx, td, 0, sptr, pd);
+}
+
+asn_enc_rval_t
+REAL_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_encode_uper(td, 0, sptr, po);
+}
int
asn_REAL2double(const REAL_t *st, double *dbl_value) {
@@ -437,16 +453,16 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
return -1;
}
- if((octv & 0x03) == 0x11) {
- /* 8.5.6.4, case d) */
+ elen = (octv & 0x03); /* bits 2 to 1; 8.5.6.4 */
+ if(elen == 0x03) { /* bits 2 to 1 = 11; 8.5.6.4, case d) */
elen = st->buf[1]; /* unsigned binary number */
if(elen == 0 || st->size <= (int)(2 + elen)) {
errno = EINVAL;
return -1;
}
+ /* FIXME: verify constraints of case d) */
ptr = &st->buf[2];
} else {
- elen = (octv & 0x03);
ptr = &st->buf[1];
}
@@ -505,8 +521,8 @@ asn_double2REAL(REAL_t *st, double dbl_value) {
uint8_t buf[16]; /* More than enough for 8-byte dbl_value */
uint8_t dscr[sizeof(dbl_value)]; /* double value scratch pad */
/* Assertion guards: won't even compile, if unexpected double size */
- char assertion_buffer1[9 - sizeof(dbl_value)] __attribute__((unused));
- char assertion_buffer2[sizeof(dbl_value) - 7] __attribute__((unused));
+ char assertion_buffer1[9 - sizeof(dbl_value)] GCC_NOTUSED;
+ char assertion_buffer2[sizeof(dbl_value) - 7] GCC_NOTUSED;
uint8_t *ptr = buf;
uint8_t *mstop; /* Last byte of mantissa */
unsigned int mval; /* Value of the last byte of mantissa */
diff --git a/src/RELATIVE-OID.c b/src/RELATIVE-OID.c
index 0181434..983fc09 100644
--- a/src/RELATIVE-OID.c
+++ b/src/RELATIVE-OID.c
@@ -5,6 +5,7 @@
*/
#include <asn_internal.h>
#include <RELATIVE-OID.h>
+#include <OCTET_STRING.h>
#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
#include <limits.h> /* for CHAR_BIT */
#include <errno.h>
@@ -25,7 +26,8 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
der_encode_primitive,
RELATIVE_OID_decode_xer,
RELATIVE_OID_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_RELATIVE_OID_tags,
sizeof(asn_DEF_RELATIVE_OID_tags)
diff --git a/src/T61String.c b/src/T61String.c
index 25d887a..98461bb 100644
--- a/src/T61String.c
+++ b/src/T61String.c
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_T61String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_T61String_tags,
sizeof(asn_DEF_T61String_tags)
diff --git a/src/TeletexString.c b/src/TeletexString.c
index b96cb3b..cc2acad 100644
--- a/src/TeletexString.c
+++ b/src/TeletexString.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_TeletexString_tags,
sizeof(asn_DEF_TeletexString_tags)
@@ -35,3 +36,139 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
0 /* No specifics */
};
+/*
+ * Here is a formal attempt at creating a mapping from TeletexString
+ * (T61String) of the latest ASN.1 standard (X.680:2002) into the Unicode
+ * character set. -- Lev Walkin <vlm@lionet.info>
+ *
+ * The first thing to keep in mind is that TeletexString (T61String)
+ * is defined in ASN.1, and is not really a T.61 string.
+ * The T.61 standard is withdrawn by ITU-T and is no longer an authoritative
+ * reference. See http://www.itu.int/rec/T-REC-T.61
+ *
+ * The X.680 specifies TeletexString (T61String) as a combination of the
+ * character sets specified by the registration numbers listed in
+ * ISO International Register of Coded Character Sets to be used with
+ * Escape Sequences (ISO-2375):
+ * 6, 87, 102, 103, 106, 107, 126, 144, 150, 153, 156, 164, 165, 168,
+ * plus SPACE and DELETE characters.
+ * In addition to that, the X.680 Table 6 NOTE 2 allows using register entries
+ * 6 and 156 instead of 102 and 103.
+ *
+ * The ISO Register itself is available at http://www.itscj.ipsj.or.jp/ISO-IR/
+ *
+ * #6 is ASCII. http://www.itscj.ipsj.or.jp/ISO-IR/006.pdf
+ * Escapes into:
+ * G0: ESC 2/8 4/2 ("(B")
+ * G1: ESC 2/9 4/2 (")B")
+ * The range is [0x21 .. 0x7e]. Conversion into Unicode
+ * is simple, because it has one-to-one correspondence.
+ * #87 is a "Japanese Graphic Character Set for Information Interchange".
+ * Is a multiple-byte set of 6877 characters.
+ * The character set is JIS X 0208-1983 (originally JIS C 6226-1983).
+ * Escapes into:
+ * G0: ESC 2/4 4/2 ("$B")
+ * G1: ESC 2/4 2/9 4/2 ("$)B")
+ * G2: ESC 2/4 2/10 4/2 ("$*B")
+ * G3: ESC 2/4 2/11 4/2 ("$+B")
+ * #102 is "Teletex Primary Set of Graphic Characters" and is almost ASCII.
+ * Escapes into:
+ * G0: ESC 2/8 7/5 ("(u")
+ * G1: ESC 2/9 7/5 (")u")
+ * G2: ESC 2/10 7/5 ("*u")
+ * G3: ESC 2/11 7/5 ("+u")
+ * It is almost identical to ASCII, except for ASCII position for '$'
+ * (DOLLAR SIGN) is filled with '¤' (CURRENCY SIGN), which is U+00A4.
+ * Also, ASCII positions for '`', '\', '^', '{', '}', '~' are marked
+ * as "should not be used".
+ * #103 is a supplementary set of characters used in combination with #102.
+ * Escapes into:
+ * G0: ESC 2/8 7/6 ("(v")
+ * G1: ESC 2/9 7/6 (")v")
+ * G2: ESC 2/10 7/6 ("*v")
+ * G3: ESC 2/11 7/6 ("+v")
+ * Some characters in that character set are combining characters,
+ * which can only be restrictively used with certain basic Latin letters.
+ * It can be thought of as a subset of #156 with the exception of 4/12
+ * which is UNDERLINE in #103 and absent in #156.
+ * #106 is a primary set of control functions, used in combination with #107.
+ * Escapes into:
+ * C0: ESC 2/1 4/5 ("!E")
+ * This set is so short I can list it here:
+ * 0x08 BS BACKSPACE -- same as Unicode
+ * 0x0a LF LINE FEED -- same as Unicode
+ * 0x0c FF FORM FEED -- same as Unicode
+ * 0x0d CR CARRIAGE RETURN -- same as Unicode
+ * 0x0e LS1 LOCKING SHIFT ONE
+ * 0x0f LS0 LOCKING SHIFT ZERO
+ * 0x19 SS2 SINGLE SHIFT TWO
+ * 0x1a SUB SUBSTITUTE CHARACTER
+ * 0x1b ESC ESCAPE -- same as Unicode
+ * 0x1d SS3 SINGLE SHIFT THREE
+ * The LS1 and LS0 are two magical functions which, respectively, invoke
+ * the currently designated G1 or G0 set into positions 2/1 to 7/14
+ * The SS2 and SS3, respectively, invoke one character of the
+ * currently designated set G2 and G3.
+ * The SUB is wholly equivalent to U+001a (SUBSTITUTE)
+ * #107 is a supplementary set of control functions, used with #106.
+ * Escapes into:
+ * C1: ESC 2/2 4/8 ('"H')
+ * This set contains three special control codes:
+ * 0x8b PLD PARTIAL LINE DOWN -- similar to <SUB>
+ * 0x8c PLU PARTIAL LINE UP -- sumilar to <SUP>
+ * 0x9b CSI CONTROL SEQUENCE INTRODUCER
+ * This set is so out of world we can probably safely ignore it.
+ * #126 is a "Right-hand Part of the Latin/Greek Alphabet".
+ * Comprises of 90 characters, including accented letters.
+ * Escapes into:
+ * G1: ESC 2/13 4/6 ("-F")
+ * G2: ESC 2/14 4/6 (".F")
+ * G3: ESC 2/15 4/6 ("/F")
+ * Note: This Registration is a subset of ISO-IR 227.
+ * #144 is a "Cyrillic part of the Latin/Cyrillic Alphabet".
+ * Comprises of 95 characters.
+ * Escapes into:
+ * G1: ESC 2/13 4/12 ("-L")
+ * G2: ESC 2/14 4/12 (".L")
+ * G3: ESC 2/15 4/12 ("/L")
+ * #150 is a "Greek Primary Set of Graphic Characters".
+ * Comprises of 94 characters.
+ * Escapes into:
+ * G0: ESC 2/8 2/1 4/0 ("(!@")
+ * G1: ESC 2/9 2/1 4/0 (")!@")
+ * G2: ESC 2/10 2/1 4/0 ("*!@")
+ * G3: ESC 2/11 2/1 4/0 ("+!@")
+ * #153 is a "Basic Cyrillic Character Set for 8-bit codes".
+ * Comprises of 68 characters.
+ * Escapes into:
+ * G1: ESC 2/13 4/15 ("-O")
+ * G2: ESC 2/14 4/15 (".O")
+ * G3: ESC 2/15 4/15 ("/O")
+ * #156 is a "Supplementary Set of ISO/IEC 6937:1992" for use with #6
+ * Comprises of 87 characters.
+ * Escapes into:
+ * G1: ESC 2/13 5/2 ("-R")
+ * G2: ESC 2/14 5/2 (".R")
+ * G3: ESC 2/15 5/2 ("/R")
+ * #164 is a "Hebrew Supplementary Set of Graphic Characters"
+ * Comprises of 27 characters.
+ * Escapes into:
+ * G1: ESC 2/13 5/3 ("-S")
+ * G2: ESC 2/14 5/3 (".S")
+ * G3: ESC 2/15 5/3 ("/S")
+ * #165 is a set of "Codes of the Chinese graphic character set"
+ * Is a multiple-byte set of 8446 characters.
+ * Escapes into:
+ * G0: ESC 2/4 2/8 4/5 ("$(E")
+ * G1: ESC 2/4 2/9 4/5 ("$)E")
+ * G2: ESC 2/4 2/10 4/5 ("$*E")
+ * G3: ESC 2/4 2/11 4/5 ("$+E")
+ * #168 is a "Japanese Graphic Character Set for Information Interchange"
+ * A multiple-byte set of 6879 characters updated from #87.
+ * Escapes into:
+ * G0: ESC 2/6 4/0 ESC 2/4 4/2 ("&@" "$B")
+ * G1: ESC 2/6 4/0 ESC 2/4 2/9 4/2 ("&@" "$)B")
+ * G2: ESC 2/6 4/0 ESC 2/4 2/10 4/2 ("&@" "$*B")
+ * G3: ESC 2/6 4/0 ESC 2/4 2/11 4/2 ("&@" "$+B")
+ */
+
diff --git a/src/UTCTime.c b/src/UTCTime.c
index 2a27718..0abe1db 100644
--- a/src/UTCTime.c
+++ b/src/UTCTime.c
@@ -23,6 +23,11 @@ static ber_tlv_tag_t asn_DEF_UTCTime_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_per_constraints_t asn_DEF_UTCTime_constraints = {
+ { APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_UTCTime = {
"UTCTime",
"UTCTime",
@@ -33,7 +38,8 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_utf8,
UTCTime_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
@@ -41,7 +47,7 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
/ sizeof(asn_DEF_UTCTime_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_UTCTime_constraints,
0, 0, /* No members */
0 /* No specifics */
};
@@ -60,7 +66,7 @@ UTCTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
errno = EPERM; /* Just an unlikely error code */
tloc = asn_UT2time(st, 0, 0);
if(tloc == -1 && errno != EPERM) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: Invalid time format: %s (%s:%d)",
td->name, strerror(errno), __FILE__, __LINE__);
return -1;
diff --git a/src/UTF8String.c b/src/UTF8String.c
index e3f7388..7e73d77 100644
--- a/src/UTF8String.c
+++ b/src/UTF8String.c
@@ -23,7 +23,8 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
@@ -72,26 +73,26 @@ UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
switch(len) {
case U8E_EINVAL:
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given", td->name);
break;
case U8E_TRUNC:
- _ASN_CTFAIL(app_key, td,
+ _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,
+ _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,
+ _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,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: UTF-8 not minimal sequence (%s:%d)",
td->name, __FILE__, __LINE__);
break;
diff --git a/src/UniversalString.c b/src/UniversalString.c
index a39e569..7d16781 100644
--- a/src/UniversalString.c
+++ b/src/UniversalString.c
@@ -13,6 +13,16 @@ static ber_tlv_tag_t asn_DEF_UniversalString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (28 << 2)), /* [UNIVERSAL 28] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_OCTET_STRING_specifics_t asn_DEF_UniversalString_specs = {
+ sizeof(UniversalString_t),
+ offsetof(UniversalString_t, _asn_ctx),
+ ASN_OSUBV_U32 /* 32-bits character */
+};
+static asn_per_constraints_t asn_DEF_UniversalString_constraints = {
+ { APC_CONSTRAINED, 32, 32, 0, 2147483647 },
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_UniversalString = {
"UniversalString",
"UniversalString",
@@ -23,7 +33,8 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
OCTET_STRING_encode_der,
UniversalString_decode_xer, /* Convert from UTF-8 */
UniversalString_encode_xer, /* Convert into UTF-8 */
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
@@ -31,9 +42,9 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
/ sizeof(asn_DEF_UniversalString_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_UniversalString_constraints,
0, 0, /* No members */
- 0 /* No specifics */
+ &asn_DEF_UniversalString_specs
};
diff --git a/src/VideotexString.c b/src/VideotexString.c
index 5f5f33d..df7233e 100644
--- a/src/VideotexString.c
+++ b/src/VideotexString.c
@@ -22,7 +22,8 @@ asn_TYPE_descriptor_t asn_DEF_VideotexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VideotexString_tags,
sizeof(asn_DEF_VideotexString_tags)
diff --git a/src/VisibleString.c b/src/VisibleString.c
index 8796582..3487b6f 100644
--- a/src/VisibleString.c
+++ b/src/VisibleString.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
@@ -12,6 +12,11 @@ static ber_tlv_tag_t asn_DEF_VisibleString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
+static asn_per_constraints_t asn_DEF_VisibleString_constraints = {
+ { APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
+ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
+ 0, 0
+};
asn_TYPE_descriptor_t asn_DEF_VisibleString = {
"VisibleString",
"VisibleString",
@@ -22,7 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
@@ -30,7 +36,7 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
/ sizeof(asn_DEF_VisibleString_tags[0]),
- 0, /* No PER visible constraints */
+ &asn_DEF_VisibleString_constraints,
0, 0, /* No members */
0 /* No specifics */
};
@@ -52,7 +58,7 @@ VisibleString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
*/
for(; buf < end; buf++) {
if(*buf < 0x20 || *buf > 0x7e) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value byte %ld (%d) "
"not in VisibleString alphabet (%s:%d)",
td->name,
@@ -63,7 +69,7 @@ VisibleString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
}
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
diff --git a/src/constr_CHOICE.c b/src/constr_CHOICE.c
index b8d6fa9..a9eb719 100644
--- a/src/constr_CHOICE.c
+++ b/src/constr_CHOICE.c
@@ -1,10 +1,11 @@
/*
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <constr_CHOICE.h>
+#include <per_opentype.h>
/*
* Number of bytes left for this structure.
@@ -482,7 +483,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int present;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -501,7 +502,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
if(!memb_ptr) {
if(elm->optional)
return 0;
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: mandatory CHOICE element %s absent (%s:%d)",
td->name, elm->name, __FILE__, __LINE__);
return -1;
@@ -524,7 +525,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
return ret;
}
} else {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: no CHOICE element given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -871,8 +872,6 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
value += specs->ext_start;
if(value >= td->elements_count)
_ASN_DECODE_FAILED;
- ASN_DEBUG("NOT IMPLEMENTED YET");
- _ASN_DECODE_FAILED;
}
/* Adjust if canonical order is different from natural order */
@@ -892,11 +891,17 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
- rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
+ if(ct && ct->range_bits >= 0) {
+ rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ } else {
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
+ }
+
if(rv.code != RC_OK)
- ASN_DEBUG("Failed to decode %s in %s (CHOICE)",
- elm->name, td->name);
+ ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
+ elm->name, td->name, rv.code);
return rv;
}
@@ -951,18 +956,6 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
if(per_put_few_bits(po, 0, 1))
_ASN_ENCODE_FAILED;
- if(ct && ct->range_bits >= 0) {
- if(per_put_few_bits(po, present, ct->range_bits))
- _ASN_ENCODE_FAILED;
- } else {
- if(specs->ext_start == -1)
- _ASN_ENCODE_FAILED;
- if(uper_put_nsnnwn(po, present - specs->ext_start))
- _ASN_ENCODE_FAILED;
- ASN_DEBUG("NOT IMPLEMENTED YET");
- _ASN_ENCODE_FAILED;
- }
-
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
@@ -972,8 +965,24 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
memb_ptr = (char *)sptr + elm->memb_offset;
}
- return elm->type->uper_encoder(elm->type, elm->per_constraints,
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, present, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+
+ return elm->type->uper_encoder(elm->type, elm->per_constraints,
memb_ptr, po);
+ } else {
+ asn_enc_rval_t rval;
+ if(specs->ext_start == -1)
+ _ASN_ENCODE_FAILED;
+ if(uper_put_nsnnwn(po, present - specs->ext_start))
+ _ASN_ENCODE_FAILED;
+ if(uper_open_type_put(elm->type, elm->per_constraints,
+ memb_ptr, po))
+ _ASN_ENCODE_FAILED;
+ rval.encoded = 0;
+ _ASN_ENCODED_OK(rval);
+ }
}
diff --git a/src/constr_SEQUENCE.c b/src/constr_SEQUENCE.c
index b769434..db3c925 100644
--- a/src/constr_SEQUENCE.c
+++ b/src/constr_SEQUENCE.c
@@ -1,10 +1,11 @@
/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <constr_SEQUENCE.h>
+#include <per_opentype.h>
/*
* Number of bytes left for this structure.
@@ -346,7 +347,8 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* or an extension (...),
* or an end of the indefinite-length structure.
*/
- if(!IN_EXTENSION_GROUP(specs, edx)) {
+ if(!IN_EXTENSION_GROUP(specs,
+ edx + elements[edx].optional)) {
ASN_DEBUG("Unexpected tag %s (at %d)",
ber_tlv_tag_string(tlv_tag), edx);
ASN_DEBUG("Expected tag %s (%s)%s",
@@ -358,7 +360,10 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
} else {
/* Skip this tag */
ssize_t skip;
+ edx += elements[edx].optional;
+ ASN_DEBUG("Skipping unexpected %s (at %d)",
+ ber_tlv_tag_string(tlv_tag), edx);
skip = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tag_len,
@@ -976,7 +981,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int edx;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -994,7 +999,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
if(!memb_ptr) {
if(elm->optional)
continue;
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: mandatory element %s absent (%s:%d)",
td->name, elm->name, __FILE__, __LINE__);
return -1;
@@ -1027,7 +1032,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
void *st = *sptr; /* Target structure. */
- int extpresent = 0; /* Extension additions are present */
+ int extpresent; /* Extension additions are present */
uint8_t *opres; /* Presence of optional root members */
asn_per_data_t opmd;
asn_dec_rval_t rv;
@@ -1049,9 +1054,12 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(specs->ext_before >= 0) {
extpresent = per_get_few_bits(pd, 1);
if(extpresent < 0) _ASN_DECODE_STARVED;
+ } else {
+ extpresent = 0;
}
/* Prepare a place and read-in the presence bitmap */
+ memset(&opmd, 0, sizeof(opmd));
if(specs->roms_count) {
opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
if(!opres) _ASN_DECODE_FAILED;
@@ -1061,24 +1069,24 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
_ASN_DECODE_STARVED;
}
opmd.buffer = opres;
- opmd.nboff = 0;
opmd.nbits = specs->roms_count;
ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
td->name, specs->roms_count, *opres);
} else {
opres = 0;
- memset(&opmd, 0, sizeof opmd);
}
/*
* Get the sequence ROOT elements.
*/
- for(edx = 0; edx < ((specs->ext_before < 0)
- ? td->elements_count : specs->ext_before + 1); edx++) {
+ for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
@@ -1101,6 +1109,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
FREEMEM(opres);
_ASN_DECODE_FAILED;
}
+ ASN_DEBUG("Filled-in default");
}
/* The member is just not present */
continue;
@@ -1120,50 +1129,176 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
}
+ /* Optionality map is not needed anymore */
+ FREEMEM(opres);
+
/*
* Deal with extensions.
*/
if(extpresent) {
- ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name);
- _ASN_DECODE_FAILED;
- } else {
- for(edx = specs->roms_count; edx < specs->roms_count
- + specs->aoms_count; edx++) {
- asn_TYPE_member_t *elm = &td->elements[edx];
- void *memb_ptr; /* Pointer to the member */
- void **memb_ptr2; /* Pointer to that pointer */
+ ssize_t bmlength;
+ uint8_t *epres; /* Presence of extension members */
+ asn_per_data_t epmd;
- if(!elm->default_value) continue;
+ bmlength = uper_get_nslength(pd);
+ if(bmlength < 0) _ASN_DECODE_STARVED;
- /* Fetch the pointer to this member */
- if(elm->flags & ATF_POINTER) {
- memb_ptr2 = (void **)((char *)st
- + elm->memb_offset);
- } else {
- memb_ptr = (char *)st + elm->memb_offset;
- memb_ptr2 = &memb_ptr;
- }
+ ASN_DEBUG("Extensions %d present in %s", bmlength, td->name);
+
+ epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
+ if(!epres) _ASN_DECODE_STARVED;
+
+ /* Get the extensions map */
+ if(per_get_many_bits(pd, epres, 0, bmlength))
+ _ASN_DECODE_STARVED;
+
+ memset(&epmd, 0, sizeof(epmd));
+ epmd.buffer = epres;
+ epmd.nbits = bmlength;
+ ASN_DEBUG("Read in extensions bitmap for %s of %d bits (%x..)",
+ td->name, bmlength, *epres);
- /* Set default value */
- if(elm->default_value(1, memb_ptr2)) {
- FREEMEM(opres);
- _ASN_DECODE_FAILED;
+ /* Go over extensions and read them in */
+ for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ if(!IN_EXTENSION_GROUP(specs, edx)) {
+ ASN_DEBUG("%d is not extension", edx);
+ continue;
+ }
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (void *)((char *)st + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ present = per_get_few_bits(&epmd, 1);
+ if(present <= 0) {
+ if(present < 0) break; /* No more extensions */
+ continue;
+ }
+
+ ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ FREEMEM(epres);
+ return rv;
+ }
+ }
+
+ /* Skip over overflow extensions which aren't present
+ * in this system's version of the protocol */
+ for(;;) {
+ ASN_DEBUG("Getting overflow extensions");
+ switch(per_get_few_bits(&epmd, 1)) {
+ case -1: break;
+ case 0: continue;
+ default:
+ if(uper_open_type_skip(opt_codec_ctx, pd)) {
+ FREEMEM(epres);
+ _ASN_DECODE_STARVED;
+ }
}
+ break;
+ }
+
+ FREEMEM(epres);
+ }
+
+ /* Fill DEFAULT members in extensions */
+ for(edx = specs->roms_count; edx < specs->roms_count
+ + specs->aoms_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void **memb_ptr2; /* Pointer to member pointer */
+
+ if(!elm->default_value) continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st
+ + elm->memb_offset);
+ if(*memb_ptr2) continue;
+ } else {
+ continue; /* Extensions are all optionals */
+ }
+
+ /* Set default value */
+ if(elm->default_value(1, memb_ptr2)) {
+ _ASN_DECODE_FAILED;
}
}
rv.consumed = 0;
rv.code = RC_OK;
- FREEMEM(opres);
return rv;
}
+static int
+SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
+ asn_per_outp_t *po1, asn_per_outp_t *po2) {
+ asn_SEQUENCE_specifics_t *specs
+ = (asn_SEQUENCE_specifics_t *)td->specifics;
+ int exts_present = 0;
+ int exts_count = 0;
+ int edx;
+
+ if(specs->ext_before < 0)
+ return 0;
+
+ /* Find out which extensions are present */
+ for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ if(!IN_EXTENSION_GROUP(specs, edx)) {
+ ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx);
+ continue;
+ }
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ present = 1;
+ }
+
+ ASN_DEBUG("checking %s (@%d) present => %d",
+ elm->type->name, edx, present);
+ exts_count++;
+ exts_present += present;
+
+ /* Encode as presence marker */
+ if(po1 && per_put_few_bits(po1, present, 1))
+ return -1;
+ /* Encode as open type field */
+ if(po2 && present && uper_open_type_put(elm->type,
+ elm->per_constraints, *memb_ptr2, po2))
+ return -1;
+
+ }
+
+ return exts_present ? exts_count : 0;
+}
+
asn_enc_rval_t
SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_SEQUENCE_specifics_t *specs
= (asn_SEQUENCE_specifics_t *)td->specifics;
asn_enc_rval_t er;
+ int n_extensions;
int edx;
int i;
@@ -1175,8 +1310,18 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
er.encoded = 0;
ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
- if(specs->ext_before >= 0)
- _ASN_ENCODE_FAILED; /* We don't encode extensions yet */
+
+
+ /*
+ * X.691#18.1 Whether structure is extensible
+ * and whether to encode extensions
+ */
+ if(specs->ext_before >= 0) {
+ n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
+ per_put_few_bits(po, n_extensions ? 1 : 0, 1);
+ } else {
+ n_extensions = 0; /* There are no extensions to encode */
+ }
/* Encode a presence bitmap */
for(i = 0; i < specs->roms_count; i++) {
@@ -1212,14 +1357,21 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
}
/*
- * Get the sequence ROOT elements.
+ * Encode the sequence ROOT elements.
*/
- for(edx = 0; edx < ((specs->ext_before < 0)
- ? td->elements_count : specs->ext_before + 1); edx++) {
+ ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
+ for(edx = 0; edx < ((specs->ext_after < 0)
+ ? td->elements_count : specs->ext_before - 1); edx++) {
+
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
+ ASN_DEBUG("About to encode %s", elm->type->name);
+
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
@@ -1240,12 +1392,32 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
continue;
+ ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
er = elm->type->uper_encoder(elm->type, elm->per_constraints,
*memb_ptr2, po);
if(er.encoded == -1)
return er;
}
+ /* No extensions to encode */
+ if(!n_extensions) _ASN_ENCODED_OK(er);
+
+ ASN_DEBUG("Length of %d bit-map", n_extensions);
+ /* #18.8. Write down the presence bit-map length. */
+ if(uper_put_nslength(po, n_extensions))
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Bit-map of %d elements", n_extensions);
+ /* #18.7. Encoding the extensions presence bit-map. */
+ /* TODO: act upon NOTE in #18.7 for canonical PER */
+ if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Writing %d extensions", n_extensions);
+ /* #18.9. Encode extensions as open type fields. */
+ if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
_ASN_ENCODED_OK(er);
}
diff --git a/src/constr_SET.c b/src/constr_SET.c
index 9b6012f..ecf5661 100644
--- a/src/constr_SET.c
+++ b/src/constr_SET.c
@@ -6,12 +6,6 @@
#include <asn_internal.h>
#include <constr_SET.h>
-#ifndef WIN32
-#include <netinet/in.h> /* for ntohl() */
-#else
-#include <winsock2.h> /* for ntohl() */
-#endif
-
/* Check that all the mandatory members are present */
static int _SET_is_populated(asn_TYPE_descriptor_t *td, void *st);
@@ -411,7 +405,7 @@ _SET_is_populated(asn_TYPE_descriptor_t *td, void *st) {
midx = edx/(8 * sizeof(specs->_mandatory_elements[0]));
pres = ((unsigned int *)((char *)st+specs->pres_offset))[midx];
- must = ntohl(specs->_mandatory_elements[midx]);
+ must = sys_ntohl(specs->_mandatory_elements[midx]);
if((pres & must) == must) {
/*
@@ -945,7 +939,7 @@ SET_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int edx;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -963,7 +957,7 @@ SET_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
if(!memb_ptr) {
if(elm->optional)
continue;
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: mandatory element %s absent (%s:%d)",
td->name, elm->name, __FILE__, __LINE__);
return -1;
diff --git a/src/constr_SET_OF.c b/src/constr_SET_OF.c
index 09f27db..11eac57 100644
--- a/src/constr_SET_OF.c
+++ b/src/constr_SET_OF.c
@@ -227,6 +227,8 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
/* Fall through */
case RC_FAIL: /* Fatal error */
+ ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+ ctx->ptr = 0;
RETURN(RC_FAIL);
} /* switch(rval) */
@@ -787,8 +789,10 @@ SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
void
SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr) {
+ asn_SET_OF_specifics_t *specs;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
+ asn_struct_ctx_t *ctx; /* Decoder context */
int i;
/*
@@ -804,6 +808,13 @@ SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
asn_set_empty(list); /* Remove (list->array) */
+ specs = (asn_SET_OF_specifics_t *)td->specifics;
+ ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
+ if(ctx->ptr) {
+ ASN_STRUCT_FREE(*elm->type, ctx->ptr);
+ ctx->ptr = 0;
+ }
+
if(!contents_only) {
FREEMEM(ptr);
}
@@ -819,7 +830,7 @@ SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int i;
if(!sptr) {
- _ASN_CTFAIL(app_key, td,
+ _ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
@@ -921,7 +932,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ASN_DEBUG("Failed to add element into %s",
td->name);
/* Fall through */
- rv.code == RC_FAIL;
+ rv.code = RC_FAIL;
} else {
ASN_DEBUG("Failed decoding %s of %s (SET OF)",
elm->type->name, td->name);
diff --git a/src/per_decoder.c b/src/per_decoder.c
index 16dee36..2b3d2e2 100644
--- a/src/per_decoder.c
+++ b/src/per_decoder.c
@@ -2,6 +2,40 @@
#include <asn_internal.h>
#include <per_decoder.h>
+/*
+ * Decode a "Production of a complete encoding", X.691#10.1.
+ * The complete encoding contains at least one byte, and is an integral
+ * multiple of 8 bytes.
+ */
+asn_dec_rval_t
+uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+ asn_dec_rval_t rval;
+
+ rval = uper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
+ if(rval.consumed) {
+ /*
+ * We've always given 8-aligned data,
+ * so convert bits to integral bytes.
+ */
+ rval.consumed += 7;
+ rval.consumed >>= 3;
+ } else if(rval.code == RC_OK) {
+ if(size) {
+ if(((uint8_t *)buffer)[0] == 0) {
+ rval.consumed = 1; /* 1 byte */
+ } else {
+ ASN_DEBUG("Expecting single zeroed byte");
+ rval.code = RC_FAIL;
+ }
+ } else {
+ /* Must contain at least 8 bits. */
+ rval.code = RC_WMORE;
+ }
+ }
+
+ return rval;
+}
+
asn_dec_rval_t
uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
asn_codec_ctx_t s_codec_ctx;
@@ -30,6 +64,7 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
}
/* Fill in the position indicator */
+ memset(&pd, 0, sizeof(pd));
pd.buffer = (const uint8_t *)buffer;
pd.nboff = skip_bits;
pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
@@ -46,6 +81,9 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
+ ASN_DEBUG("PER decoding consumed %d, counted %d",
+ rval.consumed, pd.moved);
+ assert(rval.consumed == pd.moved);
} else {
/* PER codec is not a restartable */
rval.consumed = 0;
diff --git a/src/per_encoder.c b/src/per_encoder.c
index 614dd23..f4bace0 100644
--- a/src/per_encoder.c
+++ b/src/per_encoder.c
@@ -2,41 +2,11 @@
#include <asn_internal.h>
#include <per_encoder.h>
-/* Flush partially filled buffer */
-static int _uper_encode_flush_outp(asn_per_outp_t *po);
+static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
asn_enc_rval_t
uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
- asn_per_outp_t po;
- asn_enc_rval_t er;
-
- /*
- * Invoke type-specific encoder.
- */
- if(!td || !td->uper_encoder)
- _ASN_ENCODE_FAILED; /* PER is not compiled in */
-
- po.buffer = po.tmpspace;
- po.nboff = 0;
- po.nbits = 8 * sizeof(po.tmpspace);
- po.outper = cb;
- po.op_key = app_key;
- po.flushed_bytes = 0;
-
- er = td->uper_encoder(td, 0, sptr, &po);
- if(er.encoded != -1) {
- size_t bits_to_flush;
-
- bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
-
- /* Set number of bits encoded to a firm value */
- er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
-
- if(_uper_encode_flush_outp(&po))
- _ASN_ENCODE_FAILED;
- }
-
- return er;
+ return uper_encode_internal(td, 0, sptr, cb, app_key);
}
/*
@@ -63,20 +33,71 @@ asn_enc_rval_t
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
- /*
- * Invoke type-specific encoder.
- */
- if(!td || !td->uper_encoder)
- _ASN_ENCODE_FAILED; /* PER is not compiled in */
-
key.buffer = buffer;
key.left = buffer_size;
- ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
+ if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
- return uper_encode(td, sptr, encode_to_buffer_cb, &key);
+ return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
}
+typedef struct enc_dyn_arg {
+ void *buffer;
+ size_t length;
+ size_t allocated;
+} enc_dyn_arg;
+static int
+encode_dyn_cb(const void *buffer, size_t size, void *key) {
+ enc_dyn_arg *arg = key;
+ if(arg->length + size >= arg->allocated) {
+ void *p;
+ arg->allocated = arg->allocated ? (arg->allocated << 2) : size;
+ p = REALLOC(arg->buffer, arg->allocated);
+ if(!p) {
+ FREEMEM(arg->buffer);
+ memset(arg, 0, sizeof(*arg));
+ return -1;
+ }
+ arg->buffer = p;
+ }
+ memcpy(((char *)arg->buffer) + arg->length, buffer, size);
+ arg->length += size;
+ return 0;
+}
+ssize_t
+uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) {
+ asn_enc_rval_t er;
+ enc_dyn_arg key;
+
+ memset(&key, 0, sizeof(key));
+
+ er = uper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key);
+ switch(er.encoded) {
+ case -1:
+ FREEMEM(key.buffer);
+ return -1;
+ case 0:
+ FREEMEM(key.buffer);
+ key.buffer = MALLOC(1);
+ if(key.buffer) {
+ *(char *)key.buffer = '\0';
+ *buffer_r = key.buffer;
+ return 1;
+ } else {
+ return -1;
+ }
+ default:
+ *buffer_r = key.buffer;
+ ASN_DEBUG("Complete encoded in %d bits", er.encoded);
+ return ((er.encoded + 7) >> 3);
+ }
+}
+
+/*
+ * Internally useful functions.
+ */
+
+/* Flush partially filled buffer */
static int
_uper_encode_flush_outp(asn_per_outp_t *po) {
uint8_t *buf;
@@ -93,3 +114,38 @@ _uper_encode_flush_outp(asn_per_outp_t *po) {
return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
}
+
+static asn_enc_rval_t
+uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_per_outp_t po;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->uper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 8 * sizeof(po.tmpspace);
+ po.outper = cb;
+ po.op_key = app_key;
+ po.flushed_bytes = 0;
+
+ er = td->uper_encoder(td, constraints, sptr, &po);
+ if(er.encoded != -1) {
+ size_t bits_to_flush;
+
+ bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
+
+ /* Set number of bits encoded to a firm value */
+ er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
+
+ if(_uper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+ }
+
+ return er;
+}
+
diff --git a/src/per_opentype.c b/src/per_opentype.c
new file mode 100644
index 0000000..c749c8c
--- /dev/null
+++ b/src/per_opentype.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <per_support.h>
+#include <constr_TYPE.h>
+#include <per_opentype.h>
+
+typedef struct uper_ugot_key {
+ asn_per_data_t oldpd; /* Old per data source */
+ size_t unclaimed;
+ size_t ot_moved; /* Number of bits moved by OT processing */
+ int repeat;
+} uper_ugot_key;
+
+static int uper_ugot_refill(asn_per_data_t *pd);
+static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
+static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
+
+int asn_debug_indent;
+
+/*
+ * Encode an "open type field".
+ * #10.1, #10.2
+ */
+int
+uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ void *buf;
+ void *bptr;
+ ssize_t size;
+ size_t toGo;
+
+ ASN_DEBUG("Open type put %s ...", td->name);
+
+ size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
+ if(size <= 0) return -1;
+
+ for(bptr = buf, toGo = size; toGo;) {
+ ssize_t maySave = uper_put_length(po, toGo);
+ if(maySave < 0) break;
+ if(per_put_many_bits(po, bptr, maySave * 8)) break;
+ bptr = (char *)bptr + maySave;
+ toGo -= maySave;
+ }
+
+ FREEMEM(buf);
+ if(toGo) return -1;
+
+ ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
+ td->name, size);
+
+ return 0;
+}
+
+static asn_dec_rval_t
+uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ ssize_t chunk_bytes;
+ int repeat;
+ uint8_t *buf = 0;
+ size_t bufLen = 0;
+ size_t bufSize = 0;
+ asn_per_data_t spd;
+ size_t padding;
+
+ _ASN_STACK_OVERFLOW_CHECK(ctx);
+
+ ASN_DEBUG("Getting open type %s...", td->name);
+
+ do {
+ chunk_bytes = uper_get_length(pd, -1, &repeat);
+ if(chunk_bytes < 0) {
+ FREEMEM(buf);
+ _ASN_DECODE_STARVED;
+ }
+ if(bufLen + chunk_bytes > bufSize) {
+ void *ptr;
+ bufSize = chunk_bytes + (bufSize << 2);
+ ptr = REALLOC(buf, bufSize);
+ if(!ptr) {
+ FREEMEM(buf);
+ _ASN_DECODE_FAILED;
+ }
+ buf = ptr;
+ }
+ if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
+ FREEMEM(buf);
+ _ASN_DECODE_STARVED;
+ }
+ bufLen += chunk_bytes;
+ } while(repeat);
+
+ ASN_DEBUG("Getting open type %s encoded in %d bytes", td->name,
+ bufLen);
+
+ memset(&spd, 0, sizeof(spd));
+ spd.buffer = buf;
+ spd.nbits = bufLen << 3;
+
+ asn_debug_indent += 4;
+ rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
+ asn_debug_indent -= 4;
+
+ if(rv.code == RC_OK) {
+ /* Check padding validity */
+ padding = spd.nbits - spd.nboff;
+ if(padding < 8 && per_get_few_bits(&spd, padding) == 0) {
+ /* Everything is cool */
+ FREEMEM(buf);
+ return rv;
+ }
+ FREEMEM(buf);
+ if(padding >= 8) {
+ ASN_DEBUG("Too large padding %d in open type", padding);
+ _ASN_DECODE_FAILED;
+ } else {
+ ASN_DEBUG("Non-zero padding");
+ _ASN_DECODE_FAILED;
+ }
+ } else {
+ FREEMEM(buf);
+ /* rv.code could be RC_WMORE, nonsense in this context */
+ rv.code = RC_FAIL; /* Noone would give us more */
+ }
+
+ return rv;
+}
+
+static asn_dec_rval_t GCC_NOTUSED
+uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ uper_ugot_key arg;
+ asn_dec_rval_t rv;
+ ssize_t padding;
+
+ _ASN_STACK_OVERFLOW_CHECK(ctx);
+
+ ASN_DEBUG("Getting open type %s from %s", td->name,
+ per_data_string(pd));
+ arg.oldpd = *pd;
+ arg.unclaimed = 0;
+ arg.ot_moved = 0;
+ arg.repeat = 1;
+ pd->refill = uper_ugot_refill;
+ pd->refill_key = &arg;
+ pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
+ pd->moved = 0; /* This now counts the open type size in bits */
+
+ asn_debug_indent += 4;
+ rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
+ asn_debug_indent -= 4;
+
+#define UPDRESTOREPD do { \
+ /* buffer and nboff are valid, preserve them. */ \
+ pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
+ pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
+ pd->refill = arg.oldpd.refill; \
+ pd->refill_key = arg.oldpd.refill_key; \
+ } while(0)
+
+ if(rv.code != RC_OK) {
+ UPDRESTOREPD;
+ return rv;
+ }
+
+ ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d"
+ , td->name,
+ per_data_string(pd),
+ per_data_string(&arg.oldpd),
+ arg.unclaimed, arg.repeat);
+
+ padding = pd->moved % 8;
+ if(padding) {
+ int32_t pvalue;
+ if(padding > 7) {
+ ASN_DEBUG("Too large padding %d in open type",
+ padding);
+ rv.code = RC_FAIL;
+ UPDRESTOREPD;
+ return rv;
+ }
+ padding = 8 - padding;
+ ASN_DEBUG("Getting padding of %d bits", padding);
+ pvalue = per_get_few_bits(pd, padding);
+ switch(pvalue) {
+ case -1:
+ ASN_DEBUG("Padding skip failed");
+ UPDRESTOREPD;
+ _ASN_DECODE_STARVED;
+ case 0: break;
+ default:
+ ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
+ padding, (int)pvalue);
+ UPDRESTOREPD;
+ _ASN_DECODE_FAILED;
+ }
+ }
+ if(pd->nboff != pd->nbits) {
+ ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
+ per_data_string(pd), per_data_string(&arg.oldpd));
+ if(1) {
+ UPDRESTOREPD;
+ _ASN_DECODE_FAILED;
+ } else {
+ arg.unclaimed += pd->nbits - pd->nboff;
+ }
+ }
+
+ /* Adjust pd back so it points to original data */
+ UPDRESTOREPD;
+
+ /* Skip data not consumed by the decoder */
+ if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
+ if(arg.unclaimed) {
+ switch(per_skip_bits(pd, arg.unclaimed)) {
+ case -1:
+ ASN_DEBUG("Claim of %d failed", arg.unclaimed);
+ _ASN_DECODE_STARVED;
+ case 0:
+ ASN_DEBUG("Got claim of %d", arg.unclaimed);
+ break;
+ default:
+ /* Padding must be blank */
+ ASN_DEBUG("Non-blank unconsumed padding");
+ _ASN_DECODE_FAILED;
+ }
+ arg.unclaimed = 0;
+ }
+
+ if(arg.repeat) {
+ ASN_DEBUG("Not consumed the whole thing");
+ rv.code = RC_FAIL;
+ return rv;
+ }
+
+ return rv;
+}
+
+
+asn_dec_rval_t
+uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+
+ return uper_open_type_get_simple(ctx, td, constraints,
+ sptr, pd);
+
+}
+
+int
+uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
+ asn_TYPE_descriptor_t s_td;
+ asn_dec_rval_t rv;
+
+ s_td.name = "<unknown extension>";
+ s_td.uper_decoder = uper_sot_suck;
+
+ rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
+ if(rv.code != RC_OK)
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Internal functions.
+ */
+
+static asn_dec_rval_t
+uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+
+ (void)ctx;
+ (void)td;
+ (void)constraints;
+ (void)sptr;
+
+ while(per_get_few_bits(pd, 24) >= 0);
+
+ rv.code = RC_OK;
+ rv.consumed = pd->moved;
+
+ return rv;
+}
+
+static int
+uper_ugot_refill(asn_per_data_t *pd) {
+ uper_ugot_key *arg = pd->refill_key;
+ ssize_t next_chunk_bytes, next_chunk_bits;
+ ssize_t avail;
+
+ asn_per_data_t *oldpd = &arg->oldpd;
+
+ ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d",
+ pd->moved, oldpd->moved);
+
+ /* Advance our position to where pd is */
+ oldpd->buffer = pd->buffer;
+ oldpd->nboff = pd->nboff;
+ oldpd->nbits -= pd->moved - arg->ot_moved;
+ oldpd->moved += pd->moved - arg->ot_moved;
+ arg->ot_moved = pd->moved;
+
+ if(arg->unclaimed) {
+ /* Refill the container */
+ if(per_get_few_bits(oldpd, 1))
+ return -1;
+ if(oldpd->nboff == 0) {
+ assert(0);
+ return -1;
+ }
+ pd->buffer = oldpd->buffer;
+ pd->nboff = oldpd->nboff - 1;
+ pd->nbits = oldpd->nbits;
+ ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
+ return 0;
+ }
+
+ if(!arg->repeat) {
+ ASN_DEBUG("Want more but refill doesn't have it");
+ return -1;
+ }
+
+ next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
+ ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
+ next_chunk_bytes, oldpd->moved, arg->repeat);
+ if(next_chunk_bytes < 0) return -1;
+ if(next_chunk_bytes == 0) {
+ pd->refill = 0; /* No more refills, naturally */
+ assert(!arg->repeat); /* Implementation guarantee */
+ }
+ next_chunk_bits = next_chunk_bytes << 3;
+ avail = oldpd->nbits - oldpd->nboff;
+ if(avail >= next_chunk_bits) {
+ pd->nbits = oldpd->nboff + next_chunk_bits;
+ arg->unclaimed = 0;
+ ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
+ next_chunk_bits, oldpd->moved,
+ oldpd->nboff, oldpd->nbits,
+ oldpd->nbits - oldpd->nboff);
+ } else {
+ pd->nbits = oldpd->nbits;
+ arg->unclaimed = next_chunk_bits - avail;
+ ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
+ }
+ pd->buffer = oldpd->buffer;
+ pd->nboff = oldpd->nboff;
+ ASN_DEBUG("Refilled pd%s old%s",
+ per_data_string(pd), per_data_string(oldpd));
+ return 0;
+}
+
+static int
+per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
+ int hasNonZeroBits = 0;
+ while(skip_nbits > 0) {
+ int skip;
+ if(skip_nbits < skip)
+ skip = skip_nbits;
+ else
+ skip = 24;
+ skip_nbits -= skip;
+
+ switch(per_get_few_bits(pd, skip)) {
+ case -1: return -1; /* Starving */
+ case 0: continue; /* Skipped empty space */
+ default: hasNonZeroBits = 1; continue;
+ }
+ }
+ return hasNonZeroBits;
+}
diff --git a/src/per_support.c b/src/per_support.c
index c834419..e8299c7 100644
--- a/src/per_support.c
+++ b/src/per_support.c
@@ -1,25 +1,66 @@
/*
- * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_system.h>
#include <asn_internal.h>
#include <per_support.h>
+char *
+per_data_string(asn_per_data_t *pd) {
+ static char buf[2][32];
+ static int n;
+ n = (n+1) % 2;
+ snprintf(buf[n], sizeof(buf),
+ "{m=%d span %+d[%d..%d] (%d)}",
+ pd->moved,
+ (((int)pd->buffer) & 0xf),
+ pd->nboff, pd->nbits,
+ pd->nbits - pd->nboff);
+ return buf[n];
+}
+
+void
+per_get_undo(asn_per_data_t *pd, int nbits) {
+ if((ssize_t)pd->nboff < nbits) {
+ assert((ssize_t)pd->nboff < nbits);
+ } else {
+ pd->nboff -= nbits;
+ pd->moved -= nbits;
+ }
+}
+
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
*/
int32_t
per_get_few_bits(asn_per_data_t *pd, int nbits) {
size_t off; /* Next after last bit offset */
+ ssize_t nleft; /* Number of bits left in this stream */
uint32_t accum;
const uint8_t *buf;
- if(nbits < 0 || pd->nboff + nbits > pd->nbits)
+ if(nbits < 0)
return -1;
- ASN_DEBUG("[PER get %d bits from %p+%d bits]",
- nbits, pd->buffer, pd->nboff);
+ nleft = pd->nbits - pd->nboff;
+ if(nbits > nleft) {
+ int32_t tailv, vhead;
+ if(!pd->refill || nbits > 31) return -1;
+ /* Accumulate unused bytes before refill */
+ ASN_DEBUG("Obtain the rest %d bits (want %d)", nleft, nbits);
+ tailv = per_get_few_bits(pd, nleft);
+ if(tailv < 0) return -1;
+ /* Refill (replace pd contents with new data) */
+ if(pd->refill(pd))
+ return -1;
+ nbits -= nleft;
+ vhead = per_get_few_bits(pd, nbits);
+ /* Combine the rest of previous pd with the head of new one */
+ tailv = (tailv << nbits) | vhead; /* Could == -1 */
+ return tailv;
+ }
/*
* Normalize position indicator.
@@ -29,7 +70,9 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
pd->nbits -= (pd->nboff & ~0x07);
pd->nboff &= 0x07;
}
- off = (pd->nboff += nbits);
+ pd->moved += nbits;
+ pd->nboff += nbits;
+ off = pd->nboff;
buf = pd->buffer;
/*
@@ -47,15 +90,29 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
else if(nbits <= 31) {
asn_per_data_t tpd = *pd;
/* Here are we with our 31-bits limit plus 1..7 bits offset. */
- tpd.nboff -= nbits;
+ per_get_undo(&tpd, nbits);
+ /* The number of available bits in the stream allow
+ * for the following operations to take place without
+ * invoking the ->refill() function */
accum = per_get_few_bits(&tpd, nbits - 24) << 24;
accum |= per_get_few_bits(&tpd, 24);
} else {
- pd->nboff -= nbits; /* Oops, revert back */
+ per_get_undo(pd, nbits);
return -1;
}
- return (accum & (((uint32_t)1 << nbits) - 1));
+ accum &= (((uint32_t)1 << nbits) - 1);
+
+ ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+d[%d..%d]:%02x (%d) => 0x%x]",
+ nbits, nleft,
+ pd->moved,
+ (((int)pd->buffer) & 0xf),
+ pd->nboff, pd->nbits,
+ pd->buffer[0],
+ pd->nbits - pd->nboff,
+ (int)accum);
+
+ return accum;
}
/*
@@ -130,6 +187,30 @@ uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
}
/*
+ * Get the normally small length "n".
+ * This procedure used to decode length of extensions bit-maps
+ * for SET and SEQUENCE types.
+ */
+ssize_t
+uper_get_nslength(asn_per_data_t *pd) {
+ ssize_t length;
+
+ ASN_DEBUG("Getting normally small length");
+
+ if(per_get_few_bits(pd, 1) == 0) {
+ length = per_get_few_bits(pd, 6) + 1;
+ if(length <= 0) return -1;
+ ASN_DEBUG("l=%d", length);
+ return length;
+ } else {
+ int repeat;
+ length = uper_get_length(pd, -1, &repeat);
+ if(length >= 0 && !repeat) return length;
+ return -1; /* Error, or do not support >16K extensions */
+ }
+}
+
+/*
* Get the normally small non-negative whole number.
* X.691, #10.6
*/
@@ -193,8 +274,8 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
- ASN_DEBUG("[PER put %d bits to %p+%d bits]",
- obits, po->buffer, po->nboff);
+ ASN_DEBUG("[PER put %d bits %x to %p+%d bits]",
+ obits, (int)bits, po->buffer, po->nboff);
/*
* Normalize position indicator.
@@ -210,7 +291,9 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
*/
if(po->nboff + obits > po->nbits) {
int complete_bytes = (po->buffer - po->tmpspace);
- if(po->outper(po->buffer, complete_bytes, po->op_key) < 0)
+ ASN_DEBUG("[PER output %d complete + %d]",
+ complete_bytes, po->flushed_bytes);
+ if(po->outper(po->tmpspace, complete_bytes, po->op_key) < 0)
return -1;
if(po->nboff)
po->tmpspace[0] = po->buffer[0];
@@ -229,7 +312,8 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
/* Clear data of debris before meaningful bits */
bits &= (((uint32_t)1 << obits) - 1);
- ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits,
+ ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits,
+ (int)bits, (int)bits,
po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
if(off <= 8) /* Completely within 1 byte */
@@ -258,7 +342,7 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
}
ASN_DEBUG("[PER out %u/%x => %02x buf+%d]",
- bits, bits, buf[0], po->buffer - po->tmpspace);
+ (int)bits, (int)bits, buf[0], po->buffer - po->tmpspace);
return 0;
}
@@ -316,3 +400,26 @@ uper_put_length(asn_per_outp_t *po, size_t length) {
? -1 : (ssize_t)(length << 14);
}
+
+/*
+ * Put the normally small length "n" into the stream.
+ * This procedure used to encode length of extensions bit-maps
+ * for SET and SEQUENCE types.
+ */
+int
+uper_put_nslength(asn_per_outp_t *po, size_t length) {
+
+ if(length <= 64) {
+ /* #10.9.3.4 */
+ if(length == 0) return -1;
+ return per_put_few_bits(po, length-1, 7) ? -1 : 0;
+ } else {
+ if(uper_put_length(po, length) != (ssize_t)length) {
+ /* This might happen in case of >16K extensions */
+ return -1;
+ }
+ }
+
+ return 0;
+}
+