Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / ber / length.hpp
1 #pragma once
2 /******************************************************************************
3 *
4 *   Copyright (c) 2019 AT&T Intellectual Property.
5 *   Copyright (c) 2018-2019 Nokia.
6 *
7 *   Licensed under the Apache License, Version 2.0 (the "License");
8 *   you may not use this file except in compliance with the License.
9 *   You may obtain a copy of the License at
10 *
11 *       http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *   Unless required by applicable law or agreed to in writing, software
14 *   distributed under the License is distributed on an "AS IS" BASIS,
15 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *   See the License for the specific language governing permissions and
17 *   limitations under the License.
18 *
19 ******************************************************************************/
20
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
22
23 // Local Includes: Application specific classes, functions, and libraries
24
25 namespace asn {
26 namespace ber {
27
28 constexpr size_t indefinite_length = std::numeric_limits<size_t>::max();
29
30 /***************************************************************************************
31 * Length
32 ***************************************************************************************/
33 struct Length
34 {
35         static size_t inline get(int64_t value)
36         {
37                 size_t length = 1;
38                 
39                 if(value != 0)
40                 {
41                         size_t extra_sign_bits = __builtin_clrsbll(value);
42                         length  = sizeof(value) - (extra_sign_bits >> 3) ;
43                 }
44                 
45                 return length;
46         }
47         
48         static void inline encode(size_t length, EncoderCtx& ctx)
49         {
50                 auto & buffer = ctx.refBuffer();
51                 
52                 if(length <= 0x7F)
53                 {
54                         buffer.putByte(static_cast<uint8_t>(length));
55                 }
56                 else
57                 {
58                         size_t lenlen = get(length);
59                         if(lenlen > 0x7F)
60                         {
61                                 ctx.refErrorCtx().sizeRangeError(length, 0, 0x7F);
62                         }
63                         else
64                         {
65                                 uint8_t bt = static_cast<uint8_t>(lenlen);
66                                 bt |= 0x80;
67                                 buffer.putByte(bt);
68                                 Tools::put_bytes(length, lenlen, ctx);
69                         }
70                 }
71
72         }
73         
74         static size_t inline decode(DecoderCtx& ctx)
75         {
76                 auto & buffer = ctx.refBuffer();
77                 size_t length = 0;
78                 
79                 uint8_t const* data = buffer.getBytes(1);
80                 
81                 if(data)
82                 {
83                         if(!(data[0] & 0x80))
84                         {
85                                 length = data[0];
86                         }
87                         else
88                         {
89                                 size_t lenlen = data[0] & 0x7F;
90                                 
91                                 if(lenlen)
92                                         Tools::get_bytes(length, lenlen, ctx);
93                                 else
94                                         length = indefinite_length;
95                         }
96                 }
97                 
98                 return length;
99         }
100 };
101
102 } //namespace ber
103 } //namespace asn