Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / ostring.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 #include "asn/per/common.hpp"
25
26 namespace asn {
27 namespace per {
28
29 template < class IE, class Enable = void>
30 struct Octetstring;
31
32 //16.8 Default
33 template <class IE, class Enabler = void>
34 struct OctetstringNoExt
35 {
36         static void inline run(IE const& ie, EncoderCtx& ctx)
37         {
38                 bound_t size = ie.get().size();
39                 LengthDeterminant<typename IE::constraint_t>::run(ctx, size);
40                 Tools::bit_accessor::padByte(ctx.refBuffer());
41                 ctx.refBuffer().putBytes(ie.get().data(), size);
42         }
43         static void inline run(IE& ie, DecoderCtx& ctx)
44         {
45                 size_t len = LengthDeterminant<typename IE::constraint_t>::run(ctx, false);
46                 Tools::bit_accessor::padByte(ctx.refBuffer());
47                 u8 const* data_in = ctx.refBuffer().getBytes(len);
48                 
49                 if (data_in)
50                 {
51                         ie.set(len, data_in);
52                 }
53
54         }
55 };
56
57 //16.5 Zero length
58 template <class IE>
59 struct OctetstringNoExt<IE, std::enable_if_t< (IE::constraint_t::upper_bound == 0)> >
60 {
61         static void inline run(IE const& ie, EncoderCtx& ctx) {/* do nothing */ }
62         static void inline run(IE& ie, DecoderCtx& ctx) { ie.setpresent(true); }
63 };
64
65 //16.6 Up to two octets, fixed length
66 template <class IE>
67 struct OctetstringNoExt<IE, std::enable_if_t<
68         ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound == 1))
69 >>
70 {
71         static void inline run(IE const& ie, EncoderCtx& ctx)
72         {
73                 Tools::bit_accessor::put(static_cast<u8>(ie.get().data()[0]), 8, ctx.refBuffer());
74         }
75         static void inline run(IE& ie, DecoderCtx& ctx)
76         {
77                 u8 data_in = Tools::bit_accessor::get(8, ctx.refBuffer());
78                 u8* data_out = ctx.refAllocator().alloc_bytes(1);
79                 if (data_out) {
80                         data_out[0] = data_in;
81                         ie.set(1, data_out);
82                 }
83                 else
84                         ctx.refErrorCtx().allocatorNoMem(0, 1);
85         }
86 };
87
88 template <class IE>
89 struct OctetstringNoExt<IE, std::enable_if_t<
90         ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound == 2))
91 >>
92 {
93         static void inline run(IE const& ie, EncoderCtx& ctx)
94         {
95                 Tools::bit_accessor::put(static_cast<u8>(ie.get().data()[0]), 8, ctx.refBuffer());
96                 Tools::bit_accessor::put(static_cast<u8>(ie.get().data()[1]), 8, ctx.refBuffer());
97         }
98         static void inline run(IE& ie, DecoderCtx& ctx)
99         {
100                 u8 data_in[2];
101                 data_in[0] = Tools::bit_accessor::get(8, ctx.refBuffer());
102                 data_in[1] = Tools::bit_accessor::get(8, ctx.refBuffer());
103                 u8* data_out = ctx.refAllocator().alloc_bytes(sizeof(data_in));
104                 if (data_out) {
105                         data_out[0] = data_in[0];
106                         data_out[1] = data_in[1];
107                         ie.set(sizeof(data_in), data_out);
108                 }
109                 else
110                         ctx.refErrorCtx().allocatorNoMem(0, sizeof(data_in));
111         }
112 };
113
114 //16.7 More than 2 octets, up to 64K, fixed length
115 template <class IE>
116 struct OctetstringNoExt<IE, std::enable_if_t<
117         ((IE::constraint_t::upper_bound == IE::constraint_t::lower_bound) && (IE::constraint_t::upper_bound < 65536) && (IE::constraint_t::upper_bound > 2))
118 >>
119 {
120         static void inline run(IE const& ie, EncoderCtx& ctx)
121         {
122                 Tools::bit_accessor::padByte(ctx.refBuffer());
123                 ctx.refBuffer().putBytes(ie.get().data(), ie.get().size());
124         }
125         static void inline run(IE& ie, DecoderCtx& ctx)
126         {
127                 Tools::bit_accessor::padByte(ctx.refBuffer());
128                 const size_t len = (size_t)IE::constraint_t::upper_bound;
129                 u8 const* data_in = ctx.refBuffer().getBytes(len);
130                 if (data_in)
131                 {
132                         ie.set(len, data_in);
133                 }
134         }
135 };
136
137 /**************************************************/
138
139 //16.3 : Extension present
140 template <class IE>
141 struct Octetstring<IE, std::enable_if_t<(IE::constraint_t::extended == true)> >
142 {
143         static void inline run(IE const& ie, EncoderCtx& ctx)
144         {
145                 bound_t size = ie.get().size();
146                 if (size <= IE::constraint_t::upper_bound && size >= IE::constraint_t::lower_bound)
147                 {
148                         Tools::bit_accessor::put(0, 1, ctx.refBuffer());
149                         OctetstringNoExt<IE>::run(ie, ctx);
150                 }
151                 else
152                 {
153                         Tools::bit_accessor::put(1, 1, ctx.refBuffer());
154                         Tools::bit_accessor::padByte(ctx.refBuffer());
155                         LengthDeterminant<typename IE::constraint_t>::run(ctx, size);
156                         Tools::bit_accessor::padByte(ctx.refBuffer());
157                         ctx.refBuffer().putBytes(ie.get().data(), size);
158                 }
159         }
160         static void inline run(IE& ie, DecoderCtx& ctx)
161         {
162                 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
163                 if (ext)
164                 {
165                         Tools::bit_accessor::padByte(ctx.refBuffer());
166                         size_t len = LengthDeterminant<typename IE::constraint_t>::run(ctx, true);
167                         Tools::bit_accessor::padByte(ctx.refBuffer());
168                         u8 const* data_in = ctx.refBuffer().getBytes(len);
169                         if (data_in)
170                         {
171                                 ie.set(len, data_in);
172                         }
173                 }
174                 else
175                         OctetstringNoExt<IE>::run(ie, ctx);
176         }
177 };
178
179 //16.4 : No extension
180 template <class IE>
181 struct Octetstring<IE, std::enable_if_t<(IE::constraint_t::extended == false)> >
182 {
183         static void inline run(IE const& ie, EncoderCtx& ctx)
184         {
185                 if ( ie.get().size() > size_t(IE::constraint_t::upper_bound) ||
186                          (IE::constraint_t::lower_bound >= 0 && ie.get().size() < size_t(IE::constraint_t::lower_bound)))
187                 {
188                         ctx.refErrorCtx().sizeRangeError(ie.get().size(), size_t(IE::constraint_t::lower_bound),
189                                                                                          size_t(IE::constraint_t::upper_bound));
190                 }
191                 else
192                 {
193                         OctetstringNoExt<IE>::run(ie, ctx);
194                 }
195         }
196         static void inline run(IE& ie, DecoderCtx& ctx)
197         {
198                 OctetstringNoExt<IE>::run(ie, ctx);
199                 if ( ie.get().size() > size_t(IE::constraint_t::upper_bound) ||
200                          (IE::constraint_t::lower_bound >= 0 && ie.get().size() < size_t(IE::constraint_t::lower_bound)))
201                 {
202                         ctx.refErrorCtx().sizeRangeError(ie.get().size(), size_t(IE::constraint_t::lower_bound),
203                                                                                          size_t(IE::constraint_t::upper_bound));
204                 }
205         }
206 };
207
208 } //namespace per
209 } //namespace asn