Coverage Report

Created: 2026-10-28 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ocudu/lib/asn1/asn1_utils.cpp
Line
Count
Source
1
// SPDX-FileCopyrightText: Copyright (C) 2021-2026 Software Radio Systems Limited
2
// SPDX-FileCopyrightText: Copyright (C) 2026 OCUDU contributors
3
// SPDX-License-Identifier: BSD-3-Clause-Open-MPI
4
// Portions of this file may implement 3GPP specifications, which may be subject to additional licensing requirements.
5
6
#include "ocudu/asn1/asn1_utils.h"
7
#include "ocudu/adt/bounded_bitset.h"
8
#include "ocudu/asn1/asn1_ap_utils.h"
9
10
using ocudu::byte_buffer;
11
using ocudu::span;
12
13
namespace asn1 {
14
15
/************************
16
        logging
17
************************/
18
19
void warn_assert(bool cond, const char* filename, int lineno)
20
4
{
21
4
  if (cond) {
22
0
    log_warning("Assertion in [{}][{}] failed.", filename, lineno);
23
0
  }
24
4
}
25
26
void invalid_enum_number(int value, const char* name)
27
0
{
28
0
  log_error("The provided enum value={} of type {} cannot be translated into a number", value, name);
29
0
}
30
31
void assert_choice_type(uint32_t val, uint32_t choice_id)
32
0
{
33
0
  if (OCUDU_UNLIKELY(val != choice_id)) {
34
0
    log_invalid_access_choice_id(val, choice_id);
35
0
  }
36
0
}
37
38
/************************
39
     error handling
40
************************/
41
42
void log_error_code(OCUDUASN_CODE code, const char* filename, int line)
43
809k
{
44
809k
  switch (code) {
45
0
    case OCUDUASN_ERROR_ENCODE_FAIL:
46
0
      log_error("[{}][{}] Encoding failure.", filename, line);
47
0
      break;
48
809k
    case OCUDUASN_ERROR_DECODE_FAIL:
49
809k
      log_error("[{}][{}] Decoding failure.", filename, line);
50
809k
      break;
51
0
    default:
52
0
      log_warning("[{}][{}] OCUDUASN_CODE={} not recognized.", filename, line, (int)code);
53
809k
  }
54
809k
}
55
56
const char* convert_enum_idx(const char* array[], uint32_t nof_types, uint32_t enum_val, const char* enum_type)
57
2.15M
{
58
2.15M
  if (enum_val >= nof_types) {
59
3.18k
    if (enum_val == nof_types) {
60
3.18k
      log_error("The enum of type {} was not initialized.", enum_type);
61
3.18k
    } else {
62
0
      log_error("The enum value={} of type {} is not valid.", enum_val, enum_type);
63
0
    }
64
3.18k
    return "";
65
3.18k
  }
66
2.14M
  return array[enum_val];
67
2.15M
}
68
69
bool convert_enum_str(const char* array[],
70
                      uint32_t    nof_types,
71
                      const char* str,
72
                      uint32_t&   enum_val,
73
                      const char* enum_type)
74
0
{
75
0
  for (uint32_t i = 0; i < nof_types; ++i) {
76
0
    if (strcmp(str, array[i]) == 0) {
77
0
      enum_val = i;
78
0
      return true;
79
0
    }
80
0
  }
81
0
  log_error("The string '{}' is not a valid value for enum type {}.", str, enum_type);
82
0
  return false;
83
0
}
84
85
template <class ItemType>
86
ItemType map_enum_number(ItemType* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type)
87
26.5k
{
88
26.5k
  if (enum_val >= nof_types) {
89
478
    if (enum_val == nof_types) {
90
478
      log_error("The enum of type {} is not initialized.", enum_type);
91
478
    } else {
92
0
      log_error("The enum value={} of type {} cannot be converted to a number.", enum_val, enum_type);
93
0
    }
94
478
    return 0;
95
478
  }
96
26.0k
  return array[enum_val];
97
26.5k
}
unsigned char const asn1::map_enum_number<unsigned char const>(unsigned char const*, unsigned int, unsigned int, char const*)
Line
Count
Source
87
2
{
88
2
  if (enum_val >= nof_types) {
89
0
    if (enum_val == nof_types) {
90
0
      log_error("The enum of type {} is not initialized.", enum_type);
91
0
    } else {
92
0
      log_error("The enum value={} of type {} cannot be converted to a number.", enum_val, enum_type);
93
0
    }
94
0
    return 0;
95
0
  }
96
2
  return array[enum_val];
97
2
}
unsigned short const asn1::map_enum_number<unsigned short const>(unsigned short const*, unsigned int, unsigned int, char const*)
Line
Count
Source
87
22
{
88
22
  if (enum_val >= nof_types) {
89
0
    if (enum_val == nof_types) {
90
0
      log_error("The enum of type {} is not initialized.", enum_type);
91
0
    } else {
92
0
      log_error("The enum value={} of type {} cannot be converted to a number.", enum_val, enum_type);
93
0
    }
94
0
    return 0;
95
0
  }
96
22
  return array[enum_val];
97
22
}
unsigned int const asn1::map_enum_number<unsigned int const>(unsigned int const*, unsigned int, unsigned int, char const*)
Line
Count
Source
87
26.5k
{
88
26.5k
  if (enum_val >= nof_types) {
89
478
    if (enum_val == nof_types) {
90
478
      log_error("The enum of type {} is not initialized.", enum_type);
91
478
    } else {
92
0
      log_error("The enum value={} of type {} cannot be converted to a number.", enum_val, enum_type);
93
0
    }
94
478
    return 0;
95
478
  }
96
26.0k
  return array[enum_val];
97
26.5k
}
Unexecuted instantiation: unsigned long const asn1::map_enum_number<unsigned long const>(unsigned long const*, unsigned int, unsigned int, char const*)
Unexecuted instantiation: signed char const asn1::map_enum_number<signed char const>(signed char const*, unsigned int, unsigned int, char const*)
Unexecuted instantiation: short const asn1::map_enum_number<short const>(short const*, unsigned int, unsigned int, char const*)
Unexecuted instantiation: int const asn1::map_enum_number<int const>(int const*, unsigned int, unsigned int, char const*)
Unexecuted instantiation: long const asn1::map_enum_number<long const>(long const*, unsigned int, unsigned int, char const*)
Unexecuted instantiation: float const asn1::map_enum_number<float const>(float const*, unsigned int, unsigned int, char const*)
98
template const uint8_t
99
map_enum_number<const uint8_t>(const uint8_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
100
template const uint16_t
101
map_enum_number<const uint16_t>(const uint16_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
102
template const uint32_t
103
map_enum_number<const uint32_t>(const uint32_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
104
template const uint64_t
105
map_enum_number<const uint64_t>(const uint64_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
106
template const int8_t
107
map_enum_number<const int8_t>(const int8_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
108
template const int16_t
109
map_enum_number<const int16_t>(const int16_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
110
template const int32_t
111
map_enum_number<const int32_t>(const int32_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
112
template const int64_t
113
map_enum_number<const int64_t>(const int64_t* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
114
template const float
115
map_enum_number<const float>(const float* array, uint32_t nof_types, uint32_t enum_val, const char* enum_type);
116
117
/*********************
118
       bit_ref
119
*********************/
120
121
int bit_ref::distance_bytes() const
122
0
{
123
0
  return static_cast<int>(writer.length());
124
0
}
125
126
int bit_ref::distance() const
127
116
{
128
116
  return 8 * (static_cast<int>(writer.length()) - (offset == 0 ? 0 : 1)) + offset;
129
116
}
130
131
OCUDUASN_CODE bit_ref::pack(uint64_t val, uint32_t n_bits)
132
9.23M
{
133
9.23M
  ocudu_assert(n_bits < 64, "Invalid number of bits passed to pack()");
134
23.9M
  while (n_bits > 0) {
135
14.7M
    if (offset == 0) {
136
6.15M
      if (not writer.append(0)) {
137
0
        return OCUDUASN_ERROR;
138
0
      }
139
6.15M
    }
140
14.7M
    uint64_t mask = ((1ul << n_bits) - 1ul); // bitmap of n_bits ones.
141
14.7M
    val           = val & mask;
142
14.7M
    if (static_cast<uint32_t>(8U - offset) > n_bits) {
143
      // in case n_bits < number of bits left in current byte (ie, last iteration).
144
8.73M
      auto shifted_val = static_cast<uint8_t>(val << (8u - offset - n_bits));
145
8.73M
      writer.back() += shifted_val;
146
8.73M
      offset += n_bits;
147
8.73M
      n_bits = 0;
148
8.73M
    } else {
149
      // in case, space in current byte is lower or equal to n_bits (ie, not the last iteration).
150
6.01M
      auto shifted_val = static_cast<uint8_t>(val >> (n_bits - 8u + offset));
151
6.01M
      writer.back() += shifted_val;
152
6.01M
      n_bits -= 8U - offset;
153
6.01M
      offset = 0;
154
6.01M
    }
155
14.7M
  }
156
9.23M
  return OCUDUASN_SUCCESS;
157
9.23M
}
158
159
OCUDUASN_CODE bit_ref::pack_bytes(ocudu::span<const uint8_t> bytes)
160
0
{
161
0
  if (bytes.empty()) {
162
0
    return OCUDUASN_SUCCESS;
163
0
  }
164
0
  if (offset == 0) {
165
    // Aligned case
166
0
    HANDLE_CODE(writer.append(bytes) ? OCUDUASN_SUCCESS : OCUDUASN_ERROR_ENCODE_FAIL);
167
0
  } else {
168
0
    for (uint8_t byte : bytes) {
169
0
      HANDLE_CODE(pack(byte, 8U));
170
0
    }
171
0
  }
172
0
  return OCUDUASN_SUCCESS;
173
0
}
174
175
OCUDUASN_CODE bit_ref::pack_bytes(ocudu::byte_buffer_view bytes)
176
58
{
177
58
  if (bytes.empty()) {
178
0
    return OCUDUASN_SUCCESS;
179
0
  }
180
58
  if (offset == 0) {
181
    // Aligned case.
182
58
    HANDLE_CODE(writer.append(bytes) ? OCUDUASN_SUCCESS : OCUDUASN_ERROR_ENCODE_FAIL);
183
58
  } else {
184
0
    for (uint8_t byte : bytes) {
185
0
      HANDLE_CODE(pack(byte, 8U));
186
0
    }
187
0
  }
188
58
  return OCUDUASN_SUCCESS;
189
58
}
190
191
OCUDUASN_CODE bit_ref::align_bytes_zero()
192
153k
{
193
153k
  offset = 0;
194
153k
  return OCUDUASN_SUCCESS;
195
153k
}
196
197
cbit_ref cbit_ref::subview(uint32_t offset_bytes, uint32_t len_bytes) const
198
324k
{
199
324k
  const uint32_t buffer_rem_bytes = buffer.end() - it;
200
324k
  const uint32_t nof_bytes_needed = len_bytes + ((offset != 0) ? 1 : 0); // account for the last bits in the last byte.
201
324k
  if (offset_bytes + nof_bytes_needed > buffer_rem_bytes) {
202
24.0k
    log_error("subview: Buffer size limit was achieved");
203
24.0k
    return cbit_ref(ocudu::byte_buffer_view{});
204
24.0k
  }
205
206
300k
  auto     start_it = it + offset_bytes;
207
300k
  cbit_ref v{ocudu::byte_buffer_view(start_it, start_it + nof_bytes_needed)};
208
300k
  v.offset = offset;
209
300k
  return v;
210
324k
}
211
212
int cbit_ref::distance_bytes() const
213
0
{
214
0
  return static_cast<int>(it - buffer.begin()) + (offset != 0 ? 1 : 0);
215
0
}
216
217
int cbit_ref::distance() const
218
0
{
219
0
  return (int)offset + 8 * static_cast<int>(it - buffer.begin());
220
0
}
221
222
int cbit_ref::distance(const cbit_ref& other) const
223
267k
{
224
267k
  return static_cast<int>(it - other.it) * 8 + (static_cast<int>(offset) - static_cast<int>(other.offset));
225
267k
}
226
227
template <class T>
228
OCUDUASN_CODE cbit_ref::unpack(T& val, uint32_t n_bits)
229
38.4M
{
230
38.4M
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
38.4M
  val = 0;
232
90.0M
  while (n_bits > 0) {
233
51.8M
    if (it == buffer.end()) {
234
215k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
215k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
215k
    }
237
51.5M
    if ((uint32_t)(8 - offset) > n_bits) {
238
32.6M
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
32.6M
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
32.6M
      offset += n_bits;
241
32.6M
      n_bits = 0;
242
32.6M
    } else {
243
18.9M
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
18.9M
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
18.9M
      n_bits -= 8 - offset;
246
18.9M
      offset = 0;
247
18.9M
      ++it;
248
18.9M
    }
249
51.5M
  }
250
38.2M
  return OCUDUASN_SUCCESS;
251
38.4M
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<bool>(bool&, unsigned int)
Line
Count
Source
229
19.7M
{
230
19.7M
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
19.7M
  val = 0;
232
39.3M
  while (n_bits > 0) {
233
19.7M
    if (it == buffer.end()) {
234
43.5k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
43.5k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
43.5k
    }
237
19.6M
    if ((uint32_t)(8 - offset) > n_bits) {
238
17.2M
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
17.2M
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
17.2M
      offset += n_bits;
241
17.2M
      n_bits = 0;
242
17.2M
    } else {
243
2.36M
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
2.36M
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
2.36M
      n_bits -= 8 - offset;
246
2.36M
      offset = 0;
247
2.36M
      ++it;
248
2.36M
    }
249
19.6M
  }
250
19.6M
  return OCUDUASN_SUCCESS;
251
19.7M
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<unsigned char>(unsigned char&, unsigned int)
Line
Count
Source
229
8.68M
{
230
8.68M
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
8.68M
  val = 0;
232
23.3M
  while (n_bits > 0) {
233
14.6M
    if (it == buffer.end()) {
234
9.81k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
9.81k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
9.81k
    }
237
14.6M
    if ((uint32_t)(8 - offset) > n_bits) {
238
7.08M
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
7.08M
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
7.08M
      offset += n_bits;
241
7.08M
      n_bits = 0;
242
7.59M
    } else {
243
7.59M
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
7.59M
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
7.59M
      n_bits -= 8 - offset;
246
7.59M
      offset = 0;
247
7.59M
      ++it;
248
7.59M
    }
249
14.6M
  }
250
8.67M
  return OCUDUASN_SUCCESS;
251
8.68M
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<unsigned short>(unsigned short&, unsigned int)
Line
Count
Source
229
3.82M
{
230
3.82M
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
3.82M
  val = 0;
232
12.2M
  while (n_bits > 0) {
233
8.39M
    if (it == buffer.end()) {
234
5.83k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
5.83k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
5.83k
    }
237
8.39M
    if ((uint32_t)(8 - offset) > n_bits) {
238
3.44M
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
3.44M
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
3.44M
      offset += n_bits;
241
3.44M
      n_bits = 0;
242
4.94M
    } else {
243
4.94M
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
4.94M
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
4.94M
      n_bits -= 8 - offset;
246
4.94M
      offset = 0;
247
4.94M
      ++it;
248
4.94M
    }
249
8.39M
  }
250
3.81M
  return OCUDUASN_SUCCESS;
251
3.82M
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<unsigned int>(unsigned int&, unsigned int)
Line
Count
Source
229
6.05M
{
230
6.05M
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
6.05M
  val = 0;
232
14.6M
  while (n_bits > 0) {
233
8.75M
    if (it == buffer.end()) {
234
154k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
154k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
154k
    }
237
8.60M
    if ((uint32_t)(8 - offset) > n_bits) {
238
4.73M
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
4.73M
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
4.73M
      offset += n_bits;
241
4.73M
      n_bits = 0;
242
4.73M
    } else {
243
3.87M
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
3.87M
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
3.87M
      n_bits -= 8 - offset;
246
3.87M
      offset = 0;
247
3.87M
      ++it;
248
3.87M
    }
249
8.60M
  }
250
5.90M
  return OCUDUASN_SUCCESS;
251
6.05M
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<unsigned long>(unsigned long&, unsigned int)
Line
Count
Source
229
37.8k
{
230
37.8k
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
37.8k
  val = 0;
232
85.8k
  while (n_bits > 0) {
233
49.2k
    if (it == buffer.end()) {
234
1.26k
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
1.26k
      return OCUDUASN_ERROR_DECODE_FAIL;
236
1.26k
    }
237
47.9k
    if ((uint32_t)(8 - offset) > n_bits) {
238
2.52k
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
2.52k
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
2.52k
      offset += n_bits;
241
2.52k
      n_bits = 0;
242
45.4k
    } else {
243
45.4k
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
45.4k
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
45.4k
      n_bits -= 8 - offset;
246
45.4k
      offset = 0;
247
45.4k
      ++it;
248
45.4k
    }
249
47.9k
  }
250
36.6k
  return OCUDUASN_SUCCESS;
251
37.8k
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<signed char>(signed char&, unsigned int)
Line
Count
Source
229
50.9k
{
230
50.9k
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
50.9k
  val = 0;
232
127k
  while (n_bits > 0) {
233
76.3k
    if (it == buffer.end()) {
234
14
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
14
      return OCUDUASN_ERROR_DECODE_FAIL;
236
14
    }
237
76.3k
    if ((uint32_t)(8 - offset) > n_bits) {
238
50.8k
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
50.8k
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
50.8k
      offset += n_bits;
241
50.8k
      n_bits = 0;
242
50.8k
    } else {
243
25.5k
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
25.5k
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
25.5k
      n_bits -= 8 - offset;
246
25.5k
      offset = 0;
247
25.5k
      ++it;
248
25.5k
    }
249
76.3k
  }
250
50.9k
  return OCUDUASN_SUCCESS;
251
50.9k
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<short>(short&, unsigned int)
Line
Count
Source
229
53.5k
{
230
53.5k
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
53.5k
  val = 0;
232
137k
  while (n_bits > 0) {
233
83.7k
    if (it == buffer.end()) {
234
56
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
56
      return OCUDUASN_ERROR_DECODE_FAIL;
236
56
    }
237
83.6k
    if ((uint32_t)(8 - offset) > n_bits) {
238
28.3k
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
28.3k
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
28.3k
      offset += n_bits;
241
28.3k
      n_bits = 0;
242
55.2k
    } else {
243
55.2k
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
55.2k
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
55.2k
      n_bits -= 8 - offset;
246
55.2k
      offset = 0;
247
55.2k
      ++it;
248
55.2k
    }
249
83.6k
  }
250
53.5k
  return OCUDUASN_SUCCESS;
251
53.5k
}
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<int>(int&, unsigned int)
Line
Count
Source
229
102
{
230
102
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
102
  val = 0;
232
408
  while (n_bits > 0) {
233
306
    if (it == buffer.end()) {
234
0
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
0
      return OCUDUASN_ERROR_DECODE_FAIL;
236
0
    }
237
306
    if ((uint32_t)(8 - offset) > n_bits) {
238
0
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
0
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
0
      offset += n_bits;
241
0
      n_bits = 0;
242
306
    } else {
243
306
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
306
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
306
      n_bits -= 8 - offset;
246
306
      offset = 0;
247
306
      ++it;
248
306
    }
249
306
  }
250
102
  return OCUDUASN_SUCCESS;
251
102
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<long>(long&, unsigned int)
asn1::OCUDUASN_CODE asn1::cbit_ref::unpack<char>(char&, unsigned int)
Line
Count
Source
229
44.9k
{
230
44.9k
  ocudu_assert(n_bits <= sizeof(T) * 8, "unpack_bits() only supports up to {} bits", sizeof(T) * 8);
231
44.9k
  val = 0;
232
89.5k
  while (n_bits > 0) {
233
44.9k
    if (it == buffer.end()) {
234
420
      log_error("{}: Buffer size limit {} was reached.", __FUNCTION__, buffer.length());
235
420
      return OCUDUASN_ERROR_DECODE_FAIL;
236
420
    }
237
44.5k
    if ((uint32_t)(8 - offset) > n_bits) {
238
0
      uint8_t mask = (uint8_t)(1u << (8u - offset)) - (uint8_t)(1u << (8u - offset - n_bits));
239
0
      val += ((uint32_t)((*it) & mask)) >> (8u - offset - n_bits);
240
0
      offset += n_bits;
241
0
      n_bits = 0;
242
44.5k
    } else {
243
44.5k
      auto mask = static_cast<uint8_t>((1u << (8u - offset)) - 1u);
244
44.5k
      val += ((uint64_t)((*it) & mask)) << (n_bits - 8 + offset);
245
44.5k
      n_bits -= 8 - offset;
246
44.5k
      offset = 0;
247
44.5k
      ++it;
248
44.5k
    }
249
44.5k
  }
250
44.5k
  return OCUDUASN_SUCCESS;
251
44.9k
}
252
template OCUDUASN_CODE cbit_ref::unpack<bool>(bool&, uint32_t n_bits);
253
template OCUDUASN_CODE cbit_ref::unpack<uint8_t>(uint8_t&, uint32_t n_bits);
254
template OCUDUASN_CODE cbit_ref::unpack<uint16_t>(uint16_t&, uint32_t n_bits);
255
template OCUDUASN_CODE cbit_ref::unpack<uint32_t>(uint32_t&, uint32_t n_bits);
256
template OCUDUASN_CODE cbit_ref::unpack<uint64_t>(uint64_t&, uint32_t n_bits);
257
258
OCUDUASN_CODE cbit_ref::unpack_bytes(ocudu::span<uint8_t> bytes)
259
0
{
260
0
  if (bytes.empty()) {
261
0
    return OCUDUASN_SUCCESS;
262
0
  }
263
0
  if (static_cast<std::ptrdiff_t>(bytes.size()) > buffer.end() - it) {
264
0
    log_error("unpack_bytes: Buffer size limit was achieved");
265
0
    return OCUDUASN_ERROR_DECODE_FAIL;
266
0
  }
267
0
  if (offset == 0) {
268
    // Aligned case
269
0
    std::copy(buffer.begin(), buffer.end(), bytes.begin());
270
0
    it += bytes.size();
271
0
  } else {
272
    // Unaligned case
273
0
    for (uint32_t i = 0; i < bytes.size(); ++i) {
274
0
      HANDLE_CODE(unpack(bytes[i], 8));
275
0
    }
276
0
  }
277
0
  return OCUDUASN_SUCCESS;
278
0
}
279
280
OCUDUASN_CODE cbit_ref::align_bytes()
281
1.65M
{
282
1.65M
  if (offset != 0) {
283
755k
    if (it == buffer.end()) {
284
0
      log_error("{}: Buffer size limit {} was achieved.", __FUNCTION__, buffer.length());
285
0
      return OCUDUASN_ERROR_DECODE_FAIL;
286
0
    }
287
755k
    ++it;
288
755k
    offset = 0;
289
755k
  }
290
1.65M
  return OCUDUASN_SUCCESS;
291
1.65M
}
292
293
OCUDUASN_CODE cbit_ref::advance_bits(uint32_t n_bits)
294
0
{
295
0
  uint32_t extra_bits     = (offset + n_bits) % 8;
296
0
  uint32_t bytes_required = ceil_frac(offset + n_bits, 8U);
297
0
  uint32_t bytes_offset   = (offset + n_bits) / 8U;
298
299
0
  if (bytes_required > buffer.end() - it) {
300
0
    log_error("advance_bytes: Buffer size limit was achieved");
301
0
    return OCUDUASN_ERROR_DECODE_FAIL;
302
0
  }
303
0
  it += bytes_offset;
304
0
  offset = extra_bits;
305
0
  return OCUDUASN_SUCCESS;
306
0
}
307
308
OCUDUASN_CODE cbit_ref::advance_bytes(uint32_t bytes)
309
317k
{
310
317k
  if (bytes + (offset != 0 ? 1 : 0) > buffer.end() - it) {
311
22.8k
    log_error("advance_bytes: Buffer size limit was achieved");
312
22.8k
    return OCUDUASN_ERROR_DECODE_FAIL;
313
22.8k
  }
314
295k
  it += bytes;
315
295k
  return OCUDUASN_SUCCESS;
316
317k
}
317
318
/*********************
319
     ext packing
320
*********************/
321
322
OCUDUASN_CODE pack_unsupported_ext_flag(bit_ref& bref, bool ext)
323
0
{
324
0
  HANDLE_CODE(bref.pack(ext, 1));
325
0
  if (ext) {
326
0
    log_error("ASN extensions not currently supported");
327
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
328
0
  }
329
0
  return OCUDUASN_SUCCESS;
330
0
}
331
332
OCUDUASN_CODE unpack_unsupported_ext_flag(bool& ext, cbit_ref& bref)
333
0
{
334
0
  OCUDUASN_CODE ret = bref.unpack(ext, 1);
335
0
  if (ext) {
336
0
    log_error("ASN extensions not currently supported");
337
0
    return OCUDUASN_ERROR_DECODE_FAIL;
338
0
  }
339
0
  return ret;
340
0
}
341
342
/************************
343
      enum packing
344
************************/
345
346
// Pack without extension
347
OCUDUASN_CODE pack_enum(bit_ref& bref, uint32_t enum_val, uint32_t nbits)
348
693k
{
349
693k
  return bref.pack(enum_val, nbits);
350
693k
}
351
352
// Pack with extension
353
OCUDUASN_CODE pack_enum(bit_ref& bref, uint32_t enum_val, uint32_t nbits, uint32_t nof_noext)
354
82.6k
{
355
82.6k
  bool ext = enum_val >= nof_noext;
356
82.6k
  HANDLE_CODE(bref.pack((bool)ext, 1));
357
82.6k
  OCUDUASN_CODE ret;
358
82.6k
  if (not ext) {
359
82.6k
    ret = bref.pack(enum_val, nbits);
360
82.6k
  } else {
361
40
    ret = pack_norm_small_non_neg_whole_number(bref, enum_val - nof_noext);
362
40
  }
363
82.6k
  return ret;
364
82.6k
}
365
366
OCUDUASN_CODE pack_enum(bit_ref& bref, uint32_t e, uint32_t nof_types, uint32_t nof_exts, bool has_ext)
367
775k
{
368
775k
  if (e >= nof_types) {
369
0
    log_error(
370
0
        "The provided enum is not within the range of possible values ({}>={})", (unsigned)e, (unsigned)nof_types);
371
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
372
0
  }
373
775k
  OCUDUASN_CODE ret;
374
775k
  if (has_ext) {
375
82.6k
    uint32_t nof_bits = (uint32_t)std::ceil(std::log2(nof_types - nof_exts));
376
82.6k
    ret               = pack_enum(bref, e, nof_bits, nof_types - nof_exts);
377
693k
  } else {
378
693k
    uint32_t nof_bits = (uint32_t)std::ceil(std::log2(nof_types));
379
693k
    ret               = pack_enum(bref, e, nof_bits);
380
693k
  }
381
775k
  return ret;
382
775k
}
383
384
ValOrError unpack_enum(uint32_t nof_types, uint32_t nof_exts, bool has_ext, cbit_ref& bref)
385
3.86M
{
386
3.86M
  ValOrError ret;
387
3.86M
  if (has_ext) {
388
265k
    uint32_t nof_bits = (uint32_t)std::ceil(std::log2(nof_types - nof_exts));
389
265k
    bool     ext;
390
265k
    ret.code = bref.unpack(ext, 1);
391
265k
    if (ret.code != OCUDUASN_SUCCESS) {
392
1.67k
      return ret;
393
1.67k
    }
394
264k
    if (not ext) {
395
257k
      ret.code = bref.unpack(ret.val, nof_bits);
396
257k
    } else {
397
6.45k
      ret.code = unpack_norm_small_non_neg_whole_number(ret.val, bref);
398
6.45k
      ret.val += nof_types - nof_exts;
399
6.45k
    }
400
3.59M
  } else {
401
3.59M
    uint32_t nof_bits = (uint32_t)std::ceil(std::log2(nof_types));
402
3.59M
    ret.code          = bref.unpack(ret.val, nof_bits);
403
3.59M
  }
404
3.85M
  if (ret.val >= nof_types) {
405
12.0k
    log_error("The provided enum is not within the range of possible values ({}>={})",
406
12.0k
              (unsigned)ret.val,
407
12.0k
              (unsigned)nof_types);
408
12.0k
    ret.code = OCUDUASN_ERROR_DECODE_FAIL;
409
12.0k
  }
410
3.85M
  return ret;
411
3.86M
}
412
413
/************************
414
     PER encoding
415
************************/
416
417
/**
418
 * X.691 - Section 10.5
419
 * Encoder function for a constrained whole number
420
 * @tparam IntType type of integer (e.g. uint8_t, uint32_t, etc.)
421
 * @param bref bit_ref where to encode integer
422
 * @param n integer current value
423
 * @param lb lower bound
424
 * @param ub upper bound
425
 * @return success or failure
426
 */
427
template <class IntType>
428
OCUDUASN_CODE pack_constrained_whole_number(bit_ref& bref, IntType n, IntType lb, IntType ub, bool aligned)
429
504k
{
430
504k
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
504k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
504k
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
504k
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
504k
  IntType  toencode = n - lb;
440
504k
  if (not aligned) {
441
    // UNALIGNED variant
442
504k
    bref.pack(toencode, n_bits);
443
504k
  } else {
444
    // ALIGNED variant
445
42
    OCUDUASN_CODE ret;
446
42
    if (ra < 256) {
447
8
      ret = bref.pack(toencode, n_bits);
448
34
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
34
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
34
      HANDLE_CODE(bref.align_bytes_zero());
452
34
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
34
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
34
      ret = bref.align_bytes_zero();
455
34
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
42
    return ret;
464
42
  }
465
504k
  return OCUDUASN_SUCCESS;
466
504k
}
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<signed char>(asn1::bit_ref&, signed char, signed char, signed char, bool)
Line
Count
Source
429
8
{
430
8
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
8
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
8
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
8
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
8
  IntType  toencode = n - lb;
440
8
  if (not aligned) {
441
    // UNALIGNED variant
442
8
    bref.pack(toencode, n_bits);
443
8
  } else {
444
    // ALIGNED variant
445
0
    OCUDUASN_CODE ret;
446
0
    if (ra < 256) {
447
0
      ret = bref.pack(toencode, n_bits);
448
0
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
0
      HANDLE_CODE(bref.align_bytes_zero());
452
0
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
0
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
0
      ret = bref.align_bytes_zero();
455
0
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
0
    return ret;
464
0
  }
465
8
  return OCUDUASN_SUCCESS;
466
8
}
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<short>(asn1::bit_ref&, short, short, short, bool)
Line
Count
Source
429
6
{
430
6
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
6
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
6
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
6
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
6
  IntType  toencode = n - lb;
440
6
  if (not aligned) {
441
    // UNALIGNED variant
442
6
    bref.pack(toencode, n_bits);
443
6
  } else {
444
    // ALIGNED variant
445
0
    OCUDUASN_CODE ret;
446
0
    if (ra < 256) {
447
0
      ret = bref.pack(toencode, n_bits);
448
0
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
0
      HANDLE_CODE(bref.align_bytes_zero());
452
0
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
0
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
0
      ret = bref.align_bytes_zero();
455
0
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
0
    return ret;
464
0
  }
465
6
  return OCUDUASN_SUCCESS;
466
6
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<int>(asn1::bit_ref&, int, int, int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<long>(asn1::bit_ref&, long, long, long, bool)
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<unsigned char>(asn1::bit_ref&, unsigned char, unsigned char, unsigned char, bool)
Line
Count
Source
429
212k
{
430
212k
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
212k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
212k
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
212k
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
212k
  IntType  toencode = n - lb;
440
212k
  if (not aligned) {
441
    // UNALIGNED variant
442
212k
    bref.pack(toencode, n_bits);
443
212k
  } else {
444
    // ALIGNED variant
445
0
    OCUDUASN_CODE ret;
446
0
    if (ra < 256) {
447
0
      ret = bref.pack(toencode, n_bits);
448
0
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
0
      HANDLE_CODE(bref.align_bytes_zero());
452
0
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
0
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
0
      ret = bref.align_bytes_zero();
455
0
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
0
    return ret;
464
0
  }
465
212k
  return OCUDUASN_SUCCESS;
466
212k
}
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<unsigned short>(asn1::bit_ref&, unsigned short, unsigned short, unsigned short, bool)
Line
Count
Source
429
120k
{
430
120k
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
120k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
120k
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
120k
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
120k
  IntType  toencode = n - lb;
440
120k
  if (not aligned) {
441
    // UNALIGNED variant
442
120k
    bref.pack(toencode, n_bits);
443
120k
  } else {
444
    // ALIGNED variant
445
6
    OCUDUASN_CODE ret;
446
6
    if (ra < 256) {
447
0
      ret = bref.pack(toencode, n_bits);
448
6
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
6
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
6
      HANDLE_CODE(bref.align_bytes_zero());
452
6
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
6
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
6
      ret = bref.align_bytes_zero();
455
6
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
6
    return ret;
464
6
  }
465
120k
  return OCUDUASN_SUCCESS;
466
120k
}
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<unsigned int>(asn1::bit_ref&, unsigned int, unsigned int, unsigned int, bool)
Line
Count
Source
429
171k
{
430
171k
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
171k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
171k
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
171k
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
171k
  IntType  toencode = n - lb;
440
171k
  if (not aligned) {
441
    // UNALIGNED variant
442
171k
    bref.pack(toencode, n_bits);
443
171k
  } else {
444
    // ALIGNED variant
445
32
    OCUDUASN_CODE ret;
446
32
    if (ra < 256) {
447
4
      ret = bref.pack(toencode, n_bits);
448
28
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
28
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
28
      HANDLE_CODE(bref.align_bytes_zero());
452
28
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
28
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
28
      ret = bref.align_bytes_zero();
455
28
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
32
    return ret;
464
32
  }
465
171k
  return OCUDUASN_SUCCESS;
466
171k
}
asn1::OCUDUASN_CODE asn1::pack_constrained_whole_number<unsigned long>(asn1::bit_ref&, unsigned long, unsigned long, unsigned long, bool)
Line
Count
Source
429
4
{
430
4
  if (ub < lb or n < lb or n > ub) {
431
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
432
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
433
0
  }
434
4
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept
435
4
  if (ra == 1) {
436
0
    return OCUDUASN_SUCCESS;
437
0
  }
438
4
  uint32_t n_bits   = (uint32_t)std::ceil(std::log2((float)ra)); // bit-field size
439
4
  IntType  toencode = n - lb;
440
4
  if (not aligned) {
441
    // UNALIGNED variant
442
0
    bref.pack(toencode, n_bits);
443
4
  } else {
444
    // ALIGNED variant
445
4
    OCUDUASN_CODE ret;
446
4
    if (ra < 256) {
447
4
      ret = bref.pack(toencode, n_bits);
448
4
    } else if (ra <= ASN_64K) {
449
      // both one and two octets cases
450
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
451
0
      HANDLE_CODE(bref.align_bytes_zero());
452
0
      HANDLE_CODE(bref.pack(0, n_octets * 8 - n_bits));
453
0
      HANDLE_CODE(bref.pack(toencode, n_bits));
454
0
      ret = bref.align_bytes_zero();
455
0
    } else {
456
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
457
0
      n_bits              = (uint32_t)std::floor(std::log2(std::max(toencode, (IntType)1)) + 1);
458
0
      uint32_t n_octets   = ceil_frac(n_bits, 8u);
459
0
      HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
460
0
      HANDLE_CODE(bref.align_bytes_zero());
461
0
      ret = bref.pack(toencode, n_octets * 8u);
462
0
    }
463
4
    return ret;
464
4
  }
465
0
  return OCUDUASN_SUCCESS;
466
4
}
467
template OCUDUASN_CODE
468
pack_constrained_whole_number<int8_t>(bit_ref& bref, int8_t n, int8_t lb, int8_t ub, bool aligned);
469
template OCUDUASN_CODE
470
pack_constrained_whole_number<int16_t>(bit_ref& bref, int16_t n, int16_t lb, int16_t ub, bool aligned);
471
template OCUDUASN_CODE
472
pack_constrained_whole_number<int32_t>(bit_ref& bref, int32_t n, int32_t lb, int32_t ub, bool aligned);
473
template OCUDUASN_CODE
474
pack_constrained_whole_number<int64_t>(bit_ref& bref, int64_t n, int64_t lb, int64_t ub, bool aligned);
475
template OCUDUASN_CODE
476
pack_constrained_whole_number<uint8_t>(bit_ref& bref, uint8_t n, uint8_t lb, uint8_t ub, bool aligned);
477
template OCUDUASN_CODE
478
pack_constrained_whole_number<uint16_t>(bit_ref& bref, uint16_t n, uint16_t lb, uint16_t ub, bool aligned);
479
template OCUDUASN_CODE
480
pack_constrained_whole_number<uint32_t>(bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool aligned);
481
template OCUDUASN_CODE
482
pack_constrained_whole_number<uint64_t>(bit_ref& bref, uint64_t n, uint64_t lb, uint64_t ub, bool aligned);
483
484
/**
485
 * X.691 - Section 10.5
486
 * Decoder function for a constrained whole number
487
 * @tparam IntType type of integer (e.g. uint8_t, uint32_t, etc.)
488
 * @param n integer with decoded value
489
 * @param bref bit_ref where to encode integer
490
 * @param lb lower bound
491
 * @param ub upper bound
492
 * @return success or failure
493
 */
494
template <class IntType>
495
OCUDUASN_CODE unpack_constrained_whole_number(IntType& n, cbit_ref& bref, IntType lb, IntType ub, bool aligned)
496
7.85M
{
497
7.85M
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
7.85M
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
7.85M
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
7.85M
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
7.85M
  if (not aligned) {
508
    // UNALIGNED variant
509
7.20M
    HANDLE_CODE(bref.unpack(n, n_bits));
510
7.20M
    n += lb;
511
7.20M
  } else {
512
    // ALIGNED variant
513
653k
    if (ra < 256) {
514
59.9k
      HANDLE_CODE(bref.unpack(n, n_bits));
515
593k
    } else if (ra <= ASN_64K) {
516
552k
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
552k
      HANDLE_CODE(bref.align_bytes());
518
552k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
498k
      HANDLE_CODE(bref.align_bytes());
520
498k
    } else {
521
40.4k
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
40.4k
      uint32_t n_octets;
523
40.4k
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
38.2k
      n_octets += 1;
525
38.2k
      HANDLE_CODE(bref.align_bytes());
526
38.2k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
38.2k
    }
528
593k
    n += lb;
529
593k
  }
530
531
7.79M
  if (n > ub) {
532
2.06k
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
2.06k
    return OCUDUASN_ERROR_DECODE_FAIL;
534
2.06k
  }
535
536
7.79M
  return OCUDUASN_SUCCESS;
537
7.79M
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<signed char>(signed char&, asn1::cbit_ref&, signed char, signed char, bool)
Line
Count
Source
496
50.9k
{
497
50.9k
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
50.9k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
50.9k
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
50.9k
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
50.9k
  if (not aligned) {
508
    // UNALIGNED variant
509
50.9k
    HANDLE_CODE(bref.unpack(n, n_bits));
510
50.9k
    n += lb;
511
50.9k
  } else {
512
    // ALIGNED variant
513
0
    if (ra < 256) {
514
0
      HANDLE_CODE(bref.unpack(n, n_bits));
515
0
    } else if (ra <= ASN_64K) {
516
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
0
      HANDLE_CODE(bref.align_bytes());
518
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
0
      HANDLE_CODE(bref.align_bytes());
520
0
    } else {
521
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
0
      uint32_t n_octets;
523
0
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
0
      n_octets += 1;
525
0
      HANDLE_CODE(bref.align_bytes());
526
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
0
    }
528
0
    n += lb;
529
0
  }
530
531
50.9k
  if (n > ub) {
532
7
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
7
    return OCUDUASN_ERROR_DECODE_FAIL;
534
7
  }
535
536
50.9k
  return OCUDUASN_SUCCESS;
537
50.9k
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<short>(short&, asn1::cbit_ref&, short, short, bool)
Line
Count
Source
496
53.5k
{
497
53.5k
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
53.5k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
53.5k
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
53.5k
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
53.5k
  if (not aligned) {
508
    // UNALIGNED variant
509
53.5k
    HANDLE_CODE(bref.unpack(n, n_bits));
510
53.5k
    n += lb;
511
53.5k
  } else {
512
    // ALIGNED variant
513
0
    if (ra < 256) {
514
0
      HANDLE_CODE(bref.unpack(n, n_bits));
515
0
    } else if (ra <= ASN_64K) {
516
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
0
      HANDLE_CODE(bref.align_bytes());
518
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
0
      HANDLE_CODE(bref.align_bytes());
520
0
    } else {
521
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
0
      uint32_t n_octets;
523
0
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
0
      n_octets += 1;
525
0
      HANDLE_CODE(bref.align_bytes());
526
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
0
    }
528
0
    n += lb;
529
0
  }
530
531
53.5k
  if (n > ub) {
532
19
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
19
    return OCUDUASN_ERROR_DECODE_FAIL;
534
19
  }
535
536
53.4k
  return OCUDUASN_SUCCESS;
537
53.5k
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<int>(int&, asn1::cbit_ref&, int, int, bool)
Line
Count
Source
496
102
{
497
102
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
102
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
102
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
102
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
102
  if (not aligned) {
508
    // UNALIGNED variant
509
102
    HANDLE_CODE(bref.unpack(n, n_bits));
510
102
    n += lb;
511
102
  } else {
512
    // ALIGNED variant
513
0
    if (ra < 256) {
514
0
      HANDLE_CODE(bref.unpack(n, n_bits));
515
0
    } else if (ra <= ASN_64K) {
516
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
0
      HANDLE_CODE(bref.align_bytes());
518
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
0
      HANDLE_CODE(bref.align_bytes());
520
0
    } else {
521
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
0
      uint32_t n_octets;
523
0
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
0
      n_octets += 1;
525
0
      HANDLE_CODE(bref.align_bytes());
526
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
0
    }
528
0
    n += lb;
529
0
  }
530
531
102
  if (n > ub) {
532
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
0
    return OCUDUASN_ERROR_DECODE_FAIL;
534
0
  }
535
536
102
  return OCUDUASN_SUCCESS;
537
102
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<long>(long&, asn1::cbit_ref&, long, long, bool)
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<unsigned char>(unsigned char&, asn1::cbit_ref&, unsigned char, unsigned char, bool)
Line
Count
Source
496
2.25M
{
497
2.25M
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
2.25M
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
2.25M
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
2.25M
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
2.25M
  if (not aligned) {
508
    // UNALIGNED variant
509
2.23M
    HANDLE_CODE(bref.unpack(n, n_bits));
510
2.23M
    n += lb;
511
2.23M
  } else {
512
    // ALIGNED variant
513
14.6k
    if (ra < 256) {
514
14.6k
      HANDLE_CODE(bref.unpack(n, n_bits));
515
14.6k
    } else if (ra <= ASN_64K) {
516
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
0
      HANDLE_CODE(bref.align_bytes());
518
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
0
      HANDLE_CODE(bref.align_bytes());
520
0
    } else {
521
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
0
      uint32_t n_octets;
523
0
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
0
      n_octets += 1;
525
0
      HANDLE_CODE(bref.align_bytes());
526
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
0
    }
528
14.5k
    n += lb;
529
14.5k
  }
530
531
2.25M
  if (n > ub) {
532
238
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
238
    return OCUDUASN_ERROR_DECODE_FAIL;
534
238
  }
535
536
2.25M
  return OCUDUASN_SUCCESS;
537
2.25M
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<unsigned short>(unsigned short&, asn1::cbit_ref&, unsigned short, unsigned short, bool)
Line
Count
Source
496
3.82M
{
497
3.82M
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
3.82M
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
3.82M
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
3.82M
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
3.82M
  if (not aligned) {
508
    // UNALIGNED variant
509
3.63M
    HANDLE_CODE(bref.unpack(n, n_bits));
510
3.63M
    n += lb;
511
3.63M
  } else {
512
    // ALIGNED variant
513
185k
    if (ra < 256) {
514
0
      HANDLE_CODE(bref.unpack(n, n_bits));
515
185k
    } else if (ra <= ASN_64K) {
516
185k
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
185k
      HANDLE_CODE(bref.align_bytes());
518
185k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
180k
      HANDLE_CODE(bref.align_bytes());
520
180k
    } else {
521
0
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
0
      uint32_t n_octets;
523
0
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
0
      n_octets += 1;
525
0
      HANDLE_CODE(bref.align_bytes());
526
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
0
    }
528
180k
    n += lb;
529
180k
  }
530
531
3.81M
  if (n > ub) {
532
289
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
289
    return OCUDUASN_ERROR_DECODE_FAIL;
534
289
  }
535
536
3.81M
  return OCUDUASN_SUCCESS;
537
3.81M
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<unsigned int>(unsigned int&, asn1::cbit_ref&, unsigned int, unsigned int, bool)
Line
Count
Source
496
1.63M
{
497
1.63M
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
1.63M
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
1.63M
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
1.63M
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
1.63M
  if (not aligned) {
508
    // UNALIGNED variant
509
1.22M
    HANDLE_CODE(bref.unpack(n, n_bits));
510
1.22M
    n += lb;
511
1.22M
  } else {
512
    // ALIGNED variant
513
413k
    if (ra < 256) {
514
42.9k
      HANDLE_CODE(bref.unpack(n, n_bits));
515
370k
    } else if (ra <= ASN_64K) {
516
367k
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
367k
      HANDLE_CODE(bref.align_bytes());
518
367k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
317k
      HANDLE_CODE(bref.align_bytes());
520
317k
    } else {
521
3.74k
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
3.74k
      uint32_t n_octets;
523
3.74k
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
3.70k
      n_octets += 1;
525
3.70k
      HANDLE_CODE(bref.align_bytes());
526
3.70k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
3.70k
    }
528
362k
    n += lb;
529
362k
  }
530
531
1.58M
  if (n > ub) {
532
1.13k
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
1.13k
    return OCUDUASN_ERROR_DECODE_FAIL;
534
1.13k
  }
535
536
1.58M
  return OCUDUASN_SUCCESS;
537
1.58M
}
asn1::OCUDUASN_CODE asn1::unpack_constrained_whole_number<unsigned long>(unsigned long&, asn1::cbit_ref&, unsigned long, unsigned long, bool)
Line
Count
Source
496
40.0k
{
497
40.0k
  if (ub < lb) {
498
0
    log_error("The condition lb <= ub ({} <= {}) was not met", (long)lb, (long)ub);
499
0
    return OCUDUASN_ERROR_DECODE_FAIL;
500
0
  }
501
40.0k
  uint64_t ra = (uint64_t)(ub - lb) + 1; // NOTE: Can overflow if IntType is kept.
502
40.0k
  if (ra == 1) {
503
0
    n = lb;
504
0
    return OCUDUASN_SUCCESS;
505
0
  }
506
40.0k
  uint32_t n_bits = (uint32_t)std::ceil(std::log2((float)ra));
507
40.0k
  if (not aligned) {
508
    // UNALIGNED variant
509
978
    HANDLE_CODE(bref.unpack(n, n_bits));
510
932
    n += lb;
511
39.0k
  } else {
512
    // ALIGNED variant
513
39.0k
    if (ra < 256) {
514
2.31k
      HANDLE_CODE(bref.unpack(n, n_bits));
515
36.7k
    } else if (ra <= ASN_64K) {
516
0
      uint32_t n_octets = ceil_frac(n_bits, 8u);
517
0
      HANDLE_CODE(bref.align_bytes());
518
0
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
519
0
      HANDLE_CODE(bref.align_bytes());
520
36.7k
    } else {
521
36.7k
      uint32_t n_bits_len = (uint32_t)std::ceil(std::log2(ceil_frac(n_bits, 8u)));
522
36.7k
      uint32_t n_octets;
523
36.7k
      HANDLE_CODE(bref.unpack(n_octets, n_bits_len));
524
34.5k
      n_octets += 1;
525
34.5k
      HANDLE_CODE(bref.align_bytes());
526
34.5k
      HANDLE_CODE(bref.unpack(n, n_octets * 8));
527
34.5k
    }
528
35.6k
    n += lb;
529
35.6k
  }
530
531
36.6k
  if (n > ub) {
532
374
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met\n", lb, n, ub);
533
374
    return OCUDUASN_ERROR_DECODE_FAIL;
534
374
  }
535
536
36.2k
  return OCUDUASN_SUCCESS;
537
36.6k
}
538
template OCUDUASN_CODE
539
unpack_constrained_whole_number<int8_t>(int8_t& n, cbit_ref& bref, int8_t lb, int8_t ub, bool aligned);
540
template OCUDUASN_CODE
541
unpack_constrained_whole_number<int16_t>(int16_t& n, cbit_ref& bref, int16_t lb, int16_t ub, bool aligned);
542
template OCUDUASN_CODE
543
unpack_constrained_whole_number<int32_t>(int32_t& n, cbit_ref& bref, int32_t lb, int32_t ub, bool aligned);
544
template OCUDUASN_CODE
545
unpack_constrained_whole_number<int64_t>(int64_t& n, cbit_ref& bref, int64_t lb, int64_t ub, bool aligned);
546
template OCUDUASN_CODE
547
unpack_constrained_whole_number<uint8_t>(uint8_t& n, cbit_ref& bref, uint8_t lb, uint8_t ub, bool aligned);
548
template OCUDUASN_CODE
549
unpack_constrained_whole_number<uint16_t>(uint16_t& n, cbit_ref& bref, uint16_t lb, uint16_t ub, bool aligned);
550
template OCUDUASN_CODE
551
unpack_constrained_whole_number<uint32_t>(uint32_t& n, cbit_ref& bref, uint32_t lb, uint32_t ub, bool aligned);
552
template OCUDUASN_CODE
553
unpack_constrained_whole_number<uint64_t>(uint64_t& n, cbit_ref& bref, uint64_t lb, uint64_t ub, bool aligned);
554
555
/**
556
 * X.691 - Section 10.6
557
 * Encoder function for a normally small non-negative whole number
558
 * @tparam IntType type of integer (e.g. uint8_t, uint32_t, etc.)
559
 * @param bref bit_ref where to encode integer
560
 * @param n integer current value
561
 * @return success or failure
562
 */
563
template <typename UintType>
564
OCUDUASN_CODE pack_norm_small_non_neg_whole_number(bit_ref& bref, UintType n)
565
40
{
566
40
  if (n <= 63) {
567
40
    HANDLE_CODE(bref.pack(n, 7)); // [1 bit: 0 | 6 bit: n]
568
40
  } else {
569
0
    HANDLE_CODE(bref.pack(1, 1));
570
0
    log_error("Long small integers not supported");
571
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
572
0
  }
573
40
  return OCUDUASN_SUCCESS;
574
40
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_norm_small_non_neg_whole_number<unsigned char>(asn1::bit_ref&, unsigned char)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_norm_small_non_neg_whole_number<unsigned short>(asn1::bit_ref&, unsigned short)
asn1::OCUDUASN_CODE asn1::pack_norm_small_non_neg_whole_number<unsigned int>(asn1::bit_ref&, unsigned int)
Line
Count
Source
565
40
{
566
40
  if (n <= 63) {
567
40
    HANDLE_CODE(bref.pack(n, 7)); // [1 bit: 0 | 6 bit: n]
568
40
  } else {
569
0
    HANDLE_CODE(bref.pack(1, 1));
570
0
    log_error("Long small integers not supported");
571
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
572
0
  }
573
40
  return OCUDUASN_SUCCESS;
574
40
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_norm_small_non_neg_whole_number<unsigned long>(asn1::bit_ref&, unsigned long)
575
template <typename UintType>
576
OCUDUASN_CODE unpack_norm_small_non_neg_whole_number(UintType& n, cbit_ref& bref)
577
47.9k
{
578
47.9k
  bool          ext;
579
47.9k
  OCUDUASN_CODE ret = bref.unpack(ext, 1);
580
47.9k
  HANDLE_CODE(ret);
581
47.8k
  if (not ext) {
582
45.5k
    ret = bref.unpack(n, 6);
583
45.5k
  } else {
584
2.26k
    log_error("Long small integers not supported");
585
2.26k
    return OCUDUASN_ERROR_DECODE_FAIL;
586
2.26k
  }
587
45.5k
  return ret;
588
47.8k
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_norm_small_non_neg_whole_number<unsigned char>(unsigned char&, asn1::cbit_ref&)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_norm_small_non_neg_whole_number<unsigned short>(unsigned short&, asn1::cbit_ref&)
asn1::OCUDUASN_CODE asn1::unpack_norm_small_non_neg_whole_number<unsigned int>(unsigned int&, asn1::cbit_ref&)
Line
Count
Source
577
47.9k
{
578
47.9k
  bool          ext;
579
47.9k
  OCUDUASN_CODE ret = bref.unpack(ext, 1);
580
47.9k
  HANDLE_CODE(ret);
581
47.8k
  if (not ext) {
582
45.5k
    ret = bref.unpack(n, 6);
583
45.5k
  } else {
584
2.26k
    log_error("Long small integers not supported");
585
2.26k
    return OCUDUASN_ERROR_DECODE_FAIL;
586
2.26k
  }
587
45.5k
  return ret;
588
47.8k
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_norm_small_non_neg_whole_number<unsigned long>(unsigned long&, asn1::cbit_ref&)
589
template OCUDUASN_CODE pack_norm_small_non_neg_whole_number<uint8_t>(bit_ref& bref, uint8_t n);
590
template OCUDUASN_CODE pack_norm_small_non_neg_whole_number<uint16_t>(bit_ref& bref, uint16_t n);
591
template OCUDUASN_CODE pack_norm_small_non_neg_whole_number<uint32_t>(bit_ref& bref, uint32_t n);
592
template OCUDUASN_CODE pack_norm_small_non_neg_whole_number<uint64_t>(bit_ref& bref, uint64_t n);
593
template OCUDUASN_CODE unpack_norm_small_non_neg_whole_number<uint8_t>(uint8_t& n, cbit_ref& bref);
594
template OCUDUASN_CODE unpack_norm_small_non_neg_whole_number<uint16_t>(uint16_t& n, cbit_ref& bref);
595
template OCUDUASN_CODE unpack_norm_small_non_neg_whole_number<uint32_t>(uint32_t& n, cbit_ref& bref);
596
template OCUDUASN_CODE unpack_norm_small_non_neg_whole_number<uint64_t>(uint64_t& n, cbit_ref& bref);
597
598
/// Number of octets of the minimal two's-complement encoding of an unconstrained whole number (X.691 - Section 10.8,
599
/// X.690 - Section 8.3). A non-negative value needs a leading zero bit, so e.g. 128 takes two octets, not one.
600
template <typename IntType>
601
uint32_t unconstrained_whole_number_length(IntType n)
602
0
{
603
0
  uint32_t len = 1;
604
0
  if constexpr (std::is_signed<IntType>::value) {
605
0
    auto val = static_cast<int64_t>(n);
606
0
    while (val > 127 or val < -128) {
607
0
      val >>= 8;
608
0
      ++len;
609
0
    }
610
0
  } else {
611
0
    auto val = static_cast<uint64_t>(n);
612
0
    while (val > 127) {
613
0
      val >>= 8;
614
0
      ++len;
615
0
    }
616
0
  }
617
0
  return len;
618
0
}
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<signed char>(signed char)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<short>(short)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<int>(int)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<long>(long)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<unsigned char>(unsigned char)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<unsigned short>(unsigned short)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<unsigned int>(unsigned int)
Unexecuted instantiation: unsigned int asn1::unconstrained_whole_number_length<unsigned long>(unsigned long)
619
620
/**
621
 * X.691 - Section 10.8
622
 * Encoder function for an unconstrained whole number
623
 * @tparam IntType type of integer (e.g. int8_t, uint32_t, etc.)
624
 * @param bref bit_ref where to encode integer
625
 * @param n integer current value
626
 * @return success or failure
627
 */
628
template <typename IntType>
629
OCUDUASN_CODE pack_unconstrained_whole_number(bit_ref& bref, IntType n, bool aligned)
630
0
{
631
0
  uint32_t len = unconstrained_whole_number_length(n);
632
0
  if (aligned) {
633
0
    HANDLE_CODE(bref.align_bytes_zero());
634
0
  }
635
  // Two's-complement content octets, most significant first. The conversion to uint64_t yields the 64-bit two's-
636
  // complement pattern of the value, so shifting out the low octets works for both signed and unsigned types.
637
0
  auto bits = static_cast<uint64_t>(n);
638
0
  for (uint32_t i = len; i != 0; --i) {
639
0
    uint32_t shift = 8U * (i - 1);
640
    // A non-negative value wider than 63 bits needs a 9th octet, which is the leading zero octet.
641
0
    uint64_t octet = shift < 64U ? (bits >> shift) & 0xffU : 0U;
642
0
    HANDLE_CODE(bref.pack(octet, 8));
643
0
  }
644
645
0
  return OCUDUASN_SUCCESS;
646
0
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<signed char>(asn1::bit_ref&, signed char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<short>(asn1::bit_ref&, short, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<int>(asn1::bit_ref&, int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<long>(asn1::bit_ref&, long, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<unsigned char>(asn1::bit_ref&, unsigned char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<unsigned short>(asn1::bit_ref&, unsigned short, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<unsigned int>(asn1::bit_ref&, unsigned int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_whole_number<unsigned long>(asn1::bit_ref&, unsigned long, bool)
647
template <typename IntType>
648
OCUDUASN_CODE unpack_unconstrained_whole_number(IntType& n, cbit_ref& bref, uint32_t len, bool aligned)
649
2.35k
{
650
2.35k
  if (aligned) {
651
2.35k
    HANDLE_CODE(bref.align_bytes());
652
2.35k
  }
653
2.35k
  if (len == 0) {
654
171
    log_error("Unconstrained whole number with no content octets");
655
171
    return OCUDUASN_ERROR_DECODE_FAIL;
656
171
  }
657
2.17k
  uint64_t bits     = 0;
658
2.17k
  bool     negative = false;
659
2.17k
  bool     fits     = true;
660
19.0k
  for (uint32_t i = 0; i != len; ++i) {
661
17.5k
    uint8_t octet = 0;
662
17.5k
    HANDLE_CODE(bref.unpack(octet, 8));
663
16.8k
    if (i == 0) {
664
      // The encoding is negative if the top bit of the first content octet is set.
665
2.08k
      negative = (octet & 0x80U) != 0;
666
2.08k
      fits     = not negative or std::is_signed<IntType>::value;
667
2.08k
    }
668
16.8k
    if (len - i > sizeof(uint64_t)) {
669
      // Leading octet that is dropped. It only carries sign extension if it repeats the sign bit.
670
10.5k
      fits = fits and octet == (negative ? 0xffU : 0x00U);
671
10.5k
      continue;
672
10.5k
    }
673
6.27k
    bits = (bits << 8U) | octet;
674
6.27k
  }
675
1.47k
  if (negative and len < sizeof(uint64_t)) {
676
    // Sign extension of the two's-complement encoding.
677
54
    bits |= ~static_cast<uint64_t>(0) << (8U * len);
678
1.41k
  } else if (std::is_signed<IntType>::value and len >= sizeof(uint64_t)) {
679
    // Octets were dropped from the front, so the retained bits must carry the sign of the encoding themselves.
680
0
    fits = fits and ((bits >> 63U) != 0) == negative;
681
0
  }
682
1.47k
  n = static_cast<IntType>(bits);
683
1.47k
  if (not fits or static_cast<uint64_t>(n) != bits) {
684
541
    log_error("Unconstrained whole number of {} octets does not fit in the destination type", len);
685
541
    return OCUDUASN_ERROR_DECODE_FAIL;
686
541
  }
687
688
931
  return OCUDUASN_SUCCESS;
689
1.47k
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<signed char>(signed char&, asn1::cbit_ref&, unsigned int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<short>(short&, asn1::cbit_ref&, unsigned int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<int>(int&, asn1::cbit_ref&, unsigned int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<long>(long&, asn1::cbit_ref&, unsigned int, bool)
asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<unsigned char>(unsigned char&, asn1::cbit_ref&, unsigned int, bool)
Line
Count
Source
649
787
{
650
787
  if (aligned) {
651
787
    HANDLE_CODE(bref.align_bytes());
652
787
  }
653
787
  if (len == 0) {
654
58
    log_error("Unconstrained whole number with no content octets");
655
58
    return OCUDUASN_ERROR_DECODE_FAIL;
656
58
  }
657
729
  uint64_t bits     = 0;
658
729
  bool     negative = false;
659
729
  bool     fits     = true;
660
5.42k
  for (uint32_t i = 0; i != len; ++i) {
661
4.94k
    uint8_t octet = 0;
662
4.94k
    HANDLE_CODE(bref.unpack(octet, 8));
663
4.69k
    if (i == 0) {
664
      // The encoding is negative if the top bit of the first content octet is set.
665
700
      negative = (octet & 0x80U) != 0;
666
700
      fits     = not negative or std::is_signed<IntType>::value;
667
700
    }
668
4.69k
    if (len - i > sizeof(uint64_t)) {
669
      // Leading octet that is dropped. It only carries sign extension if it repeats the sign bit.
670
2.73k
      fits = fits and octet == (negative ? 0xffU : 0x00U);
671
2.73k
      continue;
672
2.73k
    }
673
1.96k
    bits = (bits << 8U) | octet;
674
1.96k
  }
675
477
  if (negative and len < sizeof(uint64_t)) {
676
    // Sign extension of the two's-complement encoding.
677
14
    bits |= ~static_cast<uint64_t>(0) << (8U * len);
678
463
  } else if (std::is_signed<IntType>::value and len >= sizeof(uint64_t)) {
679
    // Octets were dropped from the front, so the retained bits must carry the sign of the encoding themselves.
680
0
    fits = fits and ((bits >> 63U) != 0) == negative;
681
0
  }
682
477
  n = static_cast<IntType>(bits);
683
477
  if (not fits or static_cast<uint64_t>(n) != bits) {
684
199
    log_error("Unconstrained whole number of {} octets does not fit in the destination type", len);
685
199
    return OCUDUASN_ERROR_DECODE_FAIL;
686
199
  }
687
688
278
  return OCUDUASN_SUCCESS;
689
477
}
asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<unsigned short>(unsigned short&, asn1::cbit_ref&, unsigned int, bool)
Line
Count
Source
649
609
{
650
609
  if (aligned) {
651
609
    HANDLE_CODE(bref.align_bytes());
652
609
  }
653
609
  if (len == 0) {
654
59
    log_error("Unconstrained whole number with no content octets");
655
59
    return OCUDUASN_ERROR_DECODE_FAIL;
656
59
  }
657
550
  uint64_t bits     = 0;
658
550
  bool     negative = false;
659
550
  bool     fits     = true;
660
4.45k
  for (uint32_t i = 0; i != len; ++i) {
661
4.08k
    uint8_t octet = 0;
662
4.08k
    HANDLE_CODE(bref.unpack(octet, 8));
663
3.90k
    if (i == 0) {
664
      // The encoding is negative if the top bit of the first content octet is set.
665
514
      negative = (octet & 0x80U) != 0;
666
514
      fits     = not negative or std::is_signed<IntType>::value;
667
514
    }
668
3.90k
    if (len - i > sizeof(uint64_t)) {
669
      // Leading octet that is dropped. It only carries sign extension if it repeats the sign bit.
670
2.24k
      fits = fits and octet == (negative ? 0xffU : 0x00U);
671
2.24k
      continue;
672
2.24k
    }
673
1.65k
    bits = (bits << 8U) | octet;
674
1.65k
  }
675
370
  if (negative and len < sizeof(uint64_t)) {
676
    // Sign extension of the two's-complement encoding.
677
12
    bits |= ~static_cast<uint64_t>(0) << (8U * len);
678
358
  } else if (std::is_signed<IntType>::value and len >= sizeof(uint64_t)) {
679
    // Octets were dropped from the front, so the retained bits must carry the sign of the encoding themselves.
680
0
    fits = fits and ((bits >> 63U) != 0) == negative;
681
0
  }
682
370
  n = static_cast<IntType>(bits);
683
370
  if (not fits or static_cast<uint64_t>(n) != bits) {
684
194
    log_error("Unconstrained whole number of {} octets does not fit in the destination type", len);
685
194
    return OCUDUASN_ERROR_DECODE_FAIL;
686
194
  }
687
688
176
  return OCUDUASN_SUCCESS;
689
370
}
asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<unsigned int>(unsigned int&, asn1::cbit_ref&, unsigned int, bool)
Line
Count
Source
649
496
{
650
496
  if (aligned) {
651
496
    HANDLE_CODE(bref.align_bytes());
652
496
  }
653
496
  if (len == 0) {
654
23
    log_error("Unconstrained whole number with no content octets");
655
23
    return OCUDUASN_ERROR_DECODE_FAIL;
656
23
  }
657
473
  uint64_t bits     = 0;
658
473
  bool     negative = false;
659
473
  bool     fits     = true;
660
5.83k
  for (uint32_t i = 0; i != len; ++i) {
661
5.47k
    uint8_t octet = 0;
662
5.47k
    HANDLE_CODE(bref.unpack(octet, 8));
663
5.36k
    if (i == 0) {
664
      // The encoding is negative if the top bit of the first content octet is set.
665
464
      negative = (octet & 0x80U) != 0;
666
464
      fits     = not negative or std::is_signed<IntType>::value;
667
464
    }
668
5.36k
    if (len - i > sizeof(uint64_t)) {
669
      // Leading octet that is dropped. It only carries sign extension if it repeats the sign bit.
670
3.64k
      fits = fits and octet == (negative ? 0xffU : 0x00U);
671
3.64k
      continue;
672
3.64k
    }
673
1.72k
    bits = (bits << 8U) | octet;
674
1.72k
  }
675
366
  if (negative and len < sizeof(uint64_t)) {
676
    // Sign extension of the two's-complement encoding.
677
13
    bits |= ~static_cast<uint64_t>(0) << (8U * len);
678
353
  } else if (std::is_signed<IntType>::value and len >= sizeof(uint64_t)) {
679
    // Octets were dropped from the front, so the retained bits must carry the sign of the encoding themselves.
680
0
    fits = fits and ((bits >> 63U) != 0) == negative;
681
0
  }
682
366
  n = static_cast<IntType>(bits);
683
366
  if (not fits or static_cast<uint64_t>(n) != bits) {
684
114
    log_error("Unconstrained whole number of {} octets does not fit in the destination type", len);
685
114
    return OCUDUASN_ERROR_DECODE_FAIL;
686
114
  }
687
688
252
  return OCUDUASN_SUCCESS;
689
366
}
asn1::OCUDUASN_CODE asn1::unpack_unconstrained_whole_number<unsigned long>(unsigned long&, asn1::cbit_ref&, unsigned int, bool)
Line
Count
Source
649
458
{
650
458
  if (aligned) {
651
458
    HANDLE_CODE(bref.align_bytes());
652
458
  }
653
458
  if (len == 0) {
654
31
    log_error("Unconstrained whole number with no content octets");
655
31
    return OCUDUASN_ERROR_DECODE_FAIL;
656
31
  }
657
427
  uint64_t bits     = 0;
658
427
  bool     negative = false;
659
427
  bool     fits     = true;
660
3.32k
  for (uint32_t i = 0; i != len; ++i) {
661
3.07k
    uint8_t octet = 0;
662
3.07k
    HANDLE_CODE(bref.unpack(octet, 8));
663
2.90k
    if (i == 0) {
664
      // The encoding is negative if the top bit of the first content octet is set.
665
410
      negative = (octet & 0x80U) != 0;
666
410
      fits     = not negative or std::is_signed<IntType>::value;
667
410
    }
668
2.90k
    if (len - i > sizeof(uint64_t)) {
669
      // Leading octet that is dropped. It only carries sign extension if it repeats the sign bit.
670
1.96k
      fits = fits and octet == (negative ? 0xffU : 0x00U);
671
1.96k
      continue;
672
1.96k
    }
673
937
    bits = (bits << 8U) | octet;
674
937
  }
675
259
  if (negative and len < sizeof(uint64_t)) {
676
    // Sign extension of the two's-complement encoding.
677
15
    bits |= ~static_cast<uint64_t>(0) << (8U * len);
678
244
  } else if (std::is_signed<IntType>::value and len >= sizeof(uint64_t)) {
679
    // Octets were dropped from the front, so the retained bits must carry the sign of the encoding themselves.
680
0
    fits = fits and ((bits >> 63U) != 0) == negative;
681
0
  }
682
259
  n = static_cast<IntType>(bits);
683
259
  if (not fits or static_cast<uint64_t>(n) != bits) {
684
34
    log_error("Unconstrained whole number of {} octets does not fit in the destination type", len);
685
34
    return OCUDUASN_ERROR_DECODE_FAIL;
686
34
  }
687
688
225
  return OCUDUASN_SUCCESS;
689
259
}
690
template OCUDUASN_CODE pack_unconstrained_whole_number<int8_t>(bit_ref& bref, int8_t n, bool aligned);
691
template OCUDUASN_CODE pack_unconstrained_whole_number<int16_t>(bit_ref& bref, int16_t n, bool aligned);
692
template OCUDUASN_CODE pack_unconstrained_whole_number<int32_t>(bit_ref& bref, int32_t n, bool aligned);
693
template OCUDUASN_CODE pack_unconstrained_whole_number<int64_t>(bit_ref& bref, int64_t n, bool aligned);
694
template OCUDUASN_CODE unpack_unconstrained_whole_number<int8_t>(int8_t& n, cbit_ref& bref, uint32_t len, bool aligned);
695
template OCUDUASN_CODE
696
unpack_unconstrained_whole_number<int16_t>(int16_t& n, cbit_ref& bref, uint32_t len, bool aligned);
697
template OCUDUASN_CODE
698
unpack_unconstrained_whole_number<int32_t>(int32_t& n, cbit_ref& bref, uint32_t len, bool aligned);
699
template OCUDUASN_CODE
700
unpack_unconstrained_whole_number<int64_t>(int64_t& n, cbit_ref& bref, uint32_t len, bool aligned);
701
template OCUDUASN_CODE pack_unconstrained_whole_number<uint8_t>(bit_ref& bref, uint8_t n, bool aligned);
702
template OCUDUASN_CODE pack_unconstrained_whole_number<uint16_t>(bit_ref& bref, uint16_t n, bool aligned);
703
template OCUDUASN_CODE pack_unconstrained_whole_number<uint32_t>(bit_ref& bref, uint32_t n, bool aligned);
704
template OCUDUASN_CODE pack_unconstrained_whole_number<uint64_t>(bit_ref& bref, uint64_t n, bool aligned);
705
template OCUDUASN_CODE
706
unpack_unconstrained_whole_number<uint8_t>(uint8_t& n, cbit_ref& bref, uint32_t len, bool aligned);
707
template OCUDUASN_CODE
708
unpack_unconstrained_whole_number<uint16_t>(uint16_t& n, cbit_ref& bref, uint32_t len, bool aligned);
709
template OCUDUASN_CODE
710
unpack_unconstrained_whole_number<uint32_t>(uint32_t& n, cbit_ref& bref, uint32_t len, bool aligned);
711
template OCUDUASN_CODE
712
unpack_unconstrained_whole_number<uint64_t>(uint64_t& n, cbit_ref& bref, uint32_t len, bool aligned);
713
714
/*********************
715
   varlength_packing
716
*********************/
717
718
template <typename IntType>
719
OCUDUASN_CODE pack_length(bit_ref& bref, IntType n, IntType lb, IntType ub, bool aligned)
720
176k
{
721
176k
  if (ub >= ASN_64K) {
722
6.02k
    return pack_length(bref, n, aligned);
723
6.02k
  }
724
170k
  return pack_constrained_whole_number(bref, n, lb, ub, aligned);
725
176k
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<unsigned char>(asn1::bit_ref&, unsigned char, unsigned char, unsigned char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<unsigned short>(asn1::bit_ref&, unsigned short, unsigned short, unsigned short, bool)
asn1::OCUDUASN_CODE asn1::pack_length<unsigned int>(asn1::bit_ref&, unsigned int, unsigned int, unsigned int, bool)
Line
Count
Source
720
176k
{
721
176k
  if (ub >= ASN_64K) {
722
6.02k
    return pack_length(bref, n, aligned);
723
6.02k
  }
724
170k
  return pack_constrained_whole_number(bref, n, lb, ub, aligned);
725
176k
}
asn1::OCUDUASN_CODE asn1::pack_length<unsigned long>(asn1::bit_ref&, unsigned long, unsigned long, unsigned long, bool)
Line
Count
Source
720
4
{
721
4
  if (ub >= ASN_64K) {
722
0
    return pack_length(bref, n, aligned);
723
0
  }
724
4
  return pack_constrained_whole_number(bref, n, lb, ub, aligned);
725
4
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<signed char>(asn1::bit_ref&, signed char, signed char, signed char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<short>(asn1::bit_ref&, short, short, short, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<int>(asn1::bit_ref&, int, int, int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_length<long>(asn1::bit_ref&, long, long, long, bool)
726
template OCUDUASN_CODE pack_length<uint8_t>(bit_ref& bref, uint8_t n, uint8_t lb, uint8_t ub, bool aligned);
727
template OCUDUASN_CODE pack_length<uint16_t>(bit_ref& bref, uint16_t n, uint16_t lb, uint16_t ub, bool aligned);
728
template OCUDUASN_CODE pack_length<uint32_t>(bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool aligned);
729
template OCUDUASN_CODE pack_length<uint64_t>(bit_ref& bref, uint64_t n, uint64_t lb, uint64_t ub, bool aligned);
730
template OCUDUASN_CODE pack_length<int8_t>(bit_ref& bref, int8_t n, int8_t lb, int8_t ub, bool aligned);
731
template OCUDUASN_CODE pack_length<int16_t>(bit_ref& bref, int16_t n, int16_t lb, int16_t ub, bool aligned);
732
template OCUDUASN_CODE pack_length<int32_t>(bit_ref& bref, int32_t n, int32_t lb, int32_t ub, bool aligned);
733
template OCUDUASN_CODE pack_length<int64_t>(bit_ref& bref, int64_t n, int64_t lb, int64_t ub, bool aligned);
734
735
template <typename IntType>
736
OCUDUASN_CODE unpack_length(IntType& n, cbit_ref& bref, IntType lb, IntType ub, bool aligned)
737
1.05M
{
738
1.05M
  if (ub >= ASN_64K) {
739
7.05k
    uint32_t      len;
740
7.05k
    OCUDUASN_CODE ret = unpack_length(len, bref, aligned);
741
7.05k
    n                 = len;
742
7.05k
    return ret;
743
7.05k
  }
744
1.04M
  return unpack_constrained_whole_number(n, bref, lb, ub, aligned);
745
1.05M
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<unsigned char>(unsigned char&, asn1::cbit_ref&, unsigned char, unsigned char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<unsigned short>(unsigned short&, asn1::cbit_ref&, unsigned short, unsigned short, bool)
asn1::OCUDUASN_CODE asn1::unpack_length<unsigned int>(unsigned int&, asn1::cbit_ref&, unsigned int, unsigned int, bool)
Line
Count
Source
737
1.05M
{
738
1.05M
  if (ub >= ASN_64K) {
739
6.66k
    uint32_t      len;
740
6.66k
    OCUDUASN_CODE ret = unpack_length(len, bref, aligned);
741
6.66k
    n                 = len;
742
6.66k
    return ret;
743
6.66k
  }
744
1.04M
  return unpack_constrained_whole_number(n, bref, lb, ub, aligned);
745
1.05M
}
asn1::OCUDUASN_CODE asn1::unpack_length<unsigned long>(unsigned long&, asn1::cbit_ref&, unsigned long, unsigned long, bool)
Line
Count
Source
737
2.70k
{
738
2.70k
  if (ub >= ASN_64K) {
739
388
    uint32_t      len;
740
388
    OCUDUASN_CODE ret = unpack_length(len, bref, aligned);
741
388
    n                 = len;
742
388
    return ret;
743
388
  }
744
2.31k
  return unpack_constrained_whole_number(n, bref, lb, ub, aligned);
745
2.70k
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<signed char>(signed char&, asn1::cbit_ref&, signed char, signed char, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<short>(short&, asn1::cbit_ref&, short, short, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<int>(int&, asn1::cbit_ref&, int, int, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_length<long>(long&, asn1::cbit_ref&, long, long, bool)
746
template OCUDUASN_CODE unpack_length<uint8_t>(uint8_t& n, cbit_ref& bref, uint8_t lb, uint8_t ub, bool aligned);
747
template OCUDUASN_CODE unpack_length<uint16_t>(uint16_t& n, cbit_ref& bref, uint16_t lb, uint16_t ub, bool aligned);
748
template OCUDUASN_CODE unpack_length<uint32_t>(uint32_t& n, cbit_ref& bref, uint32_t lb, uint32_t ub, bool aligned);
749
template OCUDUASN_CODE unpack_length<uint64_t>(uint64_t& n, cbit_ref& bref, uint64_t lb, uint64_t ub, bool aligned);
750
template OCUDUASN_CODE unpack_length<int8_t>(int8_t& n, cbit_ref& bref, int8_t lb, int8_t ub, bool aligned);
751
template OCUDUASN_CODE unpack_length<int16_t>(int16_t& n, cbit_ref& bref, int16_t lb, int16_t ub, bool aligned);
752
template OCUDUASN_CODE unpack_length<int32_t>(int32_t& n, cbit_ref& bref, int32_t lb, int32_t ub, bool aligned);
753
template OCUDUASN_CODE unpack_length<int64_t>(int64_t& n, cbit_ref& bref, int64_t lb, int64_t ub, bool aligned);
754
755
/**
756
 * X.691 - Section 10.9
757
 * Pack unconstrained length determinant
758
 * @param bref
759
 * @param val "n" length value to pack
760
 * @param aligned
761
 * @return
762
 */
763
OCUDUASN_CODE pack_length(bit_ref& bref, uint32_t val, bool aligned)
764
91.1k
{
765
91.1k
  if (not aligned) {
766
91.1k
    if (val < 128) {
767
91.1k
      HANDLE_CODE(bref.pack(val, 8)); // first bit is 0
768
91.1k
    } else if (val < ASN_16K) {
769
0
      HANDLE_CODE(bref.pack(0b10, 2));
770
0
      HANDLE_CODE(bref.pack(val, 14));
771
0
    } else {
772
0
      log_error("Not handling sizes longer than 16383 octets");
773
0
      return OCUDUASN_ERROR_ENCODE_FAIL;
774
0
    }
775
91.1k
  } else {
776
20
    if (val > ASN_64K) {
777
      // TODO: Error message
778
0
      return OCUDUASN_ERROR_ENCODE_FAIL;
779
0
    }
780
20
    HANDLE_CODE(bref.align_bytes_zero());
781
20
    if (val < 128) {
782
20
      return bref.pack(val, 8); // first bit is 0
783
20
    } else if (val < ASN_16K) {
784
0
      HANDLE_CODE(bref.pack(0b10, 2));
785
0
      return bref.pack(val, 14);
786
0
    } else {
787
0
      HANDLE_CODE(bref.pack(0b11, 2));
788
0
      uint32_t m = val / ASN_16K;
789
0
      HANDLE_CODE(bref.pack(m, 6));
790
0
      val = val - m * ASN_16K;
791
0
      return bref.pack(val, 16); // TODO: TODO
792
0
    }
793
20
  }
794
91.1k
  return OCUDUASN_SUCCESS;
795
91.1k
}
796
797
OCUDUASN_CODE unpack_length(uint32_t& val, cbit_ref& bref, bool aligned)
798
464k
{
799
464k
  bool ext;
800
464k
  if (not aligned) {
801
121k
    OCUDUASN_CODE ret = bref.unpack(ext, 1);
802
121k
    HANDLE_CODE(ret);
803
121k
    if (not ext) {
804
118k
      ret = bref.unpack(val, 7);
805
118k
    } else {
806
3.06k
      ret = bref.unpack(ext, 1);
807
3.06k
      HANDLE_CODE(ret);
808
3.04k
      if (not ext) {
809
2.97k
        ret = bref.unpack(val, 14);
810
2.97k
      } else {
811
68
        log_error("Not handling octet strings longer than 16383 octets");
812
68
        val = 0;
813
68
        return OCUDUASN_ERROR_DECODE_FAIL;
814
68
      }
815
3.04k
    }
816
121k
    return ret;
817
343k
  } else {
818
343k
    HANDLE_CODE(bref.align_bytes());
819
343k
    HANDLE_CODE(bref.unpack(val, 8));
820
334k
    if (val < 128) {
821
      // "n" < 128
822
      // first bit was set to zero
823
318k
      return OCUDUASN_SUCCESS;
824
318k
    }
825
16.5k
    val -= 128;
826
16.5k
    if (val < 64) {
827
      // 128 <= "n" < 16K
828
      // second bit is set to zero as well
829
13.4k
      uint32_t val_octet_2;
830
13.4k
      HANDLE_CODE(bref.unpack(val_octet_2, 8));
831
13.2k
      val = (val << 8u) + val_octet_2;
832
13.2k
      return OCUDUASN_SUCCESS;
833
13.4k
    }
834
3.08k
    val = 0;
835
3.08k
    log_error("Not handling octet strings longer than 16383 octets");
836
3.08k
    return OCUDUASN_ERROR_DECODE_FAIL;
837
16.5k
  }
838
464k
}
839
840
/************************
841
        Integer
842
************************/
843
844
template <typename IntType>
845
OCUDUASN_CODE pack_integer(bit_ref& bref, IntType n, IntType lb, IntType ub, bool has_ext, bool aligned)
846
333k
{
847
  // pack ext marker
848
333k
  bool within_bounds = n >= lb and n <= ub;
849
333k
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
333k
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
333k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
333k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
333k
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
333k
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
333k
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
333k
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
333k
  return OCUDUASN_SUCCESS;
879
333k
}
asn1::OCUDUASN_CODE asn1::pack_integer<unsigned char>(asn1::bit_ref&, unsigned char, unsigned char, unsigned char, bool, bool)
Line
Count
Source
846
212k
{
847
  // pack ext marker
848
212k
  bool within_bounds = n >= lb and n <= ub;
849
212k
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
212k
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
212k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
212k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
212k
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
212k
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
212k
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
212k
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
212k
  return OCUDUASN_SUCCESS;
879
212k
}
asn1::OCUDUASN_CODE asn1::pack_integer<unsigned short>(asn1::bit_ref&, unsigned short, unsigned short, unsigned short, bool, bool)
Line
Count
Source
846
120k
{
847
  // pack ext marker
848
120k
  bool within_bounds = n >= lb and n <= ub;
849
120k
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
120k
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
120k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
120k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
120k
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
120k
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
120k
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
120k
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
120k
  return OCUDUASN_SUCCESS;
879
120k
}
asn1::OCUDUASN_CODE asn1::pack_integer<unsigned int>(asn1::bit_ref&, unsigned int, unsigned int, unsigned int, bool, bool)
Line
Count
Source
846
221
{
847
  // pack ext marker
848
221
  bool within_bounds = n >= lb and n <= ub;
849
221
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
221
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
221
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
221
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
221
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
221
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
221
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
221
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
221
  return OCUDUASN_SUCCESS;
879
221
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_integer<unsigned long>(asn1::bit_ref&, unsigned long, unsigned long, unsigned long, bool, bool)
asn1::OCUDUASN_CODE asn1::pack_integer<signed char>(asn1::bit_ref&, signed char, signed char, signed char, bool, bool)
Line
Count
Source
846
8
{
847
  // pack ext marker
848
8
  bool within_bounds = n >= lb and n <= ub;
849
8
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
8
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
8
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
8
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
8
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
8
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
8
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
8
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
8
  return OCUDUASN_SUCCESS;
879
8
}
asn1::OCUDUASN_CODE asn1::pack_integer<short>(asn1::bit_ref&, short, short, short, bool, bool)
Line
Count
Source
846
6
{
847
  // pack ext marker
848
6
  bool within_bounds = n >= lb and n <= ub;
849
6
  if (has_ext) {
850
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
851
6
  } else if (not within_bounds) {
852
0
    log_error("The condition lb <= n <= ub ({} <= {} <= {}) was not met", (long)lb, (long)n, (long)ub);
853
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
854
0
  }
855
6
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
856
6
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
857
858
6
  if (within_bounds and lower_bounded and upper_bounded) {
859
    // constrained case
860
6
    if (lb == ub) {
861
0
      return OCUDUASN_SUCCESS;
862
0
    }
863
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
864
    //    if(indefinite_length) {
865
    //      HANDLE_CODE(pack_length(bref, n, 1, ceilf(log2f()), aligned));
866
    //    }
867
6
    HANDLE_CODE(pack_constrained_whole_number(bref, n, (IntType)lb, (IntType)ub, aligned));
868
6
  } else {
869
    // See X.691 - 12.2.6
870
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
871
0
      HANDLE_CODE(pack_length(bref, unconstrained_whole_number_length(n), aligned));
872
0
      HANDLE_CODE(pack_unconstrained_whole_number(bref, n, aligned));
873
0
    } else {
874
      // pack as semi-constrained
875
      // TODO
876
0
    }
877
0
  }
878
6
  return OCUDUASN_SUCCESS;
879
6
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_integer<int>(asn1::bit_ref&, int, int, int, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_integer<long>(asn1::bit_ref&, long, long, long, bool, bool)
880
template OCUDUASN_CODE
881
pack_integer<uint8_t>(bit_ref& bref, uint8_t n, uint8_t lb, uint8_t ub, bool has_ext, bool aligned);
882
template OCUDUASN_CODE
883
pack_integer<uint16_t>(bit_ref& bref, uint16_t n, uint16_t lb, uint16_t ub, bool has_ext, bool aligned);
884
template OCUDUASN_CODE
885
pack_integer<uint32_t>(bit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool has_ext, bool aligned);
886
template OCUDUASN_CODE
887
pack_integer<uint64_t>(bit_ref& bref, uint64_t n, uint64_t lb, uint64_t ub, bool has_ext, bool aligned);
888
template OCUDUASN_CODE pack_integer<int8_t>(bit_ref& bref, int8_t n, int8_t lb, int8_t ub, bool has_ext, bool aligned);
889
template OCUDUASN_CODE
890
pack_integer<int16_t>(bit_ref& bref, int16_t n, int16_t lb, int16_t ub, bool has_ext, bool aligned);
891
template OCUDUASN_CODE
892
pack_integer<int32_t>(bit_ref& bref, int32_t n, int32_t lb, int32_t ub, bool has_ext, bool aligned);
893
template OCUDUASN_CODE
894
pack_integer<int64_t>(bit_ref& bref, int64_t n, int64_t lb, int64_t ub, bool has_ext, bool aligned);
895
896
// unconstrained specialization case
897
template <typename IntType>
898
OCUDUASN_CODE pack_unconstrained_integer(bit_ref& bref, IntType n, bool has_ext, bool aligned)
899
0
{
900
0
  return pack_integer(
901
0
      bref, n, std::numeric_limits<IntType>::min(), std::numeric_limits<IntType>::max(), has_ext, aligned);
902
0
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_integer<signed char>(asn1::bit_ref&, signed char, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_integer<short>(asn1::bit_ref&, short, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_integer<int>(asn1::bit_ref&, int, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::pack_unconstrained_integer<long>(asn1::bit_ref&, long, bool, bool)
903
template OCUDUASN_CODE pack_unconstrained_integer<int8_t>(bit_ref& bref, int8_t n, bool has_ext, bool aligned);
904
template OCUDUASN_CODE pack_unconstrained_integer<int16_t>(bit_ref& bref, int16_t n, bool has_ext, bool aligned);
905
template OCUDUASN_CODE pack_unconstrained_integer<int32_t>(bit_ref& bref, int32_t n, bool has_ext, bool aligned);
906
template OCUDUASN_CODE pack_unconstrained_integer<int64_t>(bit_ref& bref, int64_t n, bool has_ext, bool aligned);
907
908
template <typename IntType>
909
OCUDUASN_CODE unpack_integer(IntType& n, cbit_ref& bref, IntType lb, IntType ub, bool has_ext, bool aligned)
910
6.81M
{
911
6.81M
  bool within_bounds = true;
912
6.81M
  if (has_ext) {
913
26.5k
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
26.2k
    within_bounds = not within_bounds;
915
26.2k
  }
916
6.81M
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
6.81M
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
6.81M
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
6.81M
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
6.81M
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
6.81M
  } else {
927
    // See X.691 - 12.2.6
928
2.63k
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
2.63k
      uint32_t len;
930
2.63k
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
2.35k
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
2.35k
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
2.63k
  }
937
6.78M
  return OCUDUASN_SUCCESS;
938
6.81M
}
asn1::OCUDUASN_CODE asn1::unpack_integer<unsigned char>(unsigned char&, asn1::cbit_ref&, unsigned char, unsigned char, bool, bool)
Line
Count
Source
910
2.25M
{
911
2.25M
  bool within_bounds = true;
912
2.25M
  if (has_ext) {
913
12.2k
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
12.1k
    within_bounds = not within_bounds;
915
12.1k
  }
916
2.25M
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
2.25M
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
2.25M
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
2.25M
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
2.25M
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
2.25M
  } else {
927
    // See X.691 - 12.2.6
928
885
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
885
      uint32_t len;
930
885
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
787
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
787
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
885
  }
937
2.25M
  return OCUDUASN_SUCCESS;
938
2.25M
}
asn1::OCUDUASN_CODE asn1::unpack_integer<unsigned short>(unsigned short&, asn1::cbit_ref&, unsigned short, unsigned short, bool, bool)
Line
Count
Source
910
3.82M
{
911
3.82M
  bool within_bounds = true;
912
3.82M
  if (has_ext) {
913
7.26k
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
7.18k
    within_bounds = not within_bounds;
915
7.18k
  }
916
3.82M
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
3.82M
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
3.82M
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
3.82M
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
3.82M
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
3.82M
  } else {
927
    // See X.691 - 12.2.6
928
705
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
705
      uint32_t len;
930
705
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
609
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
609
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
705
  }
937
3.81M
  return OCUDUASN_SUCCESS;
938
3.82M
}
asn1::OCUDUASN_CODE asn1::unpack_integer<unsigned int>(unsigned int&, asn1::cbit_ref&, unsigned int, unsigned int, bool, bool)
Line
Count
Source
910
596k
{
911
596k
  bool within_bounds = true;
912
596k
  if (has_ext) {
913
2.40k
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
2.27k
    within_bounds = not within_bounds;
915
2.27k
  }
916
596k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
596k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
596k
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
595k
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
595k
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
595k
  } else {
927
    // See X.691 - 12.2.6
928
529
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
529
      uint32_t len;
930
529
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
496
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
496
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
529
  }
937
580k
  return OCUDUASN_SUCCESS;
938
596k
}
asn1::OCUDUASN_CODE asn1::unpack_integer<unsigned long>(unsigned long&, asn1::cbit_ref&, unsigned long, unsigned long, bool, bool)
Line
Count
Source
910
38.3k
{
911
38.3k
  bool within_bounds = true;
912
38.3k
  if (has_ext) {
913
4.67k
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
4.61k
    within_bounds = not within_bounds;
915
4.61k
  }
916
38.2k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
38.2k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
38.2k
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
37.7k
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
37.7k
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
37.7k
  } else {
927
    // See X.691 - 12.2.6
928
517
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
517
      uint32_t len;
930
517
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
458
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
458
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
517
  }
937
34.8k
  return OCUDUASN_SUCCESS;
938
38.2k
}
asn1::OCUDUASN_CODE asn1::unpack_integer<signed char>(signed char&, asn1::cbit_ref&, signed char, signed char, bool, bool)
Line
Count
Source
910
50.9k
{
911
50.9k
  bool within_bounds = true;
912
50.9k
  if (has_ext) {
913
0
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
0
    within_bounds = not within_bounds;
915
0
  }
916
50.9k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
50.9k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
50.9k
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
50.9k
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
50.9k
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
50.9k
  } else {
927
    // See X.691 - 12.2.6
928
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
0
      uint32_t len;
930
0
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
0
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
0
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
0
  }
937
50.9k
  return OCUDUASN_SUCCESS;
938
50.9k
}
asn1::OCUDUASN_CODE asn1::unpack_integer<short>(short&, asn1::cbit_ref&, short, short, bool, bool)
Line
Count
Source
910
53.5k
{
911
53.5k
  bool within_bounds = true;
912
53.5k
  if (has_ext) {
913
0
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
0
    within_bounds = not within_bounds;
915
0
  }
916
53.5k
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
53.5k
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
53.5k
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
53.5k
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
53.5k
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
53.5k
  } else {
927
    // See X.691 - 12.2.6
928
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
0
      uint32_t len;
930
0
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
0
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
0
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
0
  }
937
53.4k
  return OCUDUASN_SUCCESS;
938
53.5k
}
asn1::OCUDUASN_CODE asn1::unpack_integer<int>(int&, asn1::cbit_ref&, int, int, bool, bool)
Line
Count
Source
910
102
{
911
102
  bool within_bounds = true;
912
102
  if (has_ext) {
913
0
    HANDLE_CODE(bref.unpack(within_bounds, 1));
914
0
    within_bounds = not within_bounds;
915
0
  }
916
102
  bool lower_bounded = lb != std::numeric_limits<IntType>::min() or std::is_unsigned<IntType>::value;
917
102
  bool upper_bounded = ub != std::numeric_limits<IntType>::max();
918
919
102
  if (within_bounds and lower_bounded and upper_bounded) {
920
    // constrained case
921
102
    if (lb == ub) {
922
0
      return OCUDUASN_SUCCESS;
923
0
    }
924
    // TODO: Check if we are in the indefinite length case, and pack length prefix if needed
925
102
    HANDLE_CODE(unpack_constrained_whole_number(n, bref, (IntType)lb, (IntType)ub, aligned));
926
102
  } else {
927
    // See X.691 - 12.2.6
928
0
    if (not within_bounds or (not lower_bounded and not upper_bounded)) {
929
0
      uint32_t len;
930
0
      HANDLE_CODE(unpack_length(len, bref, aligned));
931
0
      HANDLE_CODE(unpack_unconstrained_whole_number(n, bref, len, aligned));
932
0
    } else {
933
      // pack as semi-constrained
934
      // TODO
935
0
    }
936
0
  }
937
102
  return OCUDUASN_SUCCESS;
938
102
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_integer<long>(long&, asn1::cbit_ref&, long, long, bool, bool)
939
template OCUDUASN_CODE
940
unpack_integer<uint8_t>(uint8_t& n, cbit_ref& bref, uint8_t lb, uint8_t ub, bool has_ext, bool aligned);
941
template OCUDUASN_CODE
942
unpack_integer<uint16_t>(uint16_t& n, cbit_ref& bref, uint16_t lb, uint16_t ub, bool has_ext, bool aligned);
943
template OCUDUASN_CODE
944
unpack_integer<uint32_t>(uint32_t& n, cbit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool aligned);
945
template OCUDUASN_CODE
946
unpack_integer<uint64_t>(uint64_t& n, cbit_ref& bref, uint64_t lb, uint64_t ub, bool has_ext, bool aligned);
947
template OCUDUASN_CODE
948
unpack_integer<int8_t>(int8_t& n, cbit_ref& bref, int8_t lb, int8_t ub, bool has_ext, bool aligned);
949
template OCUDUASN_CODE
950
unpack_integer<int16_t>(int16_t& n, cbit_ref& bref, int16_t lb, int16_t ub, bool has_ext, bool aligned);
951
template OCUDUASN_CODE
952
unpack_integer<int32_t>(int32_t& n, cbit_ref& bref, int32_t lb, int32_t ub, bool has_ext, bool aligned);
953
template OCUDUASN_CODE
954
unpack_integer<int64_t>(int64_t& n, cbit_ref& bref, int64_t lb, int64_t ub, bool has_ext, bool aligned);
955
956
// unconstrained specialization case
957
template <typename IntType>
958
OCUDUASN_CODE unpack_unconstrained_integer(IntType& n, cbit_ref& bref, bool has_ext, bool aligned)
959
0
{
960
0
  return unpack_integer(
961
0
      n, bref, std::numeric_limits<IntType>::min(), std::numeric_limits<IntType>::max(), has_ext, aligned);
962
0
}
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_integer<signed char>(signed char&, asn1::cbit_ref&, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_integer<short>(short&, asn1::cbit_ref&, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_integer<int>(int&, asn1::cbit_ref&, bool, bool)
Unexecuted instantiation: asn1::OCUDUASN_CODE asn1::unpack_unconstrained_integer<long>(long&, asn1::cbit_ref&, bool, bool)
963
template OCUDUASN_CODE unpack_unconstrained_integer<int8_t>(int8_t& n, cbit_ref& bref, bool has_ext, bool aligned);
964
template OCUDUASN_CODE unpack_unconstrained_integer<int16_t>(int16_t& n, cbit_ref& bref, bool has_ext, bool aligned);
965
template OCUDUASN_CODE unpack_unconstrained_integer<int32_t>(int32_t& n, cbit_ref& bref, bool has_ext, bool aligned);
966
template OCUDUASN_CODE unpack_unconstrained_integer<int64_t>(int64_t& n, cbit_ref& bref, bool has_ext, bool aligned);
967
968
// standalone packer
969
template <class IntType>
970
integer_packer<IntType>::integer_packer(IntType lb_, IntType ub_, bool has_ext_, bool aligned_) :
971
209k
  lb(lb_), ub(ub_), has_ext(has_ext_), aligned(aligned_)
972
209k
{
973
209k
}
Unexecuted instantiation: asn1::integer_packer<signed char>::integer_packer(signed char, signed char, bool, bool)
asn1::integer_packer<short>::integer_packer(short, short, bool, bool)
Line
Count
Source
971
46
  lb(lb_), ub(ub_), has_ext(has_ext_), aligned(aligned_)
972
46
{
973
46
}
Unexecuted instantiation: asn1::integer_packer<int>::integer_packer(int, int, bool, bool)
Unexecuted instantiation: asn1::integer_packer<long>::integer_packer(long, long, bool, bool)
asn1::integer_packer<unsigned char>::integer_packer(unsigned char, unsigned char, bool, bool)
Line
Count
Source
971
157k
  lb(lb_), ub(ub_), has_ext(has_ext_), aligned(aligned_)
972
157k
{
973
157k
}
asn1::integer_packer<unsigned short>::integer_packer(unsigned short, unsigned short, bool, bool)
Line
Count
Source
971
51.4k
  lb(lb_), ub(ub_), has_ext(has_ext_), aligned(aligned_)
972
51.4k
{
973
51.4k
}
asn1::integer_packer<unsigned int>::integer_packer(unsigned int, unsigned int, bool, bool)
Line
Count
Source
971
260
  lb(lb_), ub(ub_), has_ext(has_ext_), aligned(aligned_)
972
260
{
973
260
}
Unexecuted instantiation: asn1::integer_packer<unsigned long>::integer_packer(unsigned long, unsigned long, bool, bool)
974
975
template <class IntType>
976
OCUDUASN_CODE integer_packer<IntType>::pack(bit_ref& bref, IntType n)
977
36.1k
{
978
36.1k
  return pack_integer(bref, n, lb, ub, has_ext, aligned);
979
36.1k
}
Unexecuted instantiation: asn1::integer_packer<signed char>::pack(asn1::bit_ref&, signed char)
Unexecuted instantiation: asn1::integer_packer<short>::pack(asn1::bit_ref&, short)
Unexecuted instantiation: asn1::integer_packer<int>::pack(asn1::bit_ref&, int)
Unexecuted instantiation: asn1::integer_packer<long>::pack(asn1::bit_ref&, long)
asn1::integer_packer<unsigned char>::pack(asn1::bit_ref&, unsigned char)
Line
Count
Source
977
10
{
978
10
  return pack_integer(bref, n, lb, ub, has_ext, aligned);
979
10
}
asn1::integer_packer<unsigned short>::pack(asn1::bit_ref&, unsigned short)
Line
Count
Source
977
36.1k
{
978
36.1k
  return pack_integer(bref, n, lb, ub, has_ext, aligned);
979
36.1k
}
Unexecuted instantiation: asn1::integer_packer<unsigned int>::pack(asn1::bit_ref&, unsigned int)
Unexecuted instantiation: asn1::integer_packer<unsigned long>::pack(asn1::bit_ref&, unsigned long)
980
template <class IntType>
981
OCUDUASN_CODE integer_packer<IntType>::unpack(IntType& n, cbit_ref& bref)
982
496k
{
983
496k
  return unpack_integer(n, bref, lb, ub, has_ext, aligned);
984
496k
}
Unexecuted instantiation: asn1::integer_packer<signed char>::unpack(signed char&, asn1::cbit_ref&)
asn1::integer_packer<short>::unpack(short&, asn1::cbit_ref&)
Line
Count
Source
982
64
{
983
64
  return unpack_integer(n, bref, lb, ub, has_ext, aligned);
984
64
}
Unexecuted instantiation: asn1::integer_packer<int>::unpack(int&, asn1::cbit_ref&)
Unexecuted instantiation: asn1::integer_packer<long>::unpack(long&, asn1::cbit_ref&)
asn1::integer_packer<unsigned char>::unpack(unsigned char&, asn1::cbit_ref&)
Line
Count
Source
982
441k
{
983
441k
  return unpack_integer(n, bref, lb, ub, has_ext, aligned);
984
441k
}
asn1::integer_packer<unsigned short>::unpack(unsigned short&, asn1::cbit_ref&)
Line
Count
Source
982
53.1k
{
983
53.1k
  return unpack_integer(n, bref, lb, ub, has_ext, aligned);
984
53.1k
}
asn1::integer_packer<unsigned int>::unpack(unsigned int&, asn1::cbit_ref&)
Line
Count
Source
982
1.63k
{
983
1.63k
  return unpack_integer(n, bref, lb, ub, has_ext, aligned);
984
1.63k
}
Unexecuted instantiation: asn1::integer_packer<unsigned long>::unpack(unsigned long&, asn1::cbit_ref&)
985
template struct integer_packer<int8_t>;
986
template struct integer_packer<int16_t>;
987
template struct integer_packer<int32_t>;
988
template struct integer_packer<int64_t>;
989
template struct integer_packer<uint8_t>;
990
template struct integer_packer<uint16_t>;
991
template struct integer_packer<uint32_t>;
992
template struct integer_packer<uint64_t>;
993
994
/************************
995
    common octstring
996
************************/
997
998
uint64_t octet_string_helper::to_uint(ocudu::span<const uint8_t> buf)
999
13.1k
{
1000
13.1k
  size_t nbytes = buf.size();
1001
13.1k
  if (nbytes > 8U) {
1002
0
    log_error("OCTET STRING of size={} does not fit in an uint64_t", nbytes);
1003
0
    return 0;
1004
0
  }
1005
13.1k
  uint64_t val = 0;
1006
38.6k
  for (unsigned i = 0; i < nbytes; ++i) {
1007
25.5k
    val += ((uint64_t)buf[nbytes - 1 - i]) << (uint64_t)(i * 8U);
1008
25.5k
  }
1009
13.1k
  return val;
1010
13.1k
}
1011
1012
uint64_t octet_string_helper::to_uint(const byte_buffer& buf)
1013
0
{
1014
0
  size_t nbytes = buf.length();
1015
0
  if (nbytes > 8) {
1016
0
    log_error("OCTET STRING with size={} does not fit in an uint64_t", nbytes);
1017
0
    return 0;
1018
0
  }
1019
0
  uint64_t val = 0;
1020
0
  auto     it  = buf.begin();
1021
0
  for (unsigned i = 0; i < nbytes; ++i) {
1022
0
    val += static_cast<uint64_t>(*it) << static_cast<uint64_t>((nbytes - 1 - i) * 8U);
1023
0
    ++it;
1024
0
  }
1025
0
  return val;
1026
0
}
1027
1028
void octet_string_helper::to_octet_string(ocudu::span<uint8_t> buf, uint64_t number)
1029
20.6k
{
1030
20.6k
  uint64_t nbytes = buf.size();
1031
20.6k
  if (nbytes < 8 and (static_cast<uint64_t>(1U) << (8U * nbytes)) <= number) {
1032
0
    log_error("Integer={} does not fit in an OCTET STRING of size={}", number, nbytes);
1033
0
    return;
1034
0
  }
1035
70.4k
  for (uint32_t i = 0; i < nbytes; ++i) {
1036
49.8k
    buf[nbytes - 1 - i] = (number >> (uint64_t)(i * 8U)) & 0xffu;
1037
49.8k
  }
1038
20.6k
}
1039
1040
void octet_string_helper::to_octet_string(ocudu::byte_buffer& buf, uint64_t number)
1041
0
{
1042
0
  buf           = byte_buffer{byte_buffer::fallback_allocation_tag{}};
1043
0
  size_t nbytes = sizeof(number);
1044
0
  for (uint32_t i = 0; i < nbytes; ++i) {
1045
0
    if (not buf.append((number >> (uint64_t)((nbytes - 1 - i) * 8U)) & 0xffu)) {
1046
0
      log_error("Failed to append octet string byte to buffer");
1047
0
      return;
1048
0
    }
1049
0
  }
1050
0
}
1051
1052
static void to_hex(char* cstr, uint8_t val)
1053
7.84M
{
1054
7.84M
  std::sprintf(cstr, "%02x", val);
1055
7.84M
}
1056
1057
std::string octet_string_helper::to_hex_string(ocudu::span<const uint8_t> buf)
1058
75.0k
{
1059
75.0k
  std::string s;
1060
75.0k
  s.resize(buf.size() * 2);
1061
75.0k
  char cstr[3];
1062
295k
  for (uint32_t i = 0; i < buf.size(); i++) {
1063
220k
    to_hex(cstr, buf[i]);
1064
220k
    s.replace(i * 2, 2, cstr);
1065
220k
  }
1066
75.0k
  return s;
1067
75.0k
}
1068
1069
std::string octet_string_helper::to_hex_string(const byte_buffer& buf)
1070
130k
{
1071
130k
  std::string s;
1072
130k
  s.resize(buf.length() * 2);
1073
130k
  char     cstr[3];
1074
130k
  unsigned i = 0;
1075
7.62M
  for (uint8_t b : buf) {
1076
7.62M
    to_hex(cstr, b);
1077
7.62M
    s.replace(i * 2, 2, cstr);
1078
7.62M
    ++i;
1079
7.62M
  }
1080
130k
  return s;
1081
130k
}
1082
1083
unsigned octet_string_helper::hex_string_to_octets(ocudu::span<uint8_t> buf, const std::string& str)
1084
12.0k
{
1085
12.0k
  ocudu_assert(buf.size() >= ceil_frac(str.size(), (size_t)2U), "out-of-bounds access");
1086
12.0k
  if (str.size() % 2 != 0) {
1087
0
    log_error("The provided hex string size={} is not a multiple of 2.", str.size());
1088
0
  }
1089
12.0k
  char cstr[] = "\0\0\0";
1090
48.2k
  for (unsigned i = 0; i < str.size(); i += 2) {
1091
36.1k
    std::memcpy(&cstr[0], &str[i], 2);
1092
36.1k
    buf[i / 2] = strtoul(cstr, nullptr, 16);
1093
36.1k
  }
1094
12.0k
  return (str.size() + 1) / 2;
1095
12.0k
}
1096
1097
void octet_string_helper::append_hex_string(byte_buffer& buf, const std::string& str)
1098
47.8k
{
1099
47.8k
  if (str.size() % 2 != 0) {
1100
0
    log_error("The provided hex string size={} is not a multiple of 2.", str.size());
1101
0
  }
1102
47.8k
  char cstr[] = "\0\0\0";
1103
3.26M
  for (unsigned i = 0; i < str.size(); i += 2) {
1104
3.21M
    std::memcpy(&cstr[0], &str[i], 2);
1105
3.21M
    if (not buf.append(strtoul(cstr, nullptr, 16))) {
1106
0
      log_error("Failed to append octet string byte to buffer");
1107
0
    }
1108
3.21M
  }
1109
47.8k
}
1110
1111
/************************
1112
     dyn_octstring
1113
************************/
1114
1115
template <bool Al>
1116
unbounded_octstring<Al>::unbounded_octstring(const unbounded_octstring& other) noexcept :
1117
  // Use fallback allocator, because operator= should never fail.
1118
2.72M
  ocudu::byte_buffer(fallback_allocation_tag{}, other)
1119
2.72M
{
1120
2.72M
}
asn1::unbounded_octstring<true>::unbounded_octstring(asn1::unbounded_octstring<true> const&)
Line
Count
Source
1118
2.42M
  ocudu::byte_buffer(fallback_allocation_tag{}, other)
1119
2.42M
{
1120
2.42M
}
asn1::unbounded_octstring<false>::unbounded_octstring(asn1::unbounded_octstring<false> const&)
Line
Count
Source
1118
294k
  ocudu::byte_buffer(fallback_allocation_tag{}, other)
1119
294k
{
1120
294k
}
1121
1122
template <bool Al>
1123
unbounded_octstring<Al>& unbounded_octstring<Al>::operator=(const unbounded_octstring& other) noexcept
1124
1.17M
{
1125
1.17M
  if (this != &other) {
1126
    // Use fallback allocator, because operator= should never fail.
1127
1.17M
    *this = byte_buffer{fallback_allocation_tag{}, other};
1128
1.17M
  }
1129
1.17M
  return *this;
1130
1.17M
}
asn1::unbounded_octstring<true>::operator=(asn1::unbounded_octstring<true> const&)
Line
Count
Source
1124
273k
{
1125
273k
  if (this != &other) {
1126
    // Use fallback allocator, because operator= should never fail.
1127
273k
    *this = byte_buffer{fallback_allocation_tag{}, other};
1128
273k
  }
1129
273k
  return *this;
1130
273k
}
asn1::unbounded_octstring<false>::operator=(asn1::unbounded_octstring<false> const&)
Line
Count
Source
1124
905k
{
1125
905k
  if (this != &other) {
1126
    // Use fallback allocator, because operator= should never fail.
1127
905k
    *this = byte_buffer{fallback_allocation_tag{}, other};
1128
905k
  }
1129
905k
  return *this;
1130
905k
}
1131
1132
template <bool Al>
1133
unbounded_octstring<Al>& unbounded_octstring<Al>::operator=(unbounded_octstring&& other) noexcept
1134
81.8k
{
1135
81.8k
  *static_cast<byte_buffer*>(this) = std::move(other);
1136
81.8k
  return *this;
1137
81.8k
}
asn1::unbounded_octstring<true>::operator=(asn1::unbounded_octstring<true>&&)
Line
Count
Source
1134
81.8k
{
1135
81.8k
  *static_cast<byte_buffer*>(this) = std::move(other);
1136
81.8k
  return *this;
1137
81.8k
}
Unexecuted instantiation: asn1::unbounded_octstring<false>::operator=(asn1::unbounded_octstring<false>&&)
1138
1139
template <bool Al>
1140
OCUDUASN_CODE unbounded_octstring<Al>::pack(bit_ref& bref) const
1141
85.0k
{
1142
85.0k
  HANDLE_CODE(pack_length(bref, length(), aligned));
1143
4.92M
  for (uint8_t b : *this) {
1144
4.92M
    HANDLE_CODE(bref.pack(b, 8));
1145
4.92M
  }
1146
85.0k
  return OCUDUASN_SUCCESS;
1147
85.0k
}
Unexecuted instantiation: asn1::unbounded_octstring<true>::pack(asn1::bit_ref&) const
asn1::unbounded_octstring<false>::pack(asn1::bit_ref&) const
Line
Count
Source
1141
85.0k
{
1142
85.0k
  HANDLE_CODE(pack_length(bref, length(), aligned));
1143
4.92M
  for (uint8_t b : *this) {
1144
4.92M
    HANDLE_CODE(bref.pack(b, 8));
1145
4.92M
  }
1146
85.0k
  return OCUDUASN_SUCCESS;
1147
85.0k
}
1148
1149
template <bool Al>
1150
OCUDUASN_CODE unbounded_octstring<Al>::unpack(cbit_ref& bref)
1151
115k
{
1152
115k
  unsigned len;
1153
115k
  HANDLE_CODE(unpack_length(len, bref, aligned));
1154
113k
  clear();
1155
5.23M
  for (unsigned i = 0; i != len; ++i) {
1156
5.12M
    uint8_t b;
1157
5.12M
    HANDLE_CODE(bref.unpack(b, 8));
1158
5.12M
    HANDLE_CODE(append(b) ? OCUDUASN_SUCCESS : OCUDUASN_ERROR_DECODE_FAIL);
1159
5.12M
  }
1160
111k
  return OCUDUASN_SUCCESS;
1161
113k
}
asn1::unbounded_octstring<true>::unpack(asn1::cbit_ref&)
Line
Count
Source
1151
64.5k
{
1152
64.5k
  unsigned len;
1153
64.5k
  HANDLE_CODE(unpack_length(len, bref, aligned));
1154
63.0k
  clear();
1155
718k
  for (unsigned i = 0; i != len; ++i) {
1156
657k
    uint8_t b;
1157
657k
    HANDLE_CODE(bref.unpack(b, 8));
1158
655k
    HANDLE_CODE(append(b) ? OCUDUASN_SUCCESS : OCUDUASN_ERROR_DECODE_FAIL);
1159
655k
  }
1160
61.2k
  return OCUDUASN_SUCCESS;
1161
63.0k
}
asn1::unbounded_octstring<false>::unpack(asn1::cbit_ref&)
Line
Count
Source
1151
50.9k
{
1152
50.9k
  unsigned len;
1153
50.9k
  HANDLE_CODE(unpack_length(len, bref, aligned));
1154
50.7k
  clear();
1155
4.51M
  for (unsigned i = 0; i != len; ++i) {
1156
4.46M
    uint8_t b;
1157
4.46M
    HANDLE_CODE(bref.unpack(b, 8));
1158
4.46M
    HANDLE_CODE(append(b) ? OCUDUASN_SUCCESS : OCUDUASN_ERROR_DECODE_FAIL);
1159
4.46M
  }
1160
50.5k
  return OCUDUASN_SUCCESS;
1161
50.7k
}
1162
1163
template <bool Al>
1164
std::string unbounded_octstring<Al>::to_string() const
1165
130k
{
1166
130k
  return octet_string_helper::to_hex_string(*this);
1167
130k
}
asn1::unbounded_octstring<true>::to_string() const
Line
Count
Source
1165
40.8k
{
1166
40.8k
  return octet_string_helper::to_hex_string(*this);
1167
40.8k
}
asn1::unbounded_octstring<false>::to_string() const
Line
Count
Source
1165
89.2k
{
1166
89.2k
  return octet_string_helper::to_hex_string(*this);
1167
89.2k
}
1168
1169
template <bool Al>
1170
unbounded_octstring<Al>& unbounded_octstring<Al>::from_string(const std::string& hexstr)
1171
47.8k
{
1172
  // clears previous buffer.
1173
47.8k
  *this = byte_buffer{byte_buffer::fallback_allocation_tag{}};
1174
1175
  // appends hex string to buffer.
1176
47.8k
  octet_string_helper::append_hex_string(*this, hexstr);
1177
1178
47.8k
  return *this;
1179
47.8k
}
asn1::unbounded_octstring<true>::from_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
1171
31.1k
{
1172
  // clears previous buffer.
1173
31.1k
  *this = byte_buffer{byte_buffer::fallback_allocation_tag{}};
1174
1175
  // appends hex string to buffer.
1176
31.1k
  octet_string_helper::append_hex_string(*this, hexstr);
1177
1178
31.1k
  return *this;
1179
31.1k
}
asn1::unbounded_octstring<false>::from_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
1171
16.6k
{
1172
  // clears previous buffer.
1173
16.6k
  *this = byte_buffer{byte_buffer::fallback_allocation_tag{}};
1174
1175
  // appends hex string to buffer.
1176
16.6k
  octet_string_helper::append_hex_string(*this, hexstr);
1177
1178
16.6k
  return *this;
1179
16.6k
}
1180
1181
template <bool Al>
1182
unbounded_octstring<Al>& unbounded_octstring<Al>::from_bytes(span<const uint8_t> bytes)
1183
0
{
1184
  // clears previous buffer.
1185
0
  *this = byte_buffer{byte_buffer::fallback_allocation_tag{}};
1186
1187
  // appends bytes to buffer.
1188
0
  if (not this->append(bytes)) {
1189
0
    log_error("Failed to append byte to buffer");
1190
0
  }
1191
1192
0
  return *this;
1193
0
}
Unexecuted instantiation: asn1::unbounded_octstring<true>::from_bytes(ocudu::span<unsigned char const>)
Unexecuted instantiation: asn1::unbounded_octstring<false>::from_bytes(ocudu::span<unsigned char const>)
1194
1195
template <bool Al>
1196
uint64_t unbounded_octstring<Al>::to_number() const
1197
0
{
1198
0
  return octet_string_helper::to_uint(*this);
1199
0
}
Unexecuted instantiation: asn1::unbounded_octstring<true>::to_number() const
Unexecuted instantiation: asn1::unbounded_octstring<false>::to_number() const
1200
1201
template <bool Al>
1202
unbounded_octstring<Al>& unbounded_octstring<Al>::from_number(uint64_t val)
1203
0
{
1204
0
  octet_string_helper::to_octet_string(*this, val);
1205
0
  return *this;
1206
0
}
Unexecuted instantiation: asn1::unbounded_octstring<true>::from_number(unsigned long)
Unexecuted instantiation: asn1::unbounded_octstring<false>::from_number(unsigned long)
1207
1208
template class unbounded_octstring<true>;
1209
template class unbounded_octstring<false>;
1210
1211
/*********************
1212
     bitstring
1213
*********************/
1214
1215
namespace bitstring_utils {
1216
1217
/**
1218
 * Pack ASN1 bitstring length prefix. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext
1219
 */
1220
static OCUDUASN_CODE pack_length_prefix(bit_ref& bref,
1221
                                        uint32_t len,
1222
                                        uint32_t lb         = 0,
1223
                                        uint32_t ub         = std::numeric_limits<uint32_t>::max(),
1224
                                        bool     has_ext    = false,
1225
                                        bool     is_aligned = false)
1226
89.1k
{
1227
89.1k
  if (has_ext and ub == std::numeric_limits<uint32_t>::max()) {
1228
0
    log_error("has extension marker but it is an unbounded prefix size");
1229
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
1230
0
  }
1231
89.1k
  bool within_bounds = len >= lb and len <= ub;
1232
89.1k
  if (not within_bounds and not has_ext) {
1233
0
    log_error("bitstring length={} is not within bounds [{}, {}]", len, lb, ub);
1234
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
1235
0
  }
1236
1237
  // encode ext bit
1238
89.1k
  if (has_ext) {
1239
0
    HANDLE_CODE(bref.pack(not within_bounds, 1));
1240
0
  }
1241
1242
  // do not encode prefix if fixed size
1243
89.1k
  if (lb == ub and within_bounds) {
1244
89.1k
    return OCUDUASN_SUCCESS;
1245
89.1k
  }
1246
1247
  // pack as unbounded if unbounded bitstring or ext is active
1248
2
  if (ub == std::numeric_limits<uint32_t>::max() or not within_bounds) {
1249
0
    return pack_length(bref, len);
1250
0
  }
1251
1252
  // pack as bounded bitstring
1253
2
  uint32_t len_bits = (uint32_t)std::ceil(std::log2(ub - lb));
1254
2
  HANDLE_CODE(bref.pack(len - lb, len_bits));
1255
2
  if (is_aligned) {
1256
2
    HANDLE_CODE(bref.align_bytes_zero());
1257
2
  }
1258
2
  return OCUDUASN_SUCCESS;
1259
2
}
1260
1261
static OCUDUASN_CODE
1262
pack_bitfield(bit_ref& bref, const uint8_t* buf, uint32_t nbits, uint32_t lb, uint32_t ub, bool is_aligned)
1263
89.1k
{
1264
89.1k
  if (nbits == 0) {
1265
0
    log_error("Invalid bitstring size={}", nbits);
1266
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
1267
0
  }
1268
89.1k
  if (is_aligned and (lb != ub or ub > 16)) {
1269
2
    bref.align_bytes_zero();
1270
2
  }
1271
89.1k
  uint32_t n_octs = ceil_frac(nbits, 8u);
1272
89.1k
  uint32_t offset = ((nbits - 1) % 8) + 1;
1273
89.1k
  HANDLE_CODE(bref.pack(buf[n_octs - 1], offset));
1274
243k
  for (uint32_t i = 1; i < n_octs; ++i) {
1275
154k
    HANDLE_CODE(bref.pack(buf[n_octs - 1 - i], 8));
1276
154k
  }
1277
89.1k
  return OCUDUASN_SUCCESS;
1278
89.1k
}
1279
1280
/**
1281
 * Pack ASN1 bitstring. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext
1282
 */
1283
OCUDUASN_CODE
1284
pack(bit_ref& bref, const uint8_t* data, uint32_t len, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned)
1285
89.1k
{
1286
89.1k
  HANDLE_CODE(bitstring_utils::pack_length_prefix(bref, len, lb, ub, has_ext, is_aligned));
1287
89.1k
  return pack_bitfield(bref, data, len, lb, ub, is_aligned);
1288
89.1k
}
1289
1290
// Unpack prefix, excluding ext bit
1291
1292
/**
1293
 * Unpack ASN1 bitstring length prefix. Accommodates for cases: fixed/unbounded/bounded, aligned/unaligned, with/out ext
1294
 */
1295
OCUDUASN_CODE
1296
unpack_length_prefix(uint32_t& len, cbit_ref& bref, uint32_t lb, uint32_t ub, bool has_ext, bool is_aligned)
1297
317k
{
1298
317k
  bool ext = false;
1299
317k
  if (has_ext) {
1300
18.0k
    HANDLE_CODE(bref.unpack(ext, 1));
1301
18.0k
  }
1302
1303
  // unbounded or ext is set
1304
317k
  if (ub == std::numeric_limits<uint32_t>::max() or ext) {
1305
5.33k
    return unpack_length(len, bref, is_aligned);
1306
5.33k
  }
1307
1308
  // fixed length with no ext
1309
312k
  if (lb == ub) {
1310
300k
    len = lb;
1311
300k
    return OCUDUASN_SUCCESS;
1312
300k
  }
1313
1314
  // constrained, simple case
1315
11.9k
  HANDLE_CODE(unpack_length(len, bref, lb, ub, is_aligned));
1316
  //  if (is_aligned) {
1317
  //    HANDLE_CODE(bref.align_bytes_zero());
1318
  //  }
1319
  //  uint32_t len_bits = ceilf(log2f(ub - lb));
1320
  //  HANDLE_CODE(bref.unpack(len, len_bits));
1321
  //  len += lb;
1322
11.6k
  return OCUDUASN_SUCCESS;
1323
11.9k
}
1324
1325
// for both fixed, constrained and unconstrained scenarios
1326
OCUDUASN_CODE unpack_bitfield(uint8_t* buf, cbit_ref& bref, uint32_t n, uint32_t lb, uint32_t ub, bool is_aligned)
1327
317k
{
1328
317k
  if (n > ASN_64K) {
1329
0
    log_error("bitstrings longer than 64K not supported");
1330
0
    return OCUDUASN_ERROR_DECODE_FAIL;
1331
0
  }
1332
317k
  if (n == 0) {
1333
    // empty bit string
1334
2.59k
    return OCUDUASN_SUCCESS;
1335
2.59k
  }
1336
314k
  if (is_aligned and (lb != ub or ub > 16)) {
1337
27.0k
    bref.align_bytes();
1338
27.0k
  }
1339
  // unpack exactly "n" bits
1340
314k
  uint32_t n_octs = ceil_frac(n, 8u);
1341
314k
  uint32_t offset = ((n - 1) % 8) + 1;
1342
314k
  HANDLE_CODE(bref.unpack(buf[n_octs - 1], offset));
1343
1.00M
  for (uint32_t i = 1; i < n_octs; ++i) {
1344
692k
    HANDLE_CODE(bref.unpack(buf[n_octs - 1 - i], 8));
1345
692k
  }
1346
311k
  return OCUDUASN_SUCCESS;
1347
313k
}
1348
1349
void from_number(uint8_t* ptr, uint64_t number, uint32_t nbits)
1350
106k
{
1351
106k
  if (nbits > 64u) {
1352
0
    log_error("bitstring of size={} does not fit in an uint64_t", nbits);
1353
0
    return;
1354
0
  }
1355
106k
  uint32_t nof_bytes = ceil_frac(nbits, 8u);
1356
437k
  for (uint32_t i = 0; i < nof_bytes; ++i) {
1357
331k
    ptr[i] = (number >> (i * 8u)) & 0xffu;
1358
331k
  }
1359
106k
  uint32_t offset = nbits % 8; // clean up any extra set bit
1360
106k
  if (offset > 0) {
1361
75.9k
    ptr[nof_bytes - 1] &= (uint8_t)((1u << offset) - 1u);
1362
75.9k
  }
1363
106k
}
1364
1365
std::string to_string(const uint8_t* ptr, uint32_t nbits)
1366
264k
{
1367
264k
  std::string str(nbits, '\0');
1368
7.94M
  for (uint32_t i = 0; i < nbits; ++i) {
1369
7.68M
    str[i] = bitstring_utils::get(ptr, nbits - 1 - i) ? '1' : '0';
1370
7.68M
  }
1371
264k
  return str;
1372
264k
}
1373
1374
uint64_t to_number(const uint8_t* ptr, uint32_t nbits)
1375
95.4k
{
1376
95.4k
  if (nbits > 64u) {
1377
0
    log_error("bitstring of size={} does not fit in an uint64_t", nbits);
1378
0
    return 0;
1379
0
  }
1380
95.4k
  uint64_t val       = 0;
1381
95.4k
  uint32_t nof_bytes = ceil_frac(nbits, 8u);
1382
507k
  for (uint32_t i = 0; i < nof_bytes; ++i) {
1383
412k
    val += static_cast<uint64_t>(ptr[i]) << static_cast<uint64_t>(i * 8u);
1384
412k
  }
1385
95.4k
  return val;
1386
95.4k
}
1387
1388
} // namespace bitstring_utils
1389
1390
/*********************
1391
     choice utils
1392
*********************/
1393
void log_invalid_access_choice_id(uint32_t val, uint32_t choice_id)
1394
0
{
1395
0
  log_error("The access choide id is invalid ({}!={})", (size_t)val, (size_t)choice_id);
1396
0
}
1397
void log_invalid_choice_id(uint32_t val, const char* choice_type)
1398
10.8k
{
1399
10.8k
  log_error("Invalid choice id={} for choice type {}", (size_t)val, choice_type);
1400
10.8k
}
1401
1402
/*********************
1403
   printable string
1404
*********************/
1405
1406
namespace asn_string_utils {
1407
1408
static size_t get_nof_bits_per_char(size_t lb, size_t ub, bool aligned)
1409
2.84k
{
1410
2.84k
  size_t N = ub - lb + 1;
1411
2.84k
  auto   b = (size_t)std::ceil(std::log2(N)); // B
1412
2.84k
  if (aligned) {
1413
2.84k
    b = (size_t)std::pow(2, std::ceil(std::log2(b))); // B2
1414
2.84k
  }
1415
2.84k
  return b;
1416
2.84k
}
1417
1418
static bool is_octet_aligned(size_t bits_per_char, size_t alb, size_t aub, bool aligned)
1419
2.84k
{
1420
2.84k
  size_t max_nof_bits = bits_per_char * aub;
1421
2.84k
  return aligned and (max_nof_bits > 16 or (alb != aub and max_nof_bits == 16));
1422
2.84k
}
1423
1424
static constexpr bool is_length_encoded(size_t alb, size_t aub, bool aligned)
1425
2.84k
{
1426
2.84k
  return alb != aub or aub >= ASN_64K;
1427
2.84k
}
1428
1429
OCUDUASN_CODE
1430
pack(bit_ref& bref, const std::string& s, size_t lb, size_t ub, size_t alb, size_t aub, bool ext, bool aligned)
1431
4
{
1432
4
  bool within_limits = s.size() >= alb and s.size() <= aub;
1433
4
  if (not within_limits) {
1434
    // TODO: print error
1435
    // NOTE: This should be valid for exts
1436
0
    log_error("The PrintableString size={} is not within the limits [{}, {}]", s.size(), alb, aub);
1437
0
    return OCUDUASN_ERROR_ENCODE_FAIL;
1438
0
  }
1439
4
  size_t b              = asn_string_utils::get_nof_bits_per_char(lb, ub, aligned);
1440
4
  bool   octet_aligned  = asn_string_utils::is_octet_aligned(b, alb, aub, aligned);
1441
4
  bool   length_encoded = asn_string_utils::is_length_encoded(alb, aub, aligned);
1442
1443
4
  if (ext) {
1444
4
    HANDLE_CODE(bref.pack(0, 1));
1445
4
  }
1446
4
  if (length_encoded) {
1447
4
    pack_length(bref, s.size(), alb, aub, octet_aligned);
1448
4
  }
1449
4
  if (octet_aligned) {
1450
4
    bref.align_bytes_zero();
1451
4
  }
1452
34
  for (char c : s) {
1453
34
    HANDLE_CODE(bref.pack(c, b));
1454
34
  }
1455
4
  return OCUDUASN_SUCCESS;
1456
4
}
1457
1458
OCUDUASN_CODE
1459
unpack(std::string& s, cbit_ref& bref, size_t lb, size_t ub, size_t alb, size_t aub, bool ext, bool aligned)
1460
2.83k
{
1461
2.83k
  size_t b              = asn_string_utils::get_nof_bits_per_char(lb, ub, aligned);
1462
2.83k
  bool   octet_aligned  = asn_string_utils::is_octet_aligned(b, alb, aub, aligned);
1463
2.83k
  bool   length_encoded = asn_string_utils::is_length_encoded(alb, aub, aligned);
1464
2.83k
  if (ext) {
1465
2.45k
    bool is_ext;
1466
2.45k
    HANDLE_CODE(bref.unpack(is_ext, 1));
1467
2.36k
    if (is_ext) {
1468
46
      log_error("Extension of PrintableString not supported");
1469
46
      return OCUDUASN_ERROR_DECODE_FAIL;
1470
46
    }
1471
2.36k
  }
1472
2.70k
  if (length_encoded) {
1473
2.70k
    size_t n;
1474
2.70k
    unpack_length(n, bref, alb, aub, octet_aligned);
1475
2.70k
    s.resize(n);
1476
2.70k
  }
1477
2.70k
  if (octet_aligned) {
1478
2.70k
    bref.align_bytes();
1479
2.70k
  }
1480
44.9k
  for (char& c : s) {
1481
44.9k
    HANDLE_CODE(bref.unpack(c, b));
1482
44.9k
  }
1483
2.28k
  return OCUDUASN_SUCCESS;
1484
2.70k
}
1485
1486
} // namespace asn_string_utils
1487
1488
/*********************
1489
      ext group
1490
*********************/
1491
1492
bool& ext_groups_packer_guard::operator[](uint32_t idx)
1493
0
{
1494
0
  if (idx >= groups.size()) {
1495
0
    uint32_t prev_size = groups.size();
1496
0
    groups.resize(idx + 1);
1497
0
    std::fill(&groups[prev_size], &groups[groups.size()], false);
1498
0
  }
1499
0
  return groups[idx];
1500
0
}
1501
1502
OCUDUASN_CODE ext_groups_packer_guard::pack(asn1::bit_ref& bref) const
1503
0
{
1504
  // pack number of groups
1505
0
  int32_t i = groups.size() - 1;
1506
0
  for (; i >= 0; --i) {
1507
0
    if (groups[i]) {
1508
0
      break;
1509
0
    }
1510
0
  }
1511
0
  uint32_t nof_groups = (uint32_t)i + 1u;
1512
0
  HANDLE_CODE(pack_norm_small_non_neg_whole_number(bref, nof_groups - 1));
1513
1514
  // pack each group presence flag
1515
0
  for (uint32_t j = 0; j < nof_groups; ++j) {
1516
0
    HANDLE_CODE(bref.pack(groups[j], 1));
1517
0
  }
1518
0
  return OCUDUASN_SUCCESS;
1519
0
}
1520
1521
ext_groups_unpacker_guard::ext_groups_unpacker_guard(uint32_t nof_supported_groups_) :
1522
0
  nof_supported_groups(nof_supported_groups_)
1523
0
{
1524
0
  resize(nof_supported_groups);
1525
0
}
1526
1527
bool& ext_groups_unpacker_guard::operator[](uint32_t idx)
1528
0
{
1529
0
  if (idx >= groups.size()) {
1530
    // only resizes for unknown extensions
1531
0
    resize(idx + 1);
1532
0
  }
1533
0
  return groups[idx];
1534
0
}
1535
1536
void ext_groups_unpacker_guard::resize(uint32_t new_size)
1537
0
{
1538
  // always grows
1539
0
  uint32_t prev_size = groups.size();
1540
0
  groups.resize(std::max(new_size, nof_supported_groups));
1541
0
  std::fill(&groups[prev_size], &groups[groups.size()], false);
1542
0
}
1543
1544
ext_groups_unpacker_guard::~ext_groups_unpacker_guard()
1545
0
{
1546
  // consume all the unknown extensions
1547
0
  for (uint32_t i = nof_supported_groups; i < nof_unpacked_groups; ++i) {
1548
0
    if (groups[i]) {
1549
0
      varlength_field_unpack_guard scope(*bref_tracker);
1550
0
    }
1551
0
  }
1552
0
}
1553
1554
OCUDUASN_CODE ext_groups_unpacker_guard::unpack(cbit_ref& bref)
1555
0
{
1556
0
  bref_tracker = &bref;
1557
  // unpack nof of ext groups
1558
0
  uint32_t nof_ext_groups = 0;
1559
0
  HANDLE_CODE(unpack_norm_small_non_neg_whole_number(nof_ext_groups, bref));
1560
0
  nof_unpacked_groups += nof_ext_groups + 1;
1561
0
  resize(nof_unpacked_groups);
1562
1563
  // unpack each group presence flag
1564
0
  for (uint32_t i = 0; i < nof_unpacked_groups; ++i) {
1565
0
    HANDLE_CODE(bref.unpack(groups[i], 1));
1566
0
  }
1567
0
  return OCUDUASN_SUCCESS;
1568
0
}
1569
1570
ext_groups_unpacker::ext_groups_unpacker(cbit_ref& bref, bool aligned_) :
1571
41.4k
  aligned(aligned_), outer_bref(bref), group_bref({})
1572
41.4k
{
1573
41.4k
}
1574
1575
OCUDUASN_CODE ext_groups_unpacker::unpack_presence_flags()
1576
41.4k
{
1577
  // unpack nof of ext groups
1578
41.4k
  uint32_t nof_ext_groups = 0;
1579
41.4k
  HANDLE_CODE(unpack_norm_small_non_neg_whole_number(nof_ext_groups, outer_bref));
1580
41.3k
  nof_unpacked_groups = nof_ext_groups + 1;
1581
1582
  // Resize presence flags vector
1583
41.3k
  groups.resize(nof_unpacked_groups);
1584
41.3k
  std::fill(groups.data(), groups.data() + nof_unpacked_groups, false);
1585
1586
  // unpack each group presence flag
1587
254k
  for (uint32_t i = 0; i < nof_unpacked_groups; ++i) {
1588
213k
    HANDLE_CODE(outer_bref.unpack(groups[i], 1));
1589
213k
  }
1590
1591
41.2k
  return OCUDUASN_SUCCESS;
1592
41.3k
}
1593
1594
OCUDUASN_CODE ext_groups_unpacker::unpack_next_group()
1595
233k
{
1596
233k
  if (state == state_t::unpack_presence_flags) {
1597
41.4k
    state = state_t::unpack_groups;
1598
41.4k
    HANDLE_CODE(unpack_presence_flags());
1599
41.4k
  }
1600
1601
233k
  if (next_group_idx >= nof_unpacked_groups) {
1602
28.6k
    state = state_t::done;
1603
28.6k
    return OCUDUASN_SUCCESS;
1604
28.6k
  }
1605
1606
204k
  if (groups[next_group_idx++]) {
1607
    // Group is present. Decode its length.
1608
63.7k
    uint32_t group_len;
1609
63.7k
    HANDLE_CODE(unpack_length(group_len, outer_bref, aligned));
1610
    // Create subview for the group
1611
63.4k
    group_bref = outer_bref.subview(0, group_len);
1612
    // Consume the padding bits of the group from the outer bitref
1613
63.4k
    HANDLE_CODE(outer_bref.advance_bytes(group_len));
1614
63.4k
  }
1615
1616
204k
  return OCUDUASN_SUCCESS;
1617
204k
}
1618
1619
OCUDUASN_CODE ext_groups_unpacker::consume_remaining_groups(cbit_ref& bref)
1620
39.9k
{
1621
169k
  while (next_group_idx < nof_unpacked_groups) {
1622
129k
    HANDLE_CODE(unpack_next_group());
1623
129k
  }
1624
39.8k
  bref = outer_bref;
1625
39.8k
  return OCUDUASN_SUCCESS;
1626
39.9k
}
1627
1628
/*********************
1629
     Open Field
1630
*********************/
1631
1632
58
varlength_field_pack_guard::varlength_field_pack_guard(bit_ref& bref, bool align_) : brefstart(bref)
1633
58
{
1634
58
  bref         = bit_ref(varlen_buffer);
1635
58
  bref_tracker = &bref;
1636
58
  align        = align_;
1637
58
}
1638
1639
varlength_field_pack_guard::~varlength_field_pack_guard()
1640
58
{
1641
  // fill the spare bits
1642
58
  uint32_t leftover = 7U - ((bref_tracker->distance() - (uint32_t)1U) % (uint32_t)8U);
1643
58
  bref_tracker->pack(0, leftover);
1644
1645
  // check how many bytes were written in total
1646
58
  uint32_t nof_bytes = bref_tracker->distance() / (uint32_t)8U;
1647
1648
  // go back in time to pack length
1649
58
  pack_length(brefstart, nof_bytes, align);
1650
1651
  // pack encoded bytes
1652
58
  brefstart.pack_bytes(varlen_buffer);
1653
58
  *bref_tracker = brefstart;
1654
58
}
1655
1656
270k
varlength_field_unpack_guard::varlength_field_unpack_guard(cbit_ref& bref, bool align) : bref0(bref)
1657
270k
{
1658
270k
  if (unpack_length(len, bref, align) != OCUDUASN_SUCCESS) {
1659
    // The length could not be decoded, e.g. due to a truncated buffer. Leave an empty view, so that unpacking the field
1660
    // contents fails, and do not restore the caller's bit_ref on destruction.
1661
9.90k
    len  = 0;
1662
9.90k
    bref = cbit_ref(ocudu::byte_buffer_view{});
1663
9.90k
    return;
1664
9.90k
  }
1665
260k
  bref0        = bref;
1666
260k
  bref_tracker = &bref;
1667
260k
  bref         = bref.subview(0, len);
1668
260k
}
1669
1670
varlength_field_unpack_guard::~varlength_field_unpack_guard()
1671
270k
{
1672
270k
  if (bref_tracker == nullptr) {
1673
9.90k
    return;
1674
9.90k
  }
1675
260k
  if (len * 8 < (unsigned)bref_tracker->distance(bref0)) {
1676
6.42k
    log_error("The number of bits unpacked exceeds the variable length field size ({} > {})",
1677
6.42k
              bref_tracker->distance(bref0),
1678
6.42k
              len * 8);
1679
6.42k
    return;
1680
6.42k
  }
1681
1682
  // Ignore padding bits, and skip to the end of the varlength field.
1683
254k
  bref0.advance_bytes(len);
1684
254k
  *bref_tracker = bref0;
1685
254k
}
1686
1687
/*******************
1688
    JsonWriter
1689
*******************/
1690
1691
259k
json_writer::json_writer() : ident(""), sep(NONE) {}
1692
1693
void json_writer::write_fieldname(const char* fieldname)
1694
22.6M
{
1695
22.6M
  static constexpr const char* septable[] = {",\n", "\n", ""};
1696
1697
22.6M
  fmt::format_to(std::back_inserter(buffer), "{}{}", septable[sep], sep != NONE ? ident : "");
1698
22.6M
  if (strlen(fieldname) != 0) {
1699
14.1M
    fmt::format_to(std::back_inserter(buffer), "\"{}\": ", fieldname);
1700
14.1M
  }
1701
22.6M
  sep = NONE;
1702
22.6M
}
1703
1704
void json_writer::write_str(const char* fieldname, const char* value)
1705
2.46M
{
1706
2.46M
  write_fieldname(fieldname);
1707
2.46M
  fmt::format_to(std::back_inserter(buffer), "\"{}\"", value);
1708
2.46M
  sep = COMMA;
1709
2.46M
}
1710
1711
void json_writer::write_str(const char* fieldname, const std::string& value)
1712
470k
{
1713
470k
  write_str(fieldname, value.c_str());
1714
470k
}
1715
1716
void json_writer::write_str(const char* value)
1717
9.12k
{
1718
9.12k
  write_str("", value);
1719
9.12k
}
1720
1721
void json_writer::write_str(const std::string& value)
1722
2.96k
{
1723
2.96k
  write_str("", value);
1724
2.96k
}
1725
1726
void json_writer::write_int(const char* fieldname, int64_t value)
1727
6.35M
{
1728
6.35M
  write_fieldname(fieldname);
1729
6.35M
  fmt::format_to(std::back_inserter(buffer), "{}", value);
1730
6.35M
  sep = COMMA;
1731
6.35M
}
1732
void json_writer::write_int(int64_t value)
1733
424k
{
1734
424k
  write_int("", value);
1735
424k
}
1736
1737
void json_writer::write_bool(const char* fieldname, bool value)
1738
258k
{
1739
258k
  write_fieldname(fieldname);
1740
258k
  fmt::format_to(std::back_inserter(buffer), "{}", value ? "true" : "false");
1741
258k
  sep = COMMA;
1742
258k
}
1743
void json_writer::write_bool(bool value)
1744
0
{
1745
0
  write_bool("", value);
1746
0
}
1747
1748
void json_writer::write_float(const char* fieldname, float value)
1749
0
{
1750
0
  write_fieldname(fieldname);
1751
0
  fmt::format_to(std::back_inserter(buffer), "{}", value);
1752
0
  sep = COMMA;
1753
0
}
1754
1755
void json_writer::write_float(float value)
1756
0
{
1757
0
  write_float("", value);
1758
0
}
1759
void json_writer::write_null(const char* fieldname)
1760
0
{
1761
0
  write_fieldname(fieldname);
1762
0
  fmt::format_to(std::back_inserter(buffer), "null");
1763
0
  sep = COMMA;
1764
0
}
1765
void json_writer::write_null()
1766
0
{
1767
0
  write_null("");
1768
0
}
1769
1770
void json_writer::start_obj(const char* fieldname)
1771
8.08M
{
1772
8.08M
  write_fieldname(fieldname);
1773
8.08M
  fmt::format_to(std::back_inserter(buffer), "{{");
1774
8.08M
  ident += "  ";
1775
8.08M
  sep = NEWLINE;
1776
8.08M
}
1777
void json_writer::end_obj()
1778
8.08M
{
1779
8.08M
  ident.erase(ident.size() - 2, 2);
1780
8.08M
  fmt::format_to(std::back_inserter(buffer), "\n{}}}", ident);
1781
8.08M
  sep = COMMA;
1782
8.08M
}
1783
1784
void json_writer::start_array(const char* fieldname)
1785
1.00M
{
1786
1.00M
  write_fieldname(fieldname);
1787
1.00M
  fmt::format_to(std::back_inserter(buffer), "[");
1788
1.00M
  ident += "  ";
1789
1.00M
  sep = NEWLINE;
1790
1.00M
}
1791
void json_writer::end_array()
1792
1.00M
{
1793
1.00M
  ident.erase(ident.size() - 2, 2);
1794
1.00M
  fmt::format_to(std::back_inserter(buffer), "\n{}]", ident);
1795
1.00M
  sep = COMMA;
1796
1.00M
}
1797
1798
std::string json_writer::to_string() const
1799
259k
{
1800
259k
  return std::string(buffer.data(), buffer.size());
1801
259k
}
1802
1803
/************************
1804
   General Layer Types
1805
************************/
1806
1807
uint32_t detail::base_empty_obj_set::idx_to_id(uint32_t idx)
1808
18.1k
{
1809
18.1k
  asn1::log_error("object set is empty\n");
1810
18.1k
  return 0;
1811
18.1k
}
1812
bool detail::base_empty_obj_set::is_id_valid(const uint32_t& id)
1813
0
{
1814
0
  asn1::log_error("object set is empty\n");
1815
0
  return false;
1816
0
}
1817
crit_e detail::base_empty_obj_set::get_crit(const uint32_t& id)
1818
15.0k
{
1819
15.0k
  return {};
1820
15.0k
}
1821
presence_e detail::base_empty_obj_set::get_presence(const uint32_t& id)
1822
0
{
1823
0
  return {};
1824
0
}
1825
1826
void detail::empty_obj_set_item_c::to_json(json_writer& j) const
1827
3.14k
{
1828
3.14k
  j.start_obj();
1829
3.14k
  j.end_obj();
1830
3.14k
}
1831
OCUDUASN_CODE detail::empty_obj_set_item_c::pack(bit_ref& bref) const
1832
0
{
1833
0
  varlength_field_pack_guard varlen_scope(bref, true);
1834
0
  return OCUDUASN_SUCCESS;
1835
0
}
1836
OCUDUASN_CODE detail::empty_obj_set_item_c::unpack(cbit_ref& bref)
1837
11.3k
{
1838
11.3k
  varlength_field_unpack_guard varlen_scope(bref, true);
1839
11.3k
  return OCUDUASN_SUCCESS;
1840
11.3k
}
1841
1842
const char* detail::empty_obj_set_item_c::types_opts::to_string() const
1843
0
{
1844
0
  log_error("The enum value=0 of type protocol_ies_empty_o::value_c::types is not valid.");
1845
0
  return "";
1846
0
}
1847
1848
OCUDUASN_CODE pack_unconstrained_real(bit_ref& bref, float n, bool aligned)
1849
0
{
1850
0
  if (aligned) {
1851
0
    HANDLE_CODE(bref.align_bytes_zero());
1852
0
  }
1853
1854
  // Handle special cases
1855
0
  if (std::isinf(n)) {
1856
0
    pack_length(bref, 1, aligned);
1857
0
    bref.pack(n > 0 ? 0x40 : 0x41, 8);
1858
0
    return OCUDUASN_SUCCESS;
1859
0
  } else if (std::isnan(n)) {
1860
0
    pack_length(bref, 1, aligned);
1861
0
    bref.pack(0x42, 8);
1862
0
    return OCUDUASN_SUCCESS;
1863
0
  } else if (n == 0.0f) {
1864
0
    pack_length(bref, 0, aligned);
1865
0
    return OCUDUASN_SUCCESS;
1866
0
  }
1867
1868
0
  uint32_t* bits_ptr = (uint32_t*)&n;
1869
0
  uint32_t  bits     = *bits_ptr;
1870
0
  bool      sign     = (bits >> 31) & 0x1;
1871
0
  int8_t    exponent = ((bits >> 23) & 0xff);
1872
0
  uint32_t  mantissa = (bits & 0x7fffff) | 0x800000;
1873
1874
0
  uint8_t info_octet = 0x80; // Base-2
1875
0
  if (sign) {
1876
0
    info_octet |= 0x1 << 6;
1877
0
  }
1878
1879
0
  uint32_t trailing_zeros = ocudu::zero_lsb_count<unsigned>(mantissa);
1880
0
  mantissa >>= trailing_zeros;
1881
  // the inverse of the trailing zeros gives the number of bits to shift
1882
  // the mantissa to the right to make it a whole number, this number must be added to the exponent
1883
0
  uint8_t inv_trailing_zeros = 23 - trailing_zeros;
1884
0
  exponent -= (127 + inv_trailing_zeros);
1885
0
  uint8_t asn1_exponent = exponent & 0xff;
1886
1887
0
  uint8_t mantissa_bit_len = 23 + 1 - trailing_zeros;
1888
0
  uint8_t mantissa_oct_len = (mantissa_bit_len + 7) / 8;
1889
1890
0
  uint32_t len = mantissa_oct_len + 2;
1891
0
  pack_length(bref, len, aligned);
1892
0
  bref.pack(info_octet, 8);
1893
0
  bref.pack(asn1_exponent, 8);
1894
0
  for (int8_t i = mantissa_oct_len - 1; i >= 0; --i) {
1895
0
    uint8_t octet = (mantissa >> (i * 8)) & 0xff;
1896
0
    bref.pack(octet, 8);
1897
0
  }
1898
0
  return OCUDUASN_SUCCESS;
1899
0
}
1900
1901
OCUDUASN_CODE unpack_unconstrained_real(float& n, cbit_ref& bref, bool aligned)
1902
0
{
1903
0
  if (aligned) {
1904
0
    HANDLE_CODE(bref.align_bytes());
1905
0
  }
1906
0
  uint32_t len;
1907
0
  HANDLE_CODE(unpack_length(len, bref, aligned));
1908
1909
  // Handle special case 0
1910
0
  if (len == 0) {
1911
0
    n = 0;
1912
0
    return OCUDUASN_SUCCESS;
1913
0
  }
1914
1915
0
  if (len == 2) {
1916
0
    return OCUDUASN_ERROR_DECODE_FAIL;
1917
0
  }
1918
1919
0
  uint8_t buf[10];
1920
0
  if (len > sizeof(buf)) {
1921
0
    asn1::log_error("REAL length {} exceeds maximum supported size {}", len, sizeof(buf));
1922
0
    return OCUDUASN_ERROR_DECODE_FAIL;
1923
0
  }
1924
0
  for (uint32_t i = 0; i < len; i++) {
1925
0
    HANDLE_CODE(bref.unpack(buf[i], 8));
1926
0
  }
1927
1928
0
  uint8_t info_octet = buf[0];
1929
1930
  // Handle special cases
1931
0
  if (info_octet == 0x40) {
1932
0
    n = std::numeric_limits<float>::infinity(); // Positive infinity
1933
0
    return OCUDUASN_SUCCESS;
1934
0
  } else if (info_octet == 0x41) {
1935
0
    n = -std::numeric_limits<float>::infinity(); // Negative infinity
1936
0
    return OCUDUASN_SUCCESS;
1937
0
  } else if (info_octet == 0x42) {
1938
0
    n = std::numeric_limits<float>::quiet_NaN(); // NaN
1939
0
    return OCUDUASN_SUCCESS;
1940
0
  }
1941
1942
0
  uint8_t exponent_length = (info_octet & 0x3) + 1;
1943
0
  uint8_t mantissa_length = len - exponent_length - 1;
1944
0
  if (exponent_length != 1) {
1945
    // Currently we support decoding only float with 1 byte exponent.
1946
0
    return OCUDUASN_ERROR_DECODE_FAIL;
1947
0
  }
1948
0
  if (mantissa_length > 3) {
1949
    // Currently we support decoding only float with 3 byte mantissa.
1950
0
    return OCUDUASN_ERROR_DECODE_FAIL;
1951
0
  }
1952
1953
0
  bool     sign          = (info_octet >> 6) & 0x1;
1954
0
  int8_t   asn1_exponent = static_cast<int8_t>(buf[1]);
1955
0
  uint32_t mantissa      = 0;
1956
1957
0
  for (size_t i = 2; i < len; ++i) {
1958
0
    mantissa = (mantissa << 8) | buf[i];
1959
0
  }
1960
0
  uint8_t leading_zeros = ocudu::zero_msb_count<unsigned>(mantissa) - 8;
1961
0
  mantissa <<= leading_zeros;
1962
1963
  // Build the IEEE 754 float value from the sign, exponent, and mantissa
1964
0
  uint32_t ieee_exponent = asn1_exponent + 127;
1965
0
  uint32_t ieee_mantissa = mantissa & 0x7fffff;
1966
1967
0
  if (ieee_mantissa) {
1968
0
    ieee_exponent += (23 - leading_zeros);
1969
0
  }
1970
1971
0
  uint32_t ieee_bits = (sign << 31) | (ieee_exponent << 23) | ieee_mantissa;
1972
0
  float*   bits_ptr  = (float*)&ieee_bits;
1973
0
  n                  = *bits_ptr;
1974
0
  return OCUDUASN_SUCCESS;
1975
0
}
1976
1977
} // namespace asn1