#include #include #define EMIT_ASN_DEBUG 1 #include #include #include #include static int FailOut(const void *data, size_t size, void *op_key) { assert(!"UNREACHABLE"); return 0; } static void normalize(asn_per_outp_t *po) { if(po->nboff >= 8) { po->buffer += (po->nboff >> 3); po->nbits -= (po->nboff & ~0x07); po->nboff &= 0x07; } } static void check_per_encode_constrained(int lineno, int unsigned_, long value, long lbound, unsigned long ubound, int bit_range) { INTEGER_t st; INTEGER_t *reconstructed_st = 0; asn_INTEGER_specifics_t specs; asn_per_constraints_t cts; asn_enc_rval_t enc_rval; asn_dec_rval_t dec_rval; asn_per_outp_t po; asn_per_data_t pd; if(unsigned_) printf("%d: Recoding %s %lu [%ld..%lu]\n", lineno, unsigned_ ? "unsigned" : "signed", value, lbound, ubound); else printf("%d: Recoding %s %ld [%ld..%lu]\n", lineno, unsigned_ ? "unsigned" : "signed", value, lbound, ubound); memset(&st, 0, sizeof(st)); memset(&po, 0, sizeof(po)); memset(&pd, 0, sizeof(pd)); memset(&cts, 0, sizeof(cts)); memset(&specs, 0, sizeof(specs)); cts.value.flags = APC_CONSTRAINED; cts.value.range_bits = bit_range; cts.value.effective_bits = bit_range; cts.value.lower_bound = lbound; cts.value.upper_bound = ubound; if(unsigned_) asn_ulong2INTEGER(&st, (unsigned long)value); else asn_long2INTEGER(&st, value); po.buffer = po.tmpspace; po.nboff = 0; po.nbits = 8 * sizeof(po.tmpspace); po.outper = FailOut; specs.field_width = sizeof(long); specs.field_unsigned = unsigned_; asn_DEF_INTEGER.specifics = &specs; enc_rval = INTEGER_encode_uper(&asn_DEF_INTEGER, &cts, &st, &po); assert(enc_rval.encoded == 0); normalize(&po); assert(po.buffer == &po.tmpspace[bit_range / 8]); if(unsigned_) { unsigned long recovered_value = ((uint32_t)po.tmpspace[0] << 24) | ((uint32_t)po.tmpspace[1] << 16) | ((uint32_t)po.tmpspace[2] << 8) | ((uint32_t)po.tmpspace[3] << 0); recovered_value >>= (32 - bit_range); recovered_value += cts.value.lower_bound; assert(recovered_value == (unsigned long)value); } else { long recovered_value = ((uint32_t)po.tmpspace[0] << 24) | ((uint32_t)po.tmpspace[1] << 16) | ((uint32_t)po.tmpspace[2] << 8) | ((uint32_t)po.tmpspace[3] << 0); recovered_value = (unsigned long)recovered_value >> (32 - bit_range); recovered_value += cts.value.lower_bound; assert((long)recovered_value == value); } assert(po.nboff == ((bit_range == 32) ? 0 : (8 - (32 - bit_range)))); assert(po.nbits == 8 * (sizeof(po.tmpspace) - (po.buffer-po.tmpspace))); assert(po.flushed_bytes == 0); pd.buffer = po.tmpspace; pd.nboff = 0; pd.nbits = 8 * (po.buffer - po.tmpspace) + po.nboff; pd.moved = 0; dec_rval = INTEGER_decode_uper(0, &asn_DEF_INTEGER, &cts, (void **)&reconstructed_st, &pd); assert(dec_rval.code == RC_OK); if(unsigned_) { unsigned long reconstructed_value = 0; asn_INTEGER2ulong(reconstructed_st, &reconstructed_value); assert(reconstructed_value == (unsigned long)value); } else { long reconstructed_value = 0; asn_INTEGER2long(reconstructed_st, &reconstructed_value); assert(reconstructed_value == value); } } #define CHECK(u, v, l, r, b) \ check_per_encode_constrained(__LINE__, u, v, l, r, b) int main() { int unsigned_; for(unsigned_ = 0; unsigned_ < 2; unsigned_++) { int u = unsigned_; /* Encode a signed 0x8babab into a range constrained by 0..2^29-1 */ CHECK(u, 0x8babab, 0, 536870911UL, 29); CHECK(u, 0x8babab, 0, 1073741823UL, 30); CHECK(u, 0x8babab, 0, 2147483647UL, 31); CHECK(u, 0x8babab, 10, 536870901UL, 29); CHECK(u, 0x8babab, 10, 1073741803UL, 30); CHECK(u, 0x8babab, 10, 2147483607UL, 31); CHECK(0, 0x8babab, -10, 536870901UL, 29); CHECK(0, 0x8babab, -10, 1073741803UL, 30); CHECK(0, 0x8babab, -10, 2147483607UL, 31); CHECK(u, 11, 10, 536870901UL, 29); CHECK(u, 11, 10, 1073741803UL, 30); CHECK(u, 11, 10, 2147483607UL, 31); CHECK(0, 1, -10, 536870901UL, 29); CHECK(0, 1, -10, 1073741803UL, 30); CHECK(0, 1, -10, 2147483607UL, 31); CHECK(u, 10, 10, 536870901UL, 29); CHECK(u, 10, 10, 1073741803UL, 30); CHECK(u, 10, 10, 2147483607UL, 31); CHECK(0, 0, -10, 536870901UL, 29); CHECK(0, 0, -10, 1073741803UL, 30); CHECK(0, 0, -10, 2147483607UL, 31); CHECK(0, -1, -10, 536870901UL, 29); CHECK(0, -1, -10, 1073741803UL, 30); CHECK(0, -1, -10, 2147483607UL, 31); CHECK(0, -10, -10, 536870901UL, 29); CHECK(0, -10, -10, 1073741803UL, 30); CHECK(0, -10, -10, 2147483607UL, 31); CHECK(u, 536870901UL, 10, 536870901UL, 29); CHECK(u, 1073741803UL, 10, 1073741803UL, 30); CHECK(u, 2147483607UL, 10, 2147483607UL, 31); CHECK(0, 536870901UL, -10, 536870901UL, 29); CHECK(0, 1073741803UL, -10, 1073741803UL, 30); CHECK(0, 2147483607UL, -10, 2147483607UL, 31); CHECK(0, -2147483648, -2147483648, 2147483647, 32); CHECK(0, -10, -2147483648, 2147483647, 32); CHECK(0, -1, -2147483648, 2147483647, 32); CHECK(0, 0, -2147483648, 2147483647, 32); CHECK(0, 1, -2147483648, 2147483647, 32); CHECK(0, 10, -2147483648, 2147483647, 32); CHECK(0, 2147483647, -2147483648, 2147483647, 32); CHECK(1, 0, 0, 4294967295UL, 32); CHECK(1, 1, 0, 4294967295UL, 32); CHECK(1, 10, 0, 4294967295UL, 32); CHECK(1, 2000000000, 0, 4294967295UL, 32); CHECK(1, 2147483647, 0, 4294967295UL, 32); CHECK(1, 2147483648, 0, 4294967295UL, 32); CHECK(1, 4000000000, 0, 4294967295UL, 32); CHECK(1, 4294967295UL, 0, 4294967295UL, 32); CHECK(1, 10, 10, 4294967285UL, 32); CHECK(1, 11, 10, 4294967285UL, 32); if(sizeof(long) > sizeof(uint32_t)) { CHECK(0, 0, -10, 4294967285UL, 32); CHECK(0, 1, -10, 4294967285UL, 32); CHECK(0, -1, -10, 4294967285UL, 32); CHECK(0, -10, -10, 4294967285UL, 32); CHECK(0, -10, -10, 4294967285UL, 32); CHECK(0, 0x8babab, -10, 4294967285UL, 32); CHECK(u, 0x8babab, 0, 4294967295UL, 32); CHECK(u, 11, 10, 4294967205UL, 32); CHECK(u, 10, 10, 4294967205UL, 32); CHECK(u, 4294967205UL, 10, 4294967285UL, 32); CHECK(0, 4294967205UL, -10, 4294967285UL, 32); CHECK(u, 4294967295UL, 1, 4294967295UL, 32); CHECK(u, 2000000000, 0, 4294967295UL, 32); CHECK(u, 2147483647, 0, 4294967295UL, 32); CHECK(u, 2147483648, 0, 4294967295UL, 32); CHECK(u, 4000000000, 0, 4294967295UL, 32); } } return 0; }