diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index a125219982ea6d6cc0c7b1b93d3500bbd515b06b..6bebc2d6558f66dd3580b65e34b389015ddffc21 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -247,6 +247,7 @@ endif (${RTAI}) # New C code source file, cmake must be re-run (instead of re-running make only) ############# set(asn1c_call "${OPENAIR_CMAKE}/tools/generate_asn1") +set(fix_asn1c_call "${OPENAIR_CMAKE}/tools/fix_asn1") set(asn1_generated_dir ${OPENAIR_BIN_DIR}) set(protoc_call "${OPENAIR_CMAKE}/tools/generate_protobuf") @@ -269,6 +270,15 @@ if(NOT EXISTS ${asn1c_call}) message( FATAL_ERROR "The script ${asn1c_call} must be present" ) endif(NOT EXISTS ${asn1c_call}) execute_process(COMMAND ${asn1c_call} ${RRC_FULL_DIR} ${RRC_GRAMMAR}) +if(NOT EXISTS ${fix_asn1c_call}) + message( FATAL_ERROR "The script ${fix_asn1c_call} must be present" ) +endif(NOT EXISTS ${fix_asn1c_call}) +execute_process( + COMMAND ${fix_asn1c_call} ${RRC_FULL_DIR} RRC ${RRC_ASN1_VERSION} + RESULT_VARIABLE ret) +if (NOT ${ret} STREQUAL 0) + message(FATAL_ERROR "${fix_asn1c_call}: error") +endif (NOT ${ret} STREQUAL 0) file(GLOB rrc_source ${RRC_FULL_DIR}/*.c) set(rrc_source ${rrc_source} ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1_msg.c) file(GLOB rrc_h ${RRC_FULL_DIR}/*.h) @@ -282,6 +292,7 @@ include_directories ("${RRC_FULL_DIR}") add_custom_command ( OUTPUT ${RRC_FULL_DIR}/asn1_constants.h COMMAND ${asn1c_call} ${RRC_FULL_DIR} ${RRC_GRAMMAR} + COMMAND ${fix_asn1c_call} ${RRC_FULL_DIR} RRC ${RRC_ASN1_VERSION} DEPENDS ${RRC_GRAMMAR} ) @@ -311,6 +322,12 @@ set(S1AP_ASN_FILES set(S1AP_C_DIR ${asn1_generated_dir}/${ASN1RELDIR}) #message("calling ${asn1c_call} ${S1AP_C_DIR} ${S1AP_ASN_FILES}") execute_process(COMMAND ${asn1c_call} ${S1AP_C_DIR} ${S1AP_ASN_FILES}) +execute_process( + COMMAND ${fix_asn1c_call} ${S1AP_C_DIR} S1AP ${S1AP_VERSION} + RESULT_VARIABLE ret) +if (NOT ${ret} STREQUAL 0) + message(FATAL_ERROR "${fix_asn1c_call}: error") +endif (NOT ${ret} STREQUAL 0) file(GLOB S1AP_source ${S1AP_C_DIR}/*.c) set(S1AP_OAI_generated @@ -326,6 +343,7 @@ add_custom_command ( OUTPUT ${S1AP_OAI_generated} COMMAND ${asn1c_call} ${S1AP_C_DIR} ${S1AP_ASN_FILES} COMMAND python ${S1AP_DIR}/MESSAGES/ASN1/asn1tostruct.py -f${S1AP_ASN_DIR}/S1AP-PDU-Contents.asn -o${S1AP_C_DIR} + COMMAND ${fix_asn1c_call} ${S1AP_C_DIR} S1AP ${S1AP_VERSION} DEPENDS ${S1AP_ASN_FILES} ) add_library(S1AP_LIB @@ -378,6 +396,12 @@ set(X2AP_ASN_FILES set(X2AP_C_DIR ${asn1_generated_dir}/${ASN1RELDIR}) #message("calling ${asn1c_call} ${X2AP_C_DIR} ${X2AP_ASN_FILES}") execute_process(COMMAND ${asn1c_call} ${X2AP_C_DIR} ${X2AP_ASN_FILES}) +execute_process( + COMMAND ${fix_asn1c_call} ${X2AP_C_DIR} X2AP ${X2AP_VERSION} + RESULT_VARIABLE ret) +if (NOT ${ret} STREQUAL 0) + message(FATAL_ERROR "${fix_asn1c_call}: error") +endif (NOT ${ret} STREQUAL 0) file(GLOB X2AP_source ${X2AP_C_DIR}/*.c) set(X2AP_OAI_generated @@ -394,6 +418,7 @@ add_custom_command ( OUTPUT ${X2AP_OAI_generated} COMMAND ${asn1c_call} ${X2AP_C_DIR} ${X2AP_ASN_FILES} COMMAND python ${X2AP_DIR}/MESSAGES/ASN1/asn1tostruct.py -f ${X2AP_ASN_DIR}/X2AP-PDU-Contents.asn -o ${X2AP_C_DIR} + COMMAND ${fix_asn1c_call} ${X2AP_C_DIR} X2AP ${X2AP_VERSION} DEPENDS ${X2AP_ASN_FILES} ) diff --git a/cmake_targets/tools/fix_asn1 b/cmake_targets/tools/fix_asn1 new file mode 100755 index 0000000000000000000000000000000000000000..f222374faebf098406b229ac5727ca475d09fbd1 --- /dev/null +++ b/cmake_targets/tools/fix_asn1 @@ -0,0 +1,169 @@ +#!/bin/bash + +# in those arrays, each line is: +# <file> <sha1sum of file> <replacement file> + +RRC_Rel10=( + "SystemInformation-r8-IEs.h" 819eda3db27516f7c6780d832fb3c462e2264ea7 "fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h" +) + +X2AP_Rel11_2=( + "X2ap-CriticalityDiagnostics-IE-List.h" f0e2414992bfacfbc4b9fd15c977241d6d7fabeb "fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h" + "NativeInteger.c" e23034083a0fb9d4a2e523e2a64286161e621f27 "fix_asn1.data/X2AP.rel11.2/NativeInteger.c" + "constr_SET_OF.c" 5fb65da648a57ea61f008fa226b707cf343c1c0c "fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c" +) + +S1AP_Rel10_5=( + "NativeInteger.c" e23034083a0fb9d4a2e523e2a64286161e621f27 "fix_asn1.data/S1AP.rel10.5/NativeInteger.c" + "constr_SET_OF.c" 5fb65da648a57ea61f008fa226b707cf343c1c0c "fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c" +) + +red_color="\x1b[31m" +green_color="\x1b[32m" +reset_color="\x1b[0m" + +function error() +{ + echo -e "$red_color"ERROR: "$@""$reset_color" + exit 1 +} + +function check_sha1() +{ + local file="$1" + local target_sha1="$2" + + if [ ! -f "$file" ] + then + error "$file: no such file" + fi + + local computed_sha1=$(sha1sum "$file" | cut -f 1 -d ' ') + + if [ "$target_sha1" != "$computed_sha1" ] + then + error "$file: wrong SHA1" + fi +} + +function copy_file() +{ + local file="$1" + local destination="$2" + + echo -e "$green_color""copy file $OPENAIR_DIR/cmake_targets/tools/$file to $destination""$reset_color" + + cp -f "$OPENAIR_DIR/cmake_targets/tools/$file" "$destination" + if [ $? -ne 0 ] + then + error "copy of $file to $destination failed" + fi +} + +function patch() +{ + local directory="$1" + local array=$2 + local len=$3 # the length could be computed locally but the way to do it is not clear to me [CROUX] + + local i + local file + local sha1 + local replace + local item + + for (( i = 0; i < $len; i += 3 )) + do + # special bash syntax to access the array + item=$array[$i]; file=${!item} + item=$array[$((i+1))]; sha1=${!item} + item=$array[$((i+2))]; replace=${!item} + check_sha1 "$directory/$file" "$sha1" + copy_file "$replace" "$directory" + done +} + +function patch_rrc() +{ + local directory="$1" + local version="$2" + + case "$version" in + Rel10 ) + echo "patching RRC files release 10" + patch "$directory" RRC_Rel10 ${#RRC_Rel10[*]} + ;; + * ) + error unknwon/unhandled RRC version \'"$version"\' + ;; + esac +} + +function patch_x2ap() +{ + local directory="$1" + local version="$2" + + case "$version" in + R11 ) + echo "patching X2AP files release 11.2" + patch "$directory" X2AP_Rel11_2 ${#X2AP_Rel11_2[*]} + ;; + * ) + error unknwon/unhandled X2AP version \'"$version"\' + ;; + esac +} + +function patch_s1ap() +{ + local directory="$1" + local version="$2" + + case "$version" in + R10 ) + echo "patching S1AP files release 10.5" + patch "$directory" S1AP_Rel10_5 ${#S1AP_Rel10_5[*]} + ;; + * ) + error unknwon/unhandled S1AP version \'"$version"\' + ;; + esac +} + +function main() +{ + if [ $# -ne 3 ] + then + echo "ERROR: pass <output directory> <module> <version>" + exit 1 + fi + + if [ x"$OPENAIR_DIR" = x ] + then + error "the variable OPENAIR_DIR is not set" + fi + + local directory="$1" + local module="$2" + local version="$3" + + case "$module" in + RRC ) + patch_rrc "$directory" "$version" + ;; + X2AP ) + patch_x2ap "$directory" "$version" + ;; + S1AP ) + patch_s1ap "$directory" "$version" + ;; + * ) + error unknown module "$module" + ;; + esac + + exit 0 +} + +main "$@" diff --git a/cmake_targets/tools/fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h b/cmake_targets/tools/fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h new file mode 100644 index 0000000000000000000000000000000000000000..baa09c12ef3112ba647f048f01418092fab74f77 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h @@ -0,0 +1,109 @@ +/* + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) + * From ASN.1 module "EUTRA-RRC-Definitions" + * found in "fixed_grammar.asn" + * `asn1c -gen-PER` + */ + +#ifndef _SystemInformation_r8_IEs_H_ +#define _SystemInformation_r8_IEs_H_ + + +#include <asn_application.h> + +/* Including external dependencies */ +#include <asn_SEQUENCE_OF.h> +#include "SystemInformationBlockType2.h" +#include "SystemInformationBlockType3.h" +#include "SystemInformationBlockType4.h" +#include "SystemInformationBlockType5.h" +#include "SystemInformationBlockType6.h" +#include "SystemInformationBlockType7.h" +#include "SystemInformationBlockType8.h" +#include "SystemInformationBlockType9.h" +#include "SystemInformationBlockType10.h" +#include "SystemInformationBlockType11.h" +#include "SystemInformationBlockType12-r9.h" +#include "SystemInformationBlockType13-r9.h" +#include <constr_CHOICE.h> +#include <constr_SEQUENCE_OF.h> +#include <constr_SEQUENCE.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR { + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_NOTHING, /* No components present */ + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11, + /* Extensions may appear below */ + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920, + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920 +} SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR; + +/* Forward declarations */ +struct SystemInformation_v8a0_IEs; + + union SystemInformation_r8_IEs__sib_TypeAndInfo__Member_u { + SystemInformationBlockType2_t sib2; + SystemInformationBlockType3_t sib3; + SystemInformationBlockType4_t sib4; + SystemInformationBlockType5_t sib5; + SystemInformationBlockType6_t sib6; + SystemInformationBlockType7_t sib7; + SystemInformationBlockType8_t sib8; + SystemInformationBlockType9_t sib9; + SystemInformationBlockType10_t sib10; + SystemInformationBlockType11_t sib11; + /* + * This type is extensible, + * possible extensions are below. + */ + SystemInformationBlockType12_r9_t sib12_v920; + SystemInformationBlockType13_r9_t sib13_v920; + }; + + struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member { + SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR present; + union SystemInformation_r8_IEs__sib_TypeAndInfo__Member_u choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + }; + +/* SystemInformation-r8-IEs */ +typedef struct SystemInformation_r8_IEs { + struct SystemInformation_r8_IEs__sib_TypeAndInfo { + A_SEQUENCE_OF(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } sib_TypeAndInfo; + struct SystemInformation_v8a0_IEs *nonCriticalExtension /* OPTIONAL */; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SystemInformation_r8_IEs_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SystemInformation_r8_IEs; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "SystemInformation-v8a0-IEs.h" + +#endif /* _SystemInformation_r8_IEs_H_ */ +#include <asn_internal.h> diff --git a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c new file mode 100644 index 0000000000000000000000000000000000000000..239dbdc10f45e9beb5a21aa1c041b8af0f2832d7 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c @@ -0,0 +1,412 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include <asn_internal.h> +#include <NativeInteger.h> + +/* + * NativeInteger basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeInteger = { + "INTEGER", /* The ASN.1 type is still INTEGER */ + "INTEGER", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeInteger_encode_xer, + NativeInteger_decode_uper, /* Unaligned PER decoder */ + NativeInteger_encode_uper, /* Unaligned PER encoder */ + NativeInteger_decode_aper, /* Aligned PER decoder */ + NativeInteger_encode_aper, /* Aligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeInteger_tags, + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + asn_DEF_NativeInteger_tags, /* Same as above */ + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode INTEGER type. + */ +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; + + /* + * If the structure is not there, allocate it. + */ + if(native == NULL) { + native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native))); + if(native == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as INTEGER (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded INTEGER: buf_ptr, length + * Fill the native, at the same time checking for overflow. + * If overflow occured, return with RC_FAIL. + */ + { + INTEGER_t tmp; + union { + const void *constbuf; + void *nonconstbuf; + } unconst_buf; + long l; + + unconst_buf.constbuf = buf_ptr; + tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; + tmp.size = length; + + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&tmp, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + *native = l; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)", + (long)rval.consumed, (long)length, td->name, (long)*native); + + return rval; +} + +/* + * Encode the NativeInteger using the standard INTEGER type DER encoder. + */ +asn_enc_rval_t +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */ + asn_enc_rval_t erval; + INTEGER_t tmp; + +#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */ + + tmp.buf = (uint8_t *)&native; + tmp.size = sizeof(native); + +#else /* Works even if WORDS_BIGENDIAN is not set where should've been */ + uint8_t buf[sizeof(native)]; + uint8_t *p; + + /* Prepare a fake INTEGER */ + for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) + *p = (uint8_t)native; + + tmp.buf = buf; + tmp.size = sizeof(buf); +#endif /* WORDS_BIGENDIAN */ + + /* Encode fake INTEGER */ + erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = ptr; + } + return erval; +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +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; + long *native = (long *)*sptr; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&st, 0, sizeof(st)); + rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, + opt_mname, buf_ptr, size); + if(rval.code == RC_OK) { + long l; + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&st, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + } else { + *native = l; + } + } else { + /* + * Cannot restart from the middle; + * there is no place to save state in the native type. + * Request a continuation from the very beginning. + */ + rval.consumed = 0; + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st); + return rval; +} + + +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; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + 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; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +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; + void *tmpintptr = &tmpint; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native) + : asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + + return rval; +} + +asn_dec_rval_t +NativeInteger_decode_aper(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; + void *tmpintptr = &tmpint; + //int dynamic = 0; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + //dynamic = 1; + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native) + : asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + //if (dynamic) + // free(native); + + return rval; +} + +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; + + if(!sptr) _ASN_ENCODE_FAILED; + + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); + + memset(&tmpint, 0, sizeof(tmpint)); + 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); + return er; +} + +asn_enc_rval_t +NativeInteger_encode_aper( + 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 tmpint; + + if(!sptr) _ASN_ENCODE_FAILED; + memset(&tmpint, 0, sizeof(tmpint)); + + if(specs&&specs->field_unsigned) { + unsigned long native; + native = *(unsigned long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %lu (APER) (unsigned)", td->name, native); + + if(asn_ulong2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + } else { + long native; + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (APER) (unsigned)", td->name, native); + if(asn_long2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + } + +// if((specs&&specs->field_unsigned) +// ? asn_ulong2INTEGER(&tmpint, native) +// : asn_long2INTEGER(&tmpint, native)) +// _ASN_ENCODE_FAILED; + er = INTEGER_encode_aper(td, constraints, &tmpint, po); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + return er; +} + +/* + * INTEGER specific human-readable output. + */ +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; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(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 { + return (cb("<absent>", 8, app_key) < 0) ? -1 : 0; + } +} + +void +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", + td->name, contents_only, ptr); + + if(!contents_only) { + FREEMEM(ptr); + } +} + diff --git a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c new file mode 100644 index 0000000000000000000000000000000000000000..3e2d23b254266fb08a8872694997776235c04644 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c @@ -0,0 +1,1041 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include <asn_internal.h> +#include <constr_SET_OF.h> +#include <asn_SET_OF.h> + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the <TLV>'s L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * <T:5><L:1><V> <T:6>... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * The decoder of the SET OF type. + */ +asn_dec_rval_t +SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as SET OF", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + ASN_DEBUG("Structure consumes %ld bytes, " + "buffer %ld", (long)ctx->left, (long)size); + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next item. + */ + for(;; ctx->step = 0) { + ssize_t tag_len; /* Length of TLV's T */ + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + + if(ctx->left == 0) { + ASN_DEBUG("End of SET OF %s", td->name); + /* + * No more things to decode. + * Exit out of here. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Found the terminator of the + * indefinite length structure. + */ + break; + } + } + + /* Outmost tag may be unknown and cannot be fetched/compared */ + if(elm->tag != (ber_tlv_tag_t)-1) { + if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) { + /* + * The new list member of expected type has arrived. + */ + } else { + ASN_DEBUG("Unexpected tag %s fixed SET OF %s", + ber_tlv_tag_string(tlv_tag), td->name); + ASN_DEBUG("%s SET OF has tag %s", + td->name, ber_tlv_tag_string(elm->tag)); + RETURN(RC_FAIL); + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, + elm->type, &ctx->ptr, ptr, LEFT, 0); + ASN_DEBUG("In %s SET OF %s code %d consumed %d", + td->name, elm->type->name, + rval.code, (int)rval.consumed); + switch(rval.code) { + case RC_OK: + { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + else + ctx->ptr = 0; + } + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + /* Fall through */ + case RC_FAIL: /* Fatal error */ + ASN_STRUCT_FREE(*elm->type, ctx->ptr); + ctx->ptr = 0; + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all list members) */ + + NEXT_PHASE(ctx); + case 2: + /* + * Read in all "end of content" TLVs. + */ + while(ctx->left < 0) { + if(LEFT < 2) { + if(LEFT > 0 && ((const char *)ptr)[0] != 0) { + /* Unexpected tag */ + RETURN(RC_FAIL); + } else { + RETURN(RC_WMORE); + } + } + if(((const char *)ptr)[0] == 0 + && ((const char *)ptr)[1] == 0) { + ADVANCE(2); + ctx->left++; + } else { + RETURN(RC_FAIL); + } + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + +/* + * Internally visible buffer holding a single encoded element. + */ +struct _el_buffer { + uint8_t *buf; + size_t length; + size_t size; +}; +/* Append bytes to the above structure */ +static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) { + struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr; + + if(el_buf->length + size > el_buf->size) + return -1; + + memcpy(el_buf->buf + el_buf->length, buffer, size); + + el_buf->length += size; + return 0; +} +static int _el_buf_cmp(const void *ap, const void *bp) { + const struct _el_buffer *a = (const struct _el_buffer *)ap; + const struct _el_buffer *b = (const struct _el_buffer *)bp; + int ret; + size_t common_len; + + if(a->length < b->length) + common_len = a->length; + else + common_len = b->length; + + ret = memcmp(a->buf, b->buf, common_len); + if(ret == 0) { + if(a->length < b->length) + ret = -1; + else if(a->length > b->length) + ret = 1; + } + + return ret; +} + +/* + * The DER encoder of the SET OF type. + */ +asn_enc_rval_t +SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_TYPE_descriptor_t *elm_type = elm->type; + der_type_encoder_f *der_encoder = elm_type->der_encoder; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + struct _el_buffer *encoded_els; + ssize_t eels_count = 0; + size_t max_encoded_len = 1; + asn_enc_rval_t erval; + int ret; + int edx; + + ASN_DEBUG("Estimating size for SET OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + + /* Compute maximum encoding's size */ + if(max_encoded_len < (size_t)erval.encoded) + max_encoded_len = erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + computed_size += encoding_size; + + if(!cb || list->count == 0) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + /* + * DER mandates dynamic sorting of the SET OF elements + * according to their encodings. Build an array of the + * encoded elements. + */ + encoded_els = (struct _el_buffer *)MALLOC( + list->count * sizeof(encoded_els[0])); + if(encoded_els == NULL) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + ASN_DEBUG("Encoding members of %s SET OF", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + struct _el_buffer *encoded_el = &encoded_els[eels_count]; + + if(!memb_ptr) continue; + + /* + * Prepare space for encoding. + */ + encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); + if(encoded_el->buf) { + encoded_el->length = 0; + encoded_el->size = max_encoded_len; + } else { + for(edx--; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + /* + * Encode the member into the prepared space. + */ + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, + _el_addbytes, encoded_el); + if(erval.encoded == -1) { + for(; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + return erval; + } + encoding_size += erval.encoded; + eels_count++; + } + + /* + * Sort the encoded elements according to their encoding. + */ + qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); + + /* + * Report encoded elements to the application. + * Dispose of temporary sorted members table. + */ + ret = 0; + for(edx = 0; edx < eels_count; edx++) { + struct _el_buffer *encoded_el = &encoded_els[edx]; + /* Report encoded chunks to the application */ + if(ret == 0 + && cb(encoded_el->buf, encoded_el->length, app_key) < 0) + ret = -1; + FREEMEM(encoded_el->buf); + } + FREEMEM(encoded_els); + + if(ret || computed_size != (size_t)encoding_size) { + /* + * Standard callback failed, or + * encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + } + + _ASN_ENCODED_OK(erval); +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *element = td->elements; + const char *elm_tag; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* Which tag is expected for the downstream */ + if(specs->as_XMLValueList) { + elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; + } else { + elm_tag = (*element->name) + ? element->name : element->type->xml_tag; + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + */ + for(; ctx->phase <= 2;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Go inside the inner member of a set. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + + /* Invoke the inner type decoder, m.b. multiple times */ + ASN_DEBUG("XER/SET OF element [%s]", elm_tag); + tmprval = element->type->xer_decoder(opt_codec_ctx, + element->type, &ctx->ptr, elm_tag, + buf_ptr, size); + if(tmprval.code == RC_OK) { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + ctx->ptr = 0; + XER_ADVANCE(tmprval.consumed); + } else { + XER_ADVANCE(tmprval.consumed); + RETURN(tmprval.code); + } + ctx->phase = 1; /* Back to body processing */ + ASN_DEBUG("XER/SET OF phase => %d", ctx->phase); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, + buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", + tcv, ctx->phase, xml_tag); + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + /* No more things to decode */ + XER_ADVANCE(ch_size); + ctx->phase = 3; /* Phase out */ + RETURN(RC_OK); + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase); + if(ctx->phase == 1) { + /* + * Process a single possible member. + */ + ctx->phase = 2; + continue; + } + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SET OF"); + break; + } + + ctx->phase = 3; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + + + +typedef struct xer_tmp_enc_s { + void *buffer; + size_t offset; + size_t size; +} xer_tmp_enc_t; +static int +SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { + xer_tmp_enc_t *t = (xer_tmp_enc_t *)key; + if(t->offset + size >= t->size) { + size_t newsize = (t->size << 2) + size; + void *p = REALLOC(t->buffer, newsize); + if(!p) return -1; + t->buffer = p; + t->size = newsize; + } + memcpy((char *)t->buffer + t->offset, buffer, size); + t->offset += size; + return 0; +} +static int +SET_OF_xer_order(const void *aptr, const void *bptr) { + const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr; + const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr; + size_t minlen = a->offset; + int ret; + if(b->offset < minlen) minlen = b->offset; + /* Well-formed UTF-8 has this nice lexicographical property... */ + ret = memcmp(a->buffer, b->buffer, minlen); + if(ret != 0) return ret; + if(a->offset == b->offset) + return 0; + if(a->offset == minlen) + return -1; + return 1; +} + + +asn_enc_rval_t +SET_OF_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_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + size_t mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + xer_tmp_enc_t *encs = 0; + size_t encs_count = 0; + void *original_app_key = app_key; + asn_app_consume_bytes_f *original_cb = cb; + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + if(xcan) { + encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); + if(!encs) _ASN_ENCODE_FAILED; + cb = SET_OF_encode_xer_callback; + } + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(encs) { + memset(&encs[encs_count], 0, sizeof(encs[0])); + app_key = &encs[encs_count]; + encs_count++; + } + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + if(!xcan && specs->as_XMLValueList == 1) + _i_ASN_TEXT_INDENT(1, ilevel + 1); + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + (specs->as_XMLValueList != 2), + flags, cb, app_key); + if(tmper.encoded == -1) { + td = tmper.failed_type; + sptr = tmper.structure_ptr; + goto cb_failed; + } + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + if(encs) { + xer_tmp_enc_t *enc = encs; + xer_tmp_enc_t *end = encs + encs_count; + ssize_t control_size = 0; + + cb = original_cb; + app_key = original_app_key; + qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); + + for(; enc < end; enc++) { + _ASN_CALLBACK(enc->buffer, enc->offset); + FREEMEM(enc->buffer); + enc->buffer = 0; + control_size += enc->offset; + } + assert(control_size == er.encoded); + } + + goto cleanup; +cb_failed: + er.encoded = -1; + er.failed_type = td; + er.structure_ptr = sptr; +cleanup: + if(encs) { + while(encs_count-- > 0) { + if(encs[encs_count].buffer) + FREEMEM(encs[encs_count].buffer); + } + FREEMEM(encs); + } + _ASN_ENCODED_OK(er); +} + +int +SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int ret; + int i; + + if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + _i_INDENT(1); + + ret = elm->type->print_struct(elm->type, memb_ptr, + ilevel + 1, cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +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; + + /* + * Could not use set_of_empty() because of (*free) + * incompatibility. + */ + for(i = 0; i < list->count; i++) { + void *memb_ptr = list->array[i]; + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } + list->count = 0; /* No meaningful elements left */ + + 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); + } + } +} + +int +SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_constr_check_f *constr; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int i; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + constr = elm->memb_constraints; + if(!constr) constr = elm->type->check_constraints; + + /* + * Iterate over the members of an array. + * Validate each in turn, until one fails. + */ + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + int ret; + + if(!memb_ptr) continue; + + ret = constr(elm->type, memb_ptr, ctfailcb, app_key); + if(ret) return ret; + } + + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + if(!elm->memb_constraints) + elm->memb_constraints = elm->type->check_constraints; + + return 0; +} + +asn_dec_rval_t +SET_OF_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_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + nelems = per_get_few_bits(pd, ct->effective_bits); + ASN_DEBUG("Preparing to fetch %ld+%"PRIdMAX" elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = uper_get_length(pd, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, (int)(ct ? ct->effective_bits : -1)); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code = RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + +asn_dec_rval_t +SET_OF_decode_aper(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_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ +// nelems = per_get_few_bits(pd, ct->effective_bits); + nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound); + ASN_DEBUG("Preparing to fetch %ld+%"PRIdMAX" elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = aper_get_length(pd, ct ? ct->upper_bound - ct->lower_bound + 1 : -1, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, ct ? ct->effective_bits : -1); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->aper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code = RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c new file mode 100644 index 0000000000000000000000000000000000000000..239dbdc10f45e9beb5a21aa1c041b8af0f2832d7 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c @@ -0,0 +1,412 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include <asn_internal.h> +#include <NativeInteger.h> + +/* + * NativeInteger basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeInteger = { + "INTEGER", /* The ASN.1 type is still INTEGER */ + "INTEGER", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeInteger_encode_xer, + NativeInteger_decode_uper, /* Unaligned PER decoder */ + NativeInteger_encode_uper, /* Unaligned PER encoder */ + NativeInteger_decode_aper, /* Aligned PER decoder */ + NativeInteger_encode_aper, /* Aligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeInteger_tags, + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + asn_DEF_NativeInteger_tags, /* Same as above */ + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode INTEGER type. + */ +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; + + /* + * If the structure is not there, allocate it. + */ + if(native == NULL) { + native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native))); + if(native == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as INTEGER (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded INTEGER: buf_ptr, length + * Fill the native, at the same time checking for overflow. + * If overflow occured, return with RC_FAIL. + */ + { + INTEGER_t tmp; + union { + const void *constbuf; + void *nonconstbuf; + } unconst_buf; + long l; + + unconst_buf.constbuf = buf_ptr; + tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; + tmp.size = length; + + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&tmp, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + *native = l; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)", + (long)rval.consumed, (long)length, td->name, (long)*native); + + return rval; +} + +/* + * Encode the NativeInteger using the standard INTEGER type DER encoder. + */ +asn_enc_rval_t +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */ + asn_enc_rval_t erval; + INTEGER_t tmp; + +#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */ + + tmp.buf = (uint8_t *)&native; + tmp.size = sizeof(native); + +#else /* Works even if WORDS_BIGENDIAN is not set where should've been */ + uint8_t buf[sizeof(native)]; + uint8_t *p; + + /* Prepare a fake INTEGER */ + for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) + *p = (uint8_t)native; + + tmp.buf = buf; + tmp.size = sizeof(buf); +#endif /* WORDS_BIGENDIAN */ + + /* Encode fake INTEGER */ + erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = ptr; + } + return erval; +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +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; + long *native = (long *)*sptr; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&st, 0, sizeof(st)); + rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, + opt_mname, buf_ptr, size); + if(rval.code == RC_OK) { + long l; + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */ + : asn_INTEGER2long(&st, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + } else { + *native = l; + } + } else { + /* + * Cannot restart from the middle; + * there is no place to save state in the native type. + * Request a continuation from the very beginning. + */ + rval.consumed = 0; + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st); + return rval; +} + + +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; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + 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; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +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; + void *tmpintptr = &tmpint; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native) + : asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + + return rval; +} + +asn_dec_rval_t +NativeInteger_decode_aper(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; + void *tmpintptr = &tmpint; + //int dynamic = 0; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + //dynamic = 1; + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if((specs&&specs->field_unsigned) + ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native) + : asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + //if (dynamic) + // free(native); + + return rval; +} + +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; + + if(!sptr) _ASN_ENCODE_FAILED; + + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); + + memset(&tmpint, 0, sizeof(tmpint)); + 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); + return er; +} + +asn_enc_rval_t +NativeInteger_encode_aper( + 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 tmpint; + + if(!sptr) _ASN_ENCODE_FAILED; + memset(&tmpint, 0, sizeof(tmpint)); + + if(specs&&specs->field_unsigned) { + unsigned long native; + native = *(unsigned long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %lu (APER) (unsigned)", td->name, native); + + if(asn_ulong2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + } else { + long native; + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (APER) (unsigned)", td->name, native); + if(asn_long2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + } + +// if((specs&&specs->field_unsigned) +// ? asn_ulong2INTEGER(&tmpint, native) +// : asn_long2INTEGER(&tmpint, native)) +// _ASN_ENCODE_FAILED; + er = INTEGER_encode_aper(td, constraints, &tmpint, po); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + return er; +} + +/* + * INTEGER specific human-readable output. + */ +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; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(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 { + return (cb("<absent>", 8, app_key) < 0) ? -1 : 0; + } +} + +void +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", + td->name, contents_only, ptr); + + if(!contents_only) { + FREEMEM(ptr); + } +} + diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h new file mode 100644 index 0000000000000000000000000000000000000000..d9c9fd1b4b129a144149b527ffb0f4499b2cf84a --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h @@ -0,0 +1,63 @@ +/* + * Generated by asn1c-0.9.24 (http://lionet.info/asn1c) + * From ASN.1 module "X2AP-IEs" + * found in "/roux/comments/openairinterface5g/openair2/X2AP/MESSAGES/ASN1/R11.2/X2AP-IEs.asn" + * `asn1c -gen-PER` + */ + +#ifndef _X2ap_CriticalityDiagnostics_IE_List_H_ +#define _X2ap_CriticalityDiagnostics_IE_List_H_ + + +#include <asn_application.h> + +/* Including external dependencies */ +#include <asn_SEQUENCE_OF.h> +#include "X2ap-Criticality.h" +#include "X2ap-ProtocolIE-ID.h" +#include "X2ap-TypeOfError.h" +#include <constr_SEQUENCE.h> +#include <constr_SEQUENCE_OF.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct X2ap_IE_Extensions; + +struct X2ap_CriticalityDiagnostics_IE_List__Member { + X2ap_Criticality_t iECriticality; + X2ap_ProtocolIE_ID_t iE_ID; + X2ap_TypeOfError_t typeOfError; + struct X2ap_IE_Extensions *iE_Extensions /* OPTIONAL */; + /* + * This type is extensible, + * possible extensions are below. + */ + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + }; + +/* X2ap-CriticalityDiagnostics-IE-List */ +typedef struct X2ap_CriticalityDiagnostics_IE_List { + A_SEQUENCE_OF(struct X2ap_CriticalityDiagnostics_IE_List__Member + ) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} X2ap_CriticalityDiagnostics_IE_List_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_X2ap_CriticalityDiagnostics_IE_List; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "X2ap-IE-Extensions.h" + +#endif /* _X2ap_CriticalityDiagnostics_IE_List_H_ */ +#include <asn_internal.h> diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c new file mode 100644 index 0000000000000000000000000000000000000000..3e2d23b254266fb08a8872694997776235c04644 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c @@ -0,0 +1,1041 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include <asn_internal.h> +#include <constr_SET_OF.h> +#include <asn_SET_OF.h> + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the <TLV>'s L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * <T:5><L:1><V> <T:6>... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * The decoder of the SET OF type. + */ +asn_dec_rval_t +SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as SET OF", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + ASN_DEBUG("Structure consumes %ld bytes, " + "buffer %ld", (long)ctx->left, (long)size); + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next item. + */ + for(;; ctx->step = 0) { + ssize_t tag_len; /* Length of TLV's T */ + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + + if(ctx->left == 0) { + ASN_DEBUG("End of SET OF %s", td->name); + /* + * No more things to decode. + * Exit out of here. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Found the terminator of the + * indefinite length structure. + */ + break; + } + } + + /* Outmost tag may be unknown and cannot be fetched/compared */ + if(elm->tag != (ber_tlv_tag_t)-1) { + if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) { + /* + * The new list member of expected type has arrived. + */ + } else { + ASN_DEBUG("Unexpected tag %s fixed SET OF %s", + ber_tlv_tag_string(tlv_tag), td->name); + ASN_DEBUG("%s SET OF has tag %s", + td->name, ber_tlv_tag_string(elm->tag)); + RETURN(RC_FAIL); + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, + elm->type, &ctx->ptr, ptr, LEFT, 0); + ASN_DEBUG("In %s SET OF %s code %d consumed %d", + td->name, elm->type->name, + rval.code, (int)rval.consumed); + switch(rval.code) { + case RC_OK: + { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + else + ctx->ptr = 0; + } + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + /* Fall through */ + case RC_FAIL: /* Fatal error */ + ASN_STRUCT_FREE(*elm->type, ctx->ptr); + ctx->ptr = 0; + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all list members) */ + + NEXT_PHASE(ctx); + case 2: + /* + * Read in all "end of content" TLVs. + */ + while(ctx->left < 0) { + if(LEFT < 2) { + if(LEFT > 0 && ((const char *)ptr)[0] != 0) { + /* Unexpected tag */ + RETURN(RC_FAIL); + } else { + RETURN(RC_WMORE); + } + } + if(((const char *)ptr)[0] == 0 + && ((const char *)ptr)[1] == 0) { + ADVANCE(2); + ctx->left++; + } else { + RETURN(RC_FAIL); + } + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + +/* + * Internally visible buffer holding a single encoded element. + */ +struct _el_buffer { + uint8_t *buf; + size_t length; + size_t size; +}; +/* Append bytes to the above structure */ +static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) { + struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr; + + if(el_buf->length + size > el_buf->size) + return -1; + + memcpy(el_buf->buf + el_buf->length, buffer, size); + + el_buf->length += size; + return 0; +} +static int _el_buf_cmp(const void *ap, const void *bp) { + const struct _el_buffer *a = (const struct _el_buffer *)ap; + const struct _el_buffer *b = (const struct _el_buffer *)bp; + int ret; + size_t common_len; + + if(a->length < b->length) + common_len = a->length; + else + common_len = b->length; + + ret = memcmp(a->buf, b->buf, common_len); + if(ret == 0) { + if(a->length < b->length) + ret = -1; + else if(a->length > b->length) + ret = 1; + } + + return ret; +} + +/* + * The DER encoder of the SET OF type. + */ +asn_enc_rval_t +SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_TYPE_descriptor_t *elm_type = elm->type; + der_type_encoder_f *der_encoder = elm_type->der_encoder; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + struct _el_buffer *encoded_els; + ssize_t eels_count = 0; + size_t max_encoded_len = 1; + asn_enc_rval_t erval; + int ret; + int edx; + + ASN_DEBUG("Estimating size for SET OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + + /* Compute maximum encoding's size */ + if(max_encoded_len < (size_t)erval.encoded) + max_encoded_len = erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + computed_size += encoding_size; + + if(!cb || list->count == 0) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + /* + * DER mandates dynamic sorting of the SET OF elements + * according to their encodings. Build an array of the + * encoded elements. + */ + encoded_els = (struct _el_buffer *)MALLOC( + list->count * sizeof(encoded_els[0])); + if(encoded_els == NULL) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + ASN_DEBUG("Encoding members of %s SET OF", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + struct _el_buffer *encoded_el = &encoded_els[eels_count]; + + if(!memb_ptr) continue; + + /* + * Prepare space for encoding. + */ + encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); + if(encoded_el->buf) { + encoded_el->length = 0; + encoded_el->size = max_encoded_len; + } else { + for(edx--; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + /* + * Encode the member into the prepared space. + */ + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, + _el_addbytes, encoded_el); + if(erval.encoded == -1) { + for(; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + return erval; + } + encoding_size += erval.encoded; + eels_count++; + } + + /* + * Sort the encoded elements according to their encoding. + */ + qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); + + /* + * Report encoded elements to the application. + * Dispose of temporary sorted members table. + */ + ret = 0; + for(edx = 0; edx < eels_count; edx++) { + struct _el_buffer *encoded_el = &encoded_els[edx]; + /* Report encoded chunks to the application */ + if(ret == 0 + && cb(encoded_el->buf, encoded_el->length, app_key) < 0) + ret = -1; + FREEMEM(encoded_el->buf); + } + FREEMEM(encoded_els); + + if(ret || computed_size != (size_t)encoding_size) { + /* + * Standard callback failed, or + * encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + } + + _ASN_ENCODED_OK(erval); +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *element = td->elements; + const char *elm_tag; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* Which tag is expected for the downstream */ + if(specs->as_XMLValueList) { + elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; + } else { + elm_tag = (*element->name) + ? element->name : element->type->xml_tag; + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + */ + for(; ctx->phase <= 2;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Go inside the inner member of a set. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + + /* Invoke the inner type decoder, m.b. multiple times */ + ASN_DEBUG("XER/SET OF element [%s]", elm_tag); + tmprval = element->type->xer_decoder(opt_codec_ctx, + element->type, &ctx->ptr, elm_tag, + buf_ptr, size); + if(tmprval.code == RC_OK) { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + ctx->ptr = 0; + XER_ADVANCE(tmprval.consumed); + } else { + XER_ADVANCE(tmprval.consumed); + RETURN(tmprval.code); + } + ctx->phase = 1; /* Back to body processing */ + ASN_DEBUG("XER/SET OF phase => %d", ctx->phase); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, + buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", + tcv, ctx->phase, xml_tag); + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + /* No more things to decode */ + XER_ADVANCE(ch_size); + ctx->phase = 3; /* Phase out */ + RETURN(RC_OK); + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase); + if(ctx->phase == 1) { + /* + * Process a single possible member. + */ + ctx->phase = 2; + continue; + } + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SET OF"); + break; + } + + ctx->phase = 3; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + + + +typedef struct xer_tmp_enc_s { + void *buffer; + size_t offset; + size_t size; +} xer_tmp_enc_t; +static int +SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { + xer_tmp_enc_t *t = (xer_tmp_enc_t *)key; + if(t->offset + size >= t->size) { + size_t newsize = (t->size << 2) + size; + void *p = REALLOC(t->buffer, newsize); + if(!p) return -1; + t->buffer = p; + t->size = newsize; + } + memcpy((char *)t->buffer + t->offset, buffer, size); + t->offset += size; + return 0; +} +static int +SET_OF_xer_order(const void *aptr, const void *bptr) { + const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr; + const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr; + size_t minlen = a->offset; + int ret; + if(b->offset < minlen) minlen = b->offset; + /* Well-formed UTF-8 has this nice lexicographical property... */ + ret = memcmp(a->buffer, b->buffer, minlen); + if(ret != 0) return ret; + if(a->offset == b->offset) + return 0; + if(a->offset == minlen) + return -1; + return 1; +} + + +asn_enc_rval_t +SET_OF_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_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + size_t mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + xer_tmp_enc_t *encs = 0; + size_t encs_count = 0; + void *original_app_key = app_key; + asn_app_consume_bytes_f *original_cb = cb; + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + if(xcan) { + encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); + if(!encs) _ASN_ENCODE_FAILED; + cb = SET_OF_encode_xer_callback; + } + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(encs) { + memset(&encs[encs_count], 0, sizeof(encs[0])); + app_key = &encs[encs_count]; + encs_count++; + } + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + if(!xcan && specs->as_XMLValueList == 1) + _i_ASN_TEXT_INDENT(1, ilevel + 1); + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + (specs->as_XMLValueList != 2), + flags, cb, app_key); + if(tmper.encoded == -1) { + td = tmper.failed_type; + sptr = tmper.structure_ptr; + goto cb_failed; + } + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + if(encs) { + xer_tmp_enc_t *enc = encs; + xer_tmp_enc_t *end = encs + encs_count; + ssize_t control_size = 0; + + cb = original_cb; + app_key = original_app_key; + qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); + + for(; enc < end; enc++) { + _ASN_CALLBACK(enc->buffer, enc->offset); + FREEMEM(enc->buffer); + enc->buffer = 0; + control_size += enc->offset; + } + assert(control_size == er.encoded); + } + + goto cleanup; +cb_failed: + er.encoded = -1; + er.failed_type = td; + er.structure_ptr = sptr; +cleanup: + if(encs) { + while(encs_count-- > 0) { + if(encs[encs_count].buffer) + FREEMEM(encs[encs_count].buffer); + } + FREEMEM(encs); + } + _ASN_ENCODED_OK(er); +} + +int +SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int ret; + int i; + + if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + _i_INDENT(1); + + ret = elm->type->print_struct(elm->type, memb_ptr, + ilevel + 1, cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +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; + + /* + * Could not use set_of_empty() because of (*free) + * incompatibility. + */ + for(i = 0; i < list->count; i++) { + void *memb_ptr = list->array[i]; + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } + list->count = 0; /* No meaningful elements left */ + + 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); + } + } +} + +int +SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_constr_check_f *constr; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int i; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + constr = elm->memb_constraints; + if(!constr) constr = elm->type->check_constraints; + + /* + * Iterate over the members of an array. + * Validate each in turn, until one fails. + */ + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + int ret; + + if(!memb_ptr) continue; + + ret = constr(elm->type, memb_ptr, ctfailcb, app_key); + if(ret) return ret; + } + + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + if(!elm->memb_constraints) + elm->memb_constraints = elm->type->check_constraints; + + return 0; +} + +asn_dec_rval_t +SET_OF_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_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + nelems = per_get_few_bits(pd, ct->effective_bits); + ASN_DEBUG("Preparing to fetch %ld+%"PRIdMAX" elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = uper_get_length(pd, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, (int)(ct ? ct->effective_bits : -1)); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code = RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + +asn_dec_rval_t +SET_OF_decode_aper(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_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ +// nelems = per_get_few_bits(pd, ct->effective_bits); + nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound); + ASN_DEBUG("Preparing to fetch %ld+%"PRIdMAX" elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = aper_get_length(pd, ct ? ct->upper_bound - ct->lower_bound + 1 : -1, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, ct ? ct->effective_bits : -1); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->aper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code = RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +}