|
|
|
@ -26,14 +26,24 @@
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <limits>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace asn1 {
|
|
|
|
|
|
|
|
|
|
#define ASN_16K 16383
|
|
|
|
|
#define ASN_16K 16384
|
|
|
|
|
#define ASN_64K 65536
|
|
|
|
|
|
|
|
|
|
template <class Integer>
|
|
|
|
|
constexpr Integer ceil_frac(Integer n, Integer d)
|
|
|
|
|
{
|
|
|
|
|
return (n + (d - 1)) / d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
logging
|
|
|
|
@ -59,7 +69,7 @@ void log_error_code(SRSASN_CODE code, const char* filename, int line);
|
|
|
|
|
|
|
|
|
|
#define HANDLE_CODE(ret) \
|
|
|
|
|
{ \
|
|
|
|
|
SRSASN_CODE macrocode = (ret); \
|
|
|
|
|
SRSASN_CODE macrocode = ((ret)); \
|
|
|
|
|
if (macrocode != SRSASN_SUCCESS) { \
|
|
|
|
|
log_error_code(macrocode, __FILE__, __LINE__); \
|
|
|
|
|
return macrocode; \
|
|
|
|
@ -129,7 +139,7 @@ public:
|
|
|
|
|
using const_iterator = const T*;
|
|
|
|
|
|
|
|
|
|
dyn_array() = default;
|
|
|
|
|
dyn_array(uint32_t new_size) : size_(new_size), cap_(new_size) { data_ = new T[size_]; }
|
|
|
|
|
explicit dyn_array(uint32_t new_size) : size_(new_size), cap_(new_size) { data_ = new T[size_]; }
|
|
|
|
|
dyn_array(const dyn_array<T>& other)
|
|
|
|
|
{
|
|
|
|
|
size_ = other.size_;
|
|
|
|
@ -243,6 +253,98 @@ private:
|
|
|
|
|
uint32_t current_size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This array does small buffer optimization. The array has a small stack (Nthres elements) to store elements. Once
|
|
|
|
|
* the number of elements exceeds this stack, the array allocs on the heap.
|
|
|
|
|
* @tparam T
|
|
|
|
|
* @tparam Nthres number of elements T that can be stored in the stack
|
|
|
|
|
*/
|
|
|
|
|
template <class T, uint32_t Nthres = ceil_frac(16lu, sizeof(T))>
|
|
|
|
|
class ext_array
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static const uint32_t small_buffer_size = Nthres;
|
|
|
|
|
ext_array() : size_(0), head(&small_buffer.data[0]) {}
|
|
|
|
|
explicit ext_array(uint32_t new_size) : ext_array() { resize(new_size); }
|
|
|
|
|
ext_array(const ext_array<T, Nthres>& other) : ext_array(other.size_)
|
|
|
|
|
{
|
|
|
|
|
std::copy(other.head, other.head + other.size_, head);
|
|
|
|
|
}
|
|
|
|
|
ext_array(ext_array<T, Nthres>&& other) noexcept
|
|
|
|
|
{
|
|
|
|
|
size_ = other.size();
|
|
|
|
|
if (other.is_in_small_buffer()) {
|
|
|
|
|
head = &small_buffer.data[0];
|
|
|
|
|
std::copy(other.data(), other.data() + other.size(), head);
|
|
|
|
|
} else {
|
|
|
|
|
head = other.head;
|
|
|
|
|
small_buffer.cap_ = other.small_buffer.cap_;
|
|
|
|
|
other.head = &other.small_buffer.data[0];
|
|
|
|
|
other.size_ = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
~ext_array()
|
|
|
|
|
{
|
|
|
|
|
if (not is_in_small_buffer()) {
|
|
|
|
|
delete[] head;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ext_array<T, Nthres>& operator=(const ext_array<T, Nthres>& other)
|
|
|
|
|
{
|
|
|
|
|
if (this != &other) {
|
|
|
|
|
resize(other.size());
|
|
|
|
|
std::copy(other.data(), other.data() + other.size(), head);
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t size() const { return size_; }
|
|
|
|
|
uint32_t capacity() const { return is_in_small_buffer() ? Nthres : small_buffer.cap_; }
|
|
|
|
|
T& operator[](uint32_t index) { return head[index]; }
|
|
|
|
|
const T& operator[](uint32_t index) const { return head[index]; }
|
|
|
|
|
T* data() { return &head[0]; }
|
|
|
|
|
const T* data() const { return &head[0]; }
|
|
|
|
|
T& back() { return head[size() - 1]; }
|
|
|
|
|
const T& back() const { return head[size() - 1]; }
|
|
|
|
|
bool operator==(const ext_array<T, Nthres>& other) const
|
|
|
|
|
{
|
|
|
|
|
return other.size() == size() and std::equal(other.data(), other.data() + other.size(), data());
|
|
|
|
|
}
|
|
|
|
|
void push_back(const T& elem)
|
|
|
|
|
{
|
|
|
|
|
resize(size() + 1);
|
|
|
|
|
head[size() - 1] = elem;
|
|
|
|
|
}
|
|
|
|
|
void resize(uint32_t new_size)
|
|
|
|
|
{
|
|
|
|
|
if (new_size == size_) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (capacity() >= new_size) {
|
|
|
|
|
size_ = new_size;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
T* old_data = head;
|
|
|
|
|
uint32_t newcap = new_size + 5;
|
|
|
|
|
head = new T[newcap];
|
|
|
|
|
std::copy(&small_buffer.data[0], &small_buffer.data[size_], head);
|
|
|
|
|
size_ = new_size;
|
|
|
|
|
if (old_data != &small_buffer.data[0]) {
|
|
|
|
|
delete[] old_data;
|
|
|
|
|
}
|
|
|
|
|
small_buffer.cap_ = newcap;
|
|
|
|
|
}
|
|
|
|
|
bool is_in_small_buffer() const { return head == &small_buffer.data[0]; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
union {
|
|
|
|
|
T data[Nthres];
|
|
|
|
|
uint32_t cap_;
|
|
|
|
|
} small_buffer;
|
|
|
|
|
uint32_t size_;
|
|
|
|
|
T* head;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
ext packing
|
|
|
|
|
*********************/
|
|
|
|
@ -250,6 +352,15 @@ private:
|
|
|
|
|
SRSASN_CODE pack_unsupported_ext_flag(bit_ref& bref, bool ext);
|
|
|
|
|
SRSASN_CODE unpack_unsupported_ext_flag(bool& ext, bit_ref& bref);
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
asn1 null packing
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
struct asn1_null_t {
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return SRSASN_SUCCESS; }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) const { return SRSASN_SUCCESS; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
enum packing
|
|
|
|
|
************************/
|
|
|
|
@ -337,66 +448,26 @@ public:
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
integer packing
|
|
|
|
|
PER encoding
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
// Constrained Whole Number
|
|
|
|
|
template <class IntType>
|
|
|
|
|
SRSASN_CODE pack_unalign_integer(bit_ref& bref, IntType n, IntType lb, IntType ub);
|
|
|
|
|
/* X.691 - Section 10.5 - Constrained Whole Number */
|
|
|
|
|
template <class IntType>
|
|
|
|
|
SRSASN_CODE unpack_unalign_integer(IntType& n, bit_ref& bref, IntType lb, IntType ub);
|
|
|
|
|
SRSASN_CODE pack_constrained_whole_number(bit_ref& bref, IntType n, IntType lb, IntType ub, bool aligned);
|
|
|
|
|
template <class IntType>
|
|
|
|
|
struct UnalignedIntegerPacker {
|
|
|
|
|
UnalignedIntegerPacker(IntType lb_, IntType ub_) : lb(lb_), ub(ub_) {}
|
|
|
|
|
const IntType lb;
|
|
|
|
|
const IntType ub;
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, IntType n) const;
|
|
|
|
|
SRSASN_CODE unpack(IntType& n, bit_ref& bref) const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class IntType, IntType lb, IntType ub>
|
|
|
|
|
struct unaligned_integer {
|
|
|
|
|
IntType value;
|
|
|
|
|
unaligned_integer() = default;
|
|
|
|
|
unaligned_integer(IntType value_) : value(value_) {}
|
|
|
|
|
operator IntType() { return value; }
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return pack_unalign_integer(bref, value, lb, ub); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return unpack_unalign_integer(value, bref, lb, ub); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class IntType>
|
|
|
|
|
SRSASN_CODE pack_align_integer(bit_ref& bref, IntType n, IntType lb, IntType ub);
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE unpack_align_integer(IntType& intval, bit_ref& bref, IntType lb, IntType ub);
|
|
|
|
|
template <class IntType>
|
|
|
|
|
struct AlignedIntegerPacker {
|
|
|
|
|
AlignedIntegerPacker(IntType lb_, IntType ub_);
|
|
|
|
|
IntType lb;
|
|
|
|
|
IntType ub;
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, IntType n);
|
|
|
|
|
SRSASN_CODE unpack(IntType& n, bit_ref& bref);
|
|
|
|
|
};
|
|
|
|
|
SRSASN_CODE unpack_constrained_whole_number(IntType& n, bit_ref& bref, IntType lb, IntType ub, bool aligned);
|
|
|
|
|
|
|
|
|
|
// Normally Small non-negative whole number
|
|
|
|
|
/* X.691 - Section 10.6 - Normally small non-negative whole Number */
|
|
|
|
|
template <typename UintType>
|
|
|
|
|
SRSASN_CODE pack_norm_small_integer(bit_ref& bref, UintType n);
|
|
|
|
|
SRSASN_CODE pack_norm_small_non_neg_whole_number(bit_ref& bref, UintType n);
|
|
|
|
|
template <typename UintType>
|
|
|
|
|
SRSASN_CODE unpack_norm_small_integer(UintType& n, bit_ref& bref);
|
|
|
|
|
SRSASN_CODE unpack_norm_small_non_neg_whole_number(UintType& n, bit_ref& bref);
|
|
|
|
|
|
|
|
|
|
// Unconstrained Whole Number
|
|
|
|
|
// FIXME: Implement
|
|
|
|
|
inline SRSASN_CODE pack_unconstrained_integer(bit_ref& bref, int64_t n)
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
srsasn_log_print(LOG_LEVEL_ERROR, "Not implemented\n");
|
|
|
|
|
return SRSASN_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
inline SRSASN_CODE unpack_unconstrained_integer(int64_t& n, bit_ref& bref)
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
srsasn_log_print(LOG_LEVEL_ERROR, "Not implemented\n");
|
|
|
|
|
return SRSASN_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
/* X.691 - Section 10.8 - Unconstrained Whole Number */
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE pack_unconstrained_whole_number(bit_ref& bref, IntType n, bool aligned);
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE unpack_unconstrained_whole_number(IntType& n, bit_ref& bref, bool aligned);
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
length determinant
|
|
|
|
@ -404,13 +475,66 @@ inline SRSASN_CODE unpack_unconstrained_integer(int64_t& n, bit_ref& bref)
|
|
|
|
|
|
|
|
|
|
// Pack as whole constrained number
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE pack_length(bit_ref& bref, IntType n, IntType lb, IntType ub);
|
|
|
|
|
SRSASN_CODE pack_length(bit_ref& bref, IntType n, IntType lb, IntType ub, bool aligned = false);
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE unpack_length(IntType& n, bit_ref& bref, IntType lb, IntType ub);
|
|
|
|
|
SRSASN_CODE unpack_length(IntType& n, bit_ref& bref, IntType lb, IntType ub, bool aligned = false);
|
|
|
|
|
|
|
|
|
|
// Pack as a small non-negative whole number
|
|
|
|
|
SRSASN_CODE pack_length(bit_ref& ref, uint32_t val);
|
|
|
|
|
SRSASN_CODE unpack_length(uint32_t& val, bit_ref& ref);
|
|
|
|
|
SRSASN_CODE pack_length(bit_ref& ref, uint32_t val, bool aligned = false);
|
|
|
|
|
SRSASN_CODE unpack_length(uint32_t& val, bit_ref& ref, bool aligned = false);
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
Integer
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE pack_integer(bit_ref& bref,
|
|
|
|
|
IntType n,
|
|
|
|
|
IntType lb = std::numeric_limits<IntType>::min(),
|
|
|
|
|
IntType ub = std::numeric_limits<IntType>::max(),
|
|
|
|
|
bool has_ext = false,
|
|
|
|
|
bool aligned = false);
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE unpack_integer(IntType& n,
|
|
|
|
|
bit_ref& bref,
|
|
|
|
|
IntType lb = std::numeric_limits<IntType>::min(),
|
|
|
|
|
IntType ub = std::numeric_limits<IntType>::max(),
|
|
|
|
|
bool has_ext = false,
|
|
|
|
|
bool aligned = false);
|
|
|
|
|
// unconstrained case
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE pack_unconstrained_integer(bit_ref& bref, IntType n, bool has_ext = false, bool aligned = false);
|
|
|
|
|
template <typename IntType>
|
|
|
|
|
SRSASN_CODE unpack_unconstrained_integer(IntType& n, bit_ref& bref, bool has_ext = false, bool aligned = false);
|
|
|
|
|
|
|
|
|
|
template <class IntType>
|
|
|
|
|
struct integer_packer {
|
|
|
|
|
integer_packer(IntType lb_, IntType ub_, bool has_ext_ = false, bool aligned_ = false);
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, IntType n);
|
|
|
|
|
SRSASN_CODE unpack(IntType& n, bit_ref& bref);
|
|
|
|
|
IntType lb;
|
|
|
|
|
IntType ub;
|
|
|
|
|
bool has_ext;
|
|
|
|
|
bool aligned;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class IntType,
|
|
|
|
|
IntType LB = std::numeric_limits<IntType>::min(),
|
|
|
|
|
IntType UB = std::numeric_limits<IntType>::max(),
|
|
|
|
|
bool Ext = false,
|
|
|
|
|
bool Al = false>
|
|
|
|
|
class integer
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static const IntType ub = UB, lb = LB;
|
|
|
|
|
static const bool has_ext = Ext, is_aligned = Al;
|
|
|
|
|
IntType value;
|
|
|
|
|
integer() = default;
|
|
|
|
|
integer(IntType value_) : value(value_) {}
|
|
|
|
|
operator IntType() { return value; }
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return pack_integer(bref, value, lb, ub, has_ext, is_aligned); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return unpack_integer(value, bref, lb, ub, has_ext, is_aligned); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/************************
|
|
|
|
|
General Packer/Unpacker
|
|
|
|
@ -459,7 +583,7 @@ void string_to_octstring(uint8_t* ptr, const std::string& str);
|
|
|
|
|
fixed_octstring
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
template <uint32_t N>
|
|
|
|
|
template <uint32_t N, bool aligned = false>
|
|
|
|
|
class fixed_octstring
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
@ -471,7 +595,7 @@ public:
|
|
|
|
|
|
|
|
|
|
static uint32_t size() { return N; }
|
|
|
|
|
std::string to_string() const { return octstring_to_string(&octets_[0], N); }
|
|
|
|
|
fixed_octstring<N>& from_string(const std::string& hexstr)
|
|
|
|
|
fixed_octstring<N, aligned>& from_string(const std::string& hexstr)
|
|
|
|
|
{
|
|
|
|
|
if (hexstr.size() != 2 * N) {
|
|
|
|
|
srsasn_log_print(LOG_LEVEL_ERROR, "The provided hex string size is not valid (%d!=2*%d).\n", hexstr.size(), N);
|
|
|
|
@ -481,7 +605,7 @@ public:
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
uint64_t to_number() const { return octstring_to_number(&octets_[0], size()); }
|
|
|
|
|
fixed_octstring<N>& from_number(uint64_t val)
|
|
|
|
|
fixed_octstring<N, aligned>& from_number(uint64_t val)
|
|
|
|
|
{
|
|
|
|
|
number_to_octstring(&octets_[0], val, size());
|
|
|
|
|
return *this;
|
|
|
|
@ -494,24 +618,31 @@ private:
|
|
|
|
|
std::array<uint8_t, N> octets_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <uint32_t N>
|
|
|
|
|
SRSASN_CODE fixed_octstring<N>::pack(bit_ref& bref) const
|
|
|
|
|
/**
|
|
|
|
|
* X.691 Section 16 - Encoding the octetstring type
|
|
|
|
|
* @tparam N - number of items
|
|
|
|
|
* @tparam ext - aligned variant
|
|
|
|
|
* @param bref
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
template <uint32_t N, bool aligned>
|
|
|
|
|
SRSASN_CODE fixed_octstring<N, aligned>::pack(bit_ref& bref) const
|
|
|
|
|
{
|
|
|
|
|
// if(N > 2) { // X.691 Sec.16
|
|
|
|
|
// bref.align_bytes_zero();
|
|
|
|
|
// }
|
|
|
|
|
if (aligned and N > 2) {
|
|
|
|
|
bref.align_bytes_zero();
|
|
|
|
|
}
|
|
|
|
|
for (uint32_t i = 0; i < size(); ++i) {
|
|
|
|
|
bref.pack(octets_[i], 8);
|
|
|
|
|
HANDLE_CODE(bref.pack(octets_[i], 8));
|
|
|
|
|
}
|
|
|
|
|
return SRSASN_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <uint32_t N>
|
|
|
|
|
SRSASN_CODE fixed_octstring<N>::unpack(bit_ref& bref)
|
|
|
|
|
template <uint32_t N, bool aligned>
|
|
|
|
|
SRSASN_CODE fixed_octstring<N, aligned>::unpack(bit_ref& bref)
|
|
|
|
|
{
|
|
|
|
|
// if(N > 2) { // X.691 Sec.16
|
|
|
|
|
// bref.align_bytes_zero();
|
|
|
|
|
// }
|
|
|
|
|
if (aligned and N > 2) {
|
|
|
|
|
bref.align_bytes_zero();
|
|
|
|
|
}
|
|
|
|
|
for (uint32_t i = 0; i < size(); ++i) {
|
|
|
|
|
HANDLE_CODE(bref.unpack(octets_[i], 8));
|
|
|
|
|
}
|
|
|
|
@ -522,15 +653,18 @@ SRSASN_CODE fixed_octstring<N>::unpack(bit_ref& bref)
|
|
|
|
|
dyn_octstring
|
|
|
|
|
************************/
|
|
|
|
|
|
|
|
|
|
class dyn_octstring
|
|
|
|
|
template <bool Al = false>
|
|
|
|
|
class unbounded_octstring
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
dyn_octstring() = default;
|
|
|
|
|
dyn_octstring(uint32_t new_size) : octets_(new_size) {}
|
|
|
|
|
static const bool aligned = Al;
|
|
|
|
|
|
|
|
|
|
unbounded_octstring() = default;
|
|
|
|
|
explicit unbounded_octstring(uint32_t new_size) : octets_(new_size) {}
|
|
|
|
|
|
|
|
|
|
const uint8_t& operator[](uint32_t idx) const { return octets_[idx]; }
|
|
|
|
|
uint8_t& operator[](uint32_t idx) { return octets_[idx]; }
|
|
|
|
|
bool operator==(const dyn_octstring& other) const { return octets_ == other.octets_; }
|
|
|
|
|
bool operator==(const unbounded_octstring<Al>& other) const { return octets_ == other.octets_; }
|
|
|
|
|
void resize(uint32_t new_size) { octets_.resize(new_size); }
|
|
|
|
|
uint32_t size() const { return octets_.size(); }
|
|
|
|
|
uint8_t* data() { return &octets_[0]; }
|
|
|
|
@ -539,9 +673,9 @@ public:
|
|
|
|
|
SRSASN_CODE pack(bit_ref& ie_ref) const;
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& ie_ref);
|
|
|
|
|
std::string to_string() const;
|
|
|
|
|
dyn_octstring& from_string(const std::string& hexstr);
|
|
|
|
|
unbounded_octstring<Al>& from_string(const std::string& hexstr);
|
|
|
|
|
uint64_t to_number() const { return octstring_to_number(&octets_[0], size()); }
|
|
|
|
|
dyn_octstring& from_number(uint64_t val)
|
|
|
|
|
unbounded_octstring<Al>& from_number(uint64_t val)
|
|
|
|
|
{
|
|
|
|
|
number_to_octstring(&octets_[0], val, size());
|
|
|
|
|
return *this;
|
|
|
|
@ -551,6 +685,8 @@ private:
|
|
|
|
|
dyn_array<uint8_t> octets_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using dyn_octstring = unbounded_octstring<false>;
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
common bitstring
|
|
|
|
|
*********************/
|
|
|
|
@ -563,16 +699,16 @@ inline bool bitstring_get(const uint8_t* ptr, uint32_t idx)
|
|
|
|
|
{
|
|
|
|
|
uint32_t byte_idx = idx / 8;
|
|
|
|
|
uint32_t offset = idx % 8;
|
|
|
|
|
return (ptr[byte_idx] & (1 << offset)) > 0;
|
|
|
|
|
return (ptr[byte_idx] & (1u << offset)) > 0;
|
|
|
|
|
}
|
|
|
|
|
inline void bitstring_set(uint8_t* ptr, uint32_t idx, bool value)
|
|
|
|
|
{
|
|
|
|
|
uint32_t byte_idx = idx / 8;
|
|
|
|
|
uint32_t offset = idx % 8;
|
|
|
|
|
if (value) {
|
|
|
|
|
ptr[byte_idx] |= (1 << offset);
|
|
|
|
|
ptr[byte_idx] |= (1u << offset);
|
|
|
|
|
} else {
|
|
|
|
|
ptr[byte_idx] &= ((uint16_t)(1 << 8) - 1) - (1 << offset);
|
|
|
|
|
ptr[byte_idx] &= ((uint16_t)(1u << 8) - 1) - (1 << offset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -586,10 +722,13 @@ SRSASN_CODE pack_fixed_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbi
|
|
|
|
|
SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nbits);
|
|
|
|
|
SRSASN_CODE unpack_fixed_bitstring(uint8_t* buf, bool& ext, bit_ref& bref, uint32_t nbits);
|
|
|
|
|
|
|
|
|
|
template <uint32_t N>
|
|
|
|
|
template <uint32_t N, bool Ext = false, bool Al = false>
|
|
|
|
|
class fixed_bitstring
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using type_t = fixed_bitstring<N, Ext, Al>;
|
|
|
|
|
static const bool has_ext = Ext, is_aligned = Al;
|
|
|
|
|
|
|
|
|
|
fixed_bitstring() { memset(&octets_[0], 0, nof_octets()); }
|
|
|
|
|
fixed_bitstring(const std::string& s)
|
|
|
|
|
{
|
|
|
|
@ -603,16 +742,13 @@ public:
|
|
|
|
|
}
|
|
|
|
|
bool get(uint32_t idx) const { return bitstring_get(&octets_[0], idx); }
|
|
|
|
|
void set(uint32_t idx, bool value) { bitstring_set(&octets_[0], idx, value); }
|
|
|
|
|
bool operator==(const fixed_bitstring<N>& other) const { return octets_ == other.octets_; }
|
|
|
|
|
bool operator==(const char* other_str) const
|
|
|
|
|
{
|
|
|
|
|
return strlen(other_str) == N and (*this) == fixed_bitstring<N>(other_str);
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const type_t& other) const { return octets_ == other.octets_; }
|
|
|
|
|
bool operator==(const char* other_str) const { return strlen(other_str) == N and (*this) == type_t(other_str); }
|
|
|
|
|
uint32_t nof_octets() const { return (uint32_t)ceilf(N / 8.0f); }
|
|
|
|
|
uint32_t length() const { return N; }
|
|
|
|
|
std::string to_string() const { return bitstring_to_string(&octets_[0], length()); }
|
|
|
|
|
uint64_t to_number() const { return bitstring_to_number(&octets_[0], length()); }
|
|
|
|
|
fixed_bitstring<N>& from_number(uint64_t val)
|
|
|
|
|
type_t& from_number(uint64_t val)
|
|
|
|
|
{
|
|
|
|
|
number_to_bitstring(&octets_[0], val, length());
|
|
|
|
|
return *this;
|
|
|
|
@ -621,53 +757,193 @@ public:
|
|
|
|
|
const uint8_t* data() const { return &octets_[0]; }
|
|
|
|
|
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return pack_fixed_bitstring(bref, data(), N); }
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, bool ext) const { return pack_fixed_bitstring(bref, data(), N, ext); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return unpack_fixed_bitstring(data(), bref, N); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref, bool& ext) { return unpack_fixed_bitstring(data(), ext, bref, N); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::array<uint8_t, (uint32_t)((N + 7) / 8)> octets_; // ceil(N/8.0)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
dyn_bitstring
|
|
|
|
|
bounded_bitstring
|
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
|
|
class dyn_bitstring
|
|
|
|
|
namespace bitstring_utils {
|
|
|
|
|
SRSASN_CODE
|
|
|
|
|
pack(bit_ref& bref, const uint8_t* data, uint32_t size, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned);
|
|
|
|
|
SRSASN_CODE unpack_length_prefix(uint32_t& len, bit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned);
|
|
|
|
|
SRSASN_CODE unpack_bitfield(uint8_t* buf, bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool is_aligned);
|
|
|
|
|
SRSASN_CODE
|
|
|
|
|
unpack_fixed_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nof_bits, bool has_ext = false, bool is_aligned = false);
|
|
|
|
|
} // namespace bitstring_utils
|
|
|
|
|
|
|
|
|
|
template <typename BitStringType>
|
|
|
|
|
class base_bitstring
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
using derived_t = BitStringType;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
dyn_bitstring() : n_bits(0) {}
|
|
|
|
|
dyn_bitstring(uint32_t n_bits_);
|
|
|
|
|
dyn_bitstring(const char* s);
|
|
|
|
|
bool get(uint32_t idx) const { return bitstring_get(derived()->data(), idx); }
|
|
|
|
|
void set(uint32_t idx, bool value) { bitstring_set(derived()->data(), idx, value); }
|
|
|
|
|
uint32_t nof_octets() const { return ceil_frac(derived()->length(), 8u); }
|
|
|
|
|
|
|
|
|
|
std::string to_string() const { return bitstring_to_string(derived()->data(), derived()->length()); }
|
|
|
|
|
derived_t& from_string(const std::string& s)
|
|
|
|
|
{
|
|
|
|
|
if (s.size() < derived_t::lb or s.size() > derived_t::ub) {
|
|
|
|
|
srsasn_log_print(LOG_LEVEL_ERROR,
|
|
|
|
|
"The provided string size=%d is not withing the bounds [%d, %d]\n",
|
|
|
|
|
s.size(),
|
|
|
|
|
derived_t::lb,
|
|
|
|
|
derived_t::ub);
|
|
|
|
|
} else {
|
|
|
|
|
derived()->resize(s.size());
|
|
|
|
|
for (uint32_t i = 0; i < s.size(); ++i) {
|
|
|
|
|
set(s.size() - i - 1, s[i] == '1');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *derived();
|
|
|
|
|
}
|
|
|
|
|
uint64_t to_number() const { return bitstring_to_number(derived()->data(), derived()->length()); }
|
|
|
|
|
derived_t& from_number(uint64_t val)
|
|
|
|
|
{
|
|
|
|
|
uint32_t nof_bits = (uint32_t)ceilf(log2(val));
|
|
|
|
|
if (nof_bits > derived()->length()) {
|
|
|
|
|
derived()->resize(nof_bits);
|
|
|
|
|
}
|
|
|
|
|
number_to_bitstring(derived()->data(), val, derived()->length());
|
|
|
|
|
return *derived();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const dyn_bitstring& other) const { return octets_ == other.octets_; }
|
|
|
|
|
bool operator==(const char* other_str) const;
|
|
|
|
|
bool get(uint32_t idx) const { return bitstring_get(&octets_[0], idx); }
|
|
|
|
|
void set(uint32_t idx, bool value) { bitstring_set(&octets_[0], idx, value); }
|
|
|
|
|
bool operator==(const base_bitstring<BitStringType>& other) const
|
|
|
|
|
{
|
|
|
|
|
return derived()->length() == other.derived()->length() and
|
|
|
|
|
std::equal(derived()->data(), derived()->data() + derived()->nof_octets(), other.derived()->data());
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const char* other_str) const
|
|
|
|
|
{
|
|
|
|
|
return strlen(other_str) == derived()->length() and (*this) == derived_t{}.from_string(other_str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void resize(uint32_t new_size);
|
|
|
|
|
uint32_t length() const { return n_bits; }
|
|
|
|
|
uint32_t nof_octets() const { return (uint32_t)ceilf(length() / 8.0f); }
|
|
|
|
|
std::string to_string() const { return bitstring_to_string(&octets_[0], length()); }
|
|
|
|
|
uint64_t to_number() const { return bitstring_to_number(&octets_[0], length()); }
|
|
|
|
|
dyn_bitstring& from_number(uint64_t val)
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const
|
|
|
|
|
{
|
|
|
|
|
number_to_bitstring(&octets_[0], val, length());
|
|
|
|
|
return *this;
|
|
|
|
|
return bitstring_utils::pack(bref,
|
|
|
|
|
derived()->data(),
|
|
|
|
|
derived()->length(),
|
|
|
|
|
derived_t::lb,
|
|
|
|
|
derived_t::ub,
|
|
|
|
|
derived_t::has_ext,
|
|
|
|
|
derived_t::is_aligned);
|
|
|
|
|
}
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref)
|
|
|
|
|
{
|
|
|
|
|
// X.691, subclause 15.11
|
|
|
|
|
uint32_t nbits;
|
|
|
|
|
HANDLE_CODE(bitstring_utils::unpack_length_prefix(
|
|
|
|
|
nbits, bref, derived_t::lb, derived_t::ub, derived_t::has_ext, derived_t::is_aligned));
|
|
|
|
|
derived()->resize(nbits);
|
|
|
|
|
return bitstring_utils::unpack_bitfield(
|
|
|
|
|
derived()->data(), bref, nbits, derived_t::lb, derived_t::ub, derived_t::is_aligned);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
derived_t* derived() { return static_cast<derived_t*>(this); }
|
|
|
|
|
const derived_t* derived() const { return static_cast<const derived_t*>(this); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <uint32_t LB, uint32_t UB, bool ext = false, bool aligned = false>
|
|
|
|
|
class bounded_bitstring : public base_bitstring<bounded_bitstring<LB, UB, ext, aligned> >
|
|
|
|
|
{
|
|
|
|
|
using base_t = base_bitstring<bounded_bitstring<LB, UB> >;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static const uint32_t lb = LB, ub = UB;
|
|
|
|
|
static const bool has_ext = ext, is_aligned = aligned;
|
|
|
|
|
|
|
|
|
|
explicit bounded_bitstring(uint32_t siz_ = 0) { resize(siz_); }
|
|
|
|
|
|
|
|
|
|
const uint8_t* data() const { return &octets_[0]; }
|
|
|
|
|
uint8_t* data() { return &octets_[0]; }
|
|
|
|
|
uint32_t length() const { return nof_bits; }
|
|
|
|
|
void resize(uint32_t new_size)
|
|
|
|
|
{
|
|
|
|
|
nof_bits = new_size;
|
|
|
|
|
octets_.resize(this->nof_octets());
|
|
|
|
|
memset(data(), 0, this->nof_octets());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bounded_array<uint8_t, ceil_frac(ub, 8u)> octets_;
|
|
|
|
|
uint32_t nof_bits = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
dyn_bitstring
|
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
|
|
template <bool Ext = false, bool Al = false>
|
|
|
|
|
class unbounded_bitstring : public base_bitstring<unbounded_bitstring<Ext, Al> >
|
|
|
|
|
{
|
|
|
|
|
using base_t = base_bitstring<unbounded_bitstring<Ext, Al> >;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static const uint32_t lb = 0, ub = std::numeric_limits<uint32_t>::max();
|
|
|
|
|
static const bool has_ext = Ext, is_aligned = Al;
|
|
|
|
|
|
|
|
|
|
explicit unbounded_bitstring(uint32_t siz_ = 0) { resize(siz_); }
|
|
|
|
|
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0) const;
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref, bool ext, uint32_t lb = 0, uint32_t ub = 0) const;
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0);
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref, bool& ext, uint32_t lb = 0, uint32_t ub = 0);
|
|
|
|
|
const uint8_t* data() const { return &octets_[0]; }
|
|
|
|
|
uint8_t* data() { return &octets_[0]; }
|
|
|
|
|
uint32_t length() const { return n_bits; }
|
|
|
|
|
void resize(uint32_t new_size)
|
|
|
|
|
{
|
|
|
|
|
n_bits = new_size;
|
|
|
|
|
octets_.resize(this->nof_octets());
|
|
|
|
|
memset(data(), 0, this->nof_octets()); // resize always resets content
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
dyn_array<uint8_t> octets_;
|
|
|
|
|
uint32_t n_bits;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using dyn_bitstring = unbounded_bitstring<false, false>;
|
|
|
|
|
|
|
|
|
|
// class dyn_bitstring
|
|
|
|
|
//{
|
|
|
|
|
// public:
|
|
|
|
|
// dyn_bitstring() = default;
|
|
|
|
|
// dyn_bitstring(uint32_t n_bits_);
|
|
|
|
|
// dyn_bitstring(const char* s);
|
|
|
|
|
//
|
|
|
|
|
// bool operator==(const dyn_bitstring& other) const { return octets_ == other.octets_; }
|
|
|
|
|
// bool operator==(const char* other_str) const;
|
|
|
|
|
// bool get(uint32_t idx) const { return bitstring_get(&octets_[0], idx); }
|
|
|
|
|
// void set(uint32_t idx, bool value) { bitstring_set(&octets_[0], idx, value); }
|
|
|
|
|
//
|
|
|
|
|
// void resize(uint32_t new_size);
|
|
|
|
|
// uint32_t length() const { return n_bits; }
|
|
|
|
|
// uint32_t nof_octets() const { return (uint32_t)ceilf(length() / 8.0f); }
|
|
|
|
|
// std::string to_string() const { return bitstring_to_string(&octets_[0], length()); }
|
|
|
|
|
// uint64_t to_number() const { return bitstring_to_number(&octets_[0], length()); }
|
|
|
|
|
// dyn_bitstring& from_number(uint64_t val)
|
|
|
|
|
// {
|
|
|
|
|
// number_to_bitstring(&octets_[0], val, length());
|
|
|
|
|
// return *this;
|
|
|
|
|
// }
|
|
|
|
|
// const uint8_t* data() const { return &octets_[0]; }
|
|
|
|
|
// uint8_t* data() { return &octets_[0]; }
|
|
|
|
|
//
|
|
|
|
|
// SRSASN_CODE pack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0) const;
|
|
|
|
|
// SRSASN_CODE pack(bit_ref& bref, bool ext, uint32_t lb = 0, uint32_t ub = 0) const;
|
|
|
|
|
// SRSASN_CODE unpack(bit_ref& bref, uint32_t lb = 0, uint32_t ub = 0);
|
|
|
|
|
// SRSASN_CODE unpack(bit_ref& bref, bool& ext, uint32_t lb = 0, uint32_t ub = 0);
|
|
|
|
|
//
|
|
|
|
|
// private:
|
|
|
|
|
// dyn_array<uint8_t> octets_;
|
|
|
|
|
// uint32_t n_bits = 0;
|
|
|
|
|
//};
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
fixed sequence of
|
|
|
|
|
*********************/
|
|
|
|
@ -729,9 +1005,14 @@ struct FixedSeqOfPacker {
|
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
|
|
template <class ArrayType, class ItemPacker>
|
|
|
|
|
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb, uint32_t ub, ItemPacker packer)
|
|
|
|
|
{
|
|
|
|
|
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub));
|
|
|
|
|
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref,
|
|
|
|
|
const ArrayType& seqof,
|
|
|
|
|
uint32_t lb,
|
|
|
|
|
uint32_t ub,
|
|
|
|
|
ItemPacker packer,
|
|
|
|
|
bool aligned = false)
|
|
|
|
|
{
|
|
|
|
|
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub, aligned));
|
|
|
|
|
for (uint32_t i = 0; i < seqof.size(); ++i) {
|
|
|
|
|
HANDLE_CODE(packer.pack(bref, seqof[i]));
|
|
|
|
|
}
|
|
|
|
@ -739,9 +1020,9 @@ SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class ArrayType>
|
|
|
|
|
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb, uint32_t ub)
|
|
|
|
|
SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb, uint32_t ub, bool aligned = false)
|
|
|
|
|
{
|
|
|
|
|
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub));
|
|
|
|
|
HANDLE_CODE(pack_length(bref, seqof.size(), lb, ub, aligned));
|
|
|
|
|
for (uint32_t i = 0; i < seqof.size(); ++i) {
|
|
|
|
|
HANDLE_CODE(seqof[i].pack(bref));
|
|
|
|
|
}
|
|
|
|
@ -749,10 +1030,15 @@ SRSASN_CODE pack_dyn_seq_of(bit_ref& bref, const ArrayType& seqof, uint32_t lb,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class ArrayType, class ItemUnpacker>
|
|
|
|
|
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint32_t ub, ItemUnpacker unpacker)
|
|
|
|
|
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof,
|
|
|
|
|
bit_ref& bref,
|
|
|
|
|
uint32_t lb,
|
|
|
|
|
uint32_t ub,
|
|
|
|
|
ItemUnpacker unpacker,
|
|
|
|
|
bool aligned = false)
|
|
|
|
|
{
|
|
|
|
|
uint32_t nof_items;
|
|
|
|
|
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub));
|
|
|
|
|
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub, aligned));
|
|
|
|
|
seqof.resize(nof_items);
|
|
|
|
|
for (uint32_t i = 0; i < nof_items; ++i) {
|
|
|
|
|
HANDLE_CODE(unpacker.unpack(seqof[i], bref));
|
|
|
|
@ -761,10 +1047,10 @@ SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class ArrayType>
|
|
|
|
|
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint32_t ub)
|
|
|
|
|
SRSASN_CODE unpack_dyn_seq_of(ArrayType& seqof, bit_ref& bref, uint32_t lb, uint32_t ub, bool aligned = false)
|
|
|
|
|
{
|
|
|
|
|
uint32_t nof_items;
|
|
|
|
|
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub));
|
|
|
|
|
HANDLE_CODE(unpack_length(nof_items, bref, lb, ub, aligned));
|
|
|
|
|
seqof.resize(nof_items);
|
|
|
|
|
for (uint32_t i = 0; i < nof_items; ++i) {
|
|
|
|
|
HANDLE_CODE(seqof[i].unpack(bref));
|
|
|
|
@ -790,87 +1076,50 @@ struct SeqOfPacker {
|
|
|
|
|
uint32_t ub;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class ItemType, uint32_t lb, uint32_t ub>
|
|
|
|
|
template <class ItemType, uint32_t lb, uint32_t ub, bool aligned = false>
|
|
|
|
|
struct dyn_seq_of : public dyn_array<ItemType> {
|
|
|
|
|
SeqOfPacker<Packer> packer;
|
|
|
|
|
dyn_seq_of() : packer(lb, ub, Packer()) {}
|
|
|
|
|
dyn_seq_of(const dyn_array<ItemType>& other) : dyn_array<ItemType>(other), packer(lb, ub, Packer()) {}
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return packer.pack(bref, *this); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return packer.unpack(*this, bref); }
|
|
|
|
|
dyn_seq_of() = default;
|
|
|
|
|
dyn_seq_of(const dyn_array<ItemType>& other) : dyn_array<ItemType>(other) {}
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return pack_dyn_seq_of(bref, *this, lb, ub, aligned); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return unpack_dyn_seq_of(*this, bref, lb, ub, aligned); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
choice utils
|
|
|
|
|
printable string
|
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
|
|
union alignment_t {
|
|
|
|
|
char c;
|
|
|
|
|
float f;
|
|
|
|
|
uint32_t i;
|
|
|
|
|
uint64_t i2;
|
|
|
|
|
double d;
|
|
|
|
|
long double d2;
|
|
|
|
|
uint32_t* ptr;
|
|
|
|
|
};
|
|
|
|
|
#define MAX2(a, b) ((a) > (b)) ? (a) : (b)
|
|
|
|
|
#define MAX4(a, b, c, d) MAX2((MAX2(a, b)), MAX2(c, d))
|
|
|
|
|
#define MAX8(a, b, c, d, e, f, g, h) MAX2((MAX4(a, b, c, d)), (MAX4(e, f, g, h)))
|
|
|
|
|
#define MAX12(a, b, c, d, e, f, g, h, i, j, k, l) MAX2((MAX8(a, b, c, d, e, f, g, h)), (MAX4(i, j, k, l)))
|
|
|
|
|
#define MAX16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
|
|
|
|
|
MAX2((MAX8(a, b, c, d, e, f, g, h)), (MAX8(i, j, k, l, m, n, o, p)))
|
|
|
|
|
#define MAX32( \
|
|
|
|
|
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \
|
|
|
|
|
MAX2((MAX16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)), \
|
|
|
|
|
(MAX16(a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1)))
|
|
|
|
|
|
|
|
|
|
template <size_t SIZE>
|
|
|
|
|
class choice_buffer_t
|
|
|
|
|
/* X.691 - Section 27 - Character Restricted String */
|
|
|
|
|
namespace asn_string_utils {
|
|
|
|
|
SRSASN_CODE
|
|
|
|
|
pack(bit_ref& bref, const std::string& s, size_t lb, size_t ub, size_t alb, size_t aub, bool ext, bool aligned);
|
|
|
|
|
SRSASN_CODE unpack(std::string& s, bit_ref& bref, size_t lb, size_t ub, size_t alb, size_t aub, bool ext, bool aligned);
|
|
|
|
|
} // namespace asn_string_utils
|
|
|
|
|
|
|
|
|
|
template <uint32_t LB,
|
|
|
|
|
uint32_t UB,
|
|
|
|
|
uint32_t ALB = 0,
|
|
|
|
|
uint32_t AUB = std::numeric_limits<uint32_t>::max(),
|
|
|
|
|
bool ext = false,
|
|
|
|
|
bool aligned = false>
|
|
|
|
|
class asn_string
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
struct __attribute__((__may_alias__)) bytes {
|
|
|
|
|
uint8_t buf_[MAX2(SIZE, 8)];
|
|
|
|
|
uint8_t* data() { return &buf_[0]; }
|
|
|
|
|
const uint8_t* data() const { return &buf_[0]; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
T& get()
|
|
|
|
|
{
|
|
|
|
|
return *((T*)buffer.buf_.data());
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T& get() const
|
|
|
|
|
{
|
|
|
|
|
return *((T*)buffer.buf_.data());
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void destroy()
|
|
|
|
|
{
|
|
|
|
|
((T*)buffer.buf_.data())->~T();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void init()
|
|
|
|
|
{
|
|
|
|
|
new (buffer.buf_.data()) T();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void init(const T& other)
|
|
|
|
|
{
|
|
|
|
|
new (buffer.buf_.data()) T(other);
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void set(const T& other)
|
|
|
|
|
{
|
|
|
|
|
get<T>() = other;
|
|
|
|
|
}
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const { return asn_string_utils::pack(bref, str, LB, UB, ALB, AUB, ext, aligned); }
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref) { return asn_string_utils::unpack(str, bref, LB, UB, ALB, AUB, ext, aligned); }
|
|
|
|
|
char& operator[](std::size_t idx) { return str[idx]; }
|
|
|
|
|
const char& operator[](std::size_t idx) const { return str[idx]; }
|
|
|
|
|
void resize(std::size_t newsize) { str.resize(newsize); }
|
|
|
|
|
std::size_t size() const { return str.size(); }
|
|
|
|
|
std::string to_string() const { return str; }
|
|
|
|
|
void from_string(std::string s) { str = std::move(s); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
union {
|
|
|
|
|
alignment_t a_;
|
|
|
|
|
bytes buf_;
|
|
|
|
|
} buffer;
|
|
|
|
|
std::string str;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <uint32_t ALB = 0, uint32_t AUB = std::numeric_limits<uint32_t>::max(), bool ext = false, bool aligned = false>
|
|
|
|
|
using printable_string = asn_string<32, 122, ALB, AUB, ext, aligned>;
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
copy_ptr
|
|
|
|
|
*********************/
|
|
|
|
@ -935,6 +1184,80 @@ copy_ptr<T> make_copy_ptr(const T& t)
|
|
|
|
|
return copy_ptr<T>(new T(t));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
choice utils
|
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
|
|
union alignment_t {
|
|
|
|
|
char c;
|
|
|
|
|
float f;
|
|
|
|
|
uint32_t i;
|
|
|
|
|
uint64_t i2;
|
|
|
|
|
double d;
|
|
|
|
|
long double d2;
|
|
|
|
|
uint32_t* ptr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <std::size_t arg1, std::size_t... others>
|
|
|
|
|
struct static_max;
|
|
|
|
|
|
|
|
|
|
template <std::size_t arg>
|
|
|
|
|
struct static_max<arg> {
|
|
|
|
|
static const std::size_t value = arg;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <std::size_t arg1, std::size_t arg2, std::size_t... others>
|
|
|
|
|
struct static_max<arg1, arg2, others...> {
|
|
|
|
|
static const std::size_t value =
|
|
|
|
|
arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <std::size_t Size, std::size_t Align>
|
|
|
|
|
struct choice_buffer_base_t {
|
|
|
|
|
static const std::size_t data_size = Size;
|
|
|
|
|
static const std::size_t data_align = Align;
|
|
|
|
|
using buffer_t = typename std::aligned_storage<data_size, data_align>::type;
|
|
|
|
|
buffer_t buffer;
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
T& get()
|
|
|
|
|
{
|
|
|
|
|
return *(reinterpret_cast<T*>(&buffer));
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T& get() const
|
|
|
|
|
{
|
|
|
|
|
return *(reinterpret_cast<const T*>(&buffer));
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void destroy()
|
|
|
|
|
{
|
|
|
|
|
get<T>().~T();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void init()
|
|
|
|
|
{
|
|
|
|
|
new (&buffer) T();
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void init(const T& other)
|
|
|
|
|
{
|
|
|
|
|
new (&buffer) T(other);
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void set(const T& other)
|
|
|
|
|
{
|
|
|
|
|
get<T>() = other;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
|
struct choice_buffer_t : public choice_buffer_base_t<static_max<sizeof(alignment_t), sizeof(Ts)...>::value,
|
|
|
|
|
static_max<alignof(alignment_t), alignof(Ts)...>::value> {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using pod_choice_buffer_t = choice_buffer_t<>;
|
|
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
|
ext group
|
|
|
|
|
*********************/
|
|
|
|
@ -946,7 +1269,7 @@ public:
|
|
|
|
|
SRSASN_CODE pack(bit_ref& bref) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bounded_array<bool, 20> groups;
|
|
|
|
|
ext_array<bool> groups;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ext_groups_unpacker_guard
|
|
|
|
@ -960,7 +1283,7 @@ public:
|
|
|
|
|
SRSASN_CODE unpack(bit_ref& bref);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bounded_array<bool, 20> groups;
|
|
|
|
|
ext_array<bool> groups;
|
|
|
|
|
const uint32_t nof_supported_groups;
|
|
|
|
|
uint32_t nof_unpacked_groups = 0;
|
|
|
|
|
bit_ref* bref_tracker = nullptr;
|
|
|
|
@ -973,7 +1296,7 @@ private:
|
|
|
|
|
class varlength_field_pack_guard
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
varlength_field_pack_guard(bit_ref& bref);
|
|
|
|
|
explicit varlength_field_pack_guard(bit_ref& bref, bool align_ = false);
|
|
|
|
|
~varlength_field_pack_guard();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
@ -981,18 +1304,19 @@ private:
|
|
|
|
|
// bit_ref bref0;
|
|
|
|
|
bit_ref* bref_tracker;
|
|
|
|
|
uint8_t buffer[1024];
|
|
|
|
|
bool align;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class varlength_field_unpack_guard
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
varlength_field_unpack_guard(bit_ref& bref);
|
|
|
|
|
explicit varlength_field_unpack_guard(bit_ref& bref, bool align = false);
|
|
|
|
|
~varlength_field_unpack_guard();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bit_ref bref0;
|
|
|
|
|
bit_ref* bref_tracker;
|
|
|
|
|
uint32_t len;
|
|
|
|
|
bit_ref* bref_tracker = nullptr;
|
|
|
|
|
uint32_t len = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*******************
|
|
|
|
|