2 /******************************************************************************
4 * Copyright (c) 2019 AT&T Intellectual Property.
5 * Copyright (c) 2018-2019 Nokia.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************************/
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 // Local Includes: Application specific classes, functions, and libraries
24 #include "asn/per/common.hpp"
25 #include "asn/per/visitor.hpp"
30 /******************************************************************
32 *****************************************************************/
33 template <class Container, typename IE, class Enabler = void>
36 static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
38 Element<IE, IE::ie_type>::run(ie, ctx);
41 static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
43 Element<IE, IE::ie_type>::run(ie, ctx);
46 template <class Container, typename IE>
47 struct Adapter<Container, IE, std::enable_if_t< (IE::ie_type == element_type::T_OBJFIELD_FTV) >>
49 static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
51 VisitorEncoder v(ctx);
52 bool rv = ie.encode(v, cont);
53 if(!rv && static_cast<bool>(ctx))
55 ctx.refErrorCtx().errorNoObject(Container::name());
59 static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
61 VisitorDecoder v(ctx);
62 bool rv = ie.decode(v, cont);
63 if(!rv && static_cast<bool>(ctx))
65 ctx.refErrorCtx().errorNoObject(Container::name());
69 template <class Container, typename IE>
70 struct Adapter<Container, IE, std::enable_if_t< (IE::ie_type == element_type::T_OBJFIELD_TF)> >
72 static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
74 OpenTypeVisitorEncoder v(ctx);
75 bool rv = ie.encode(v, cont);
76 if(!rv && static_cast<bool>(ctx))
78 ctx.refErrorCtx().errorNoObject(Container::name());
82 static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont)
84 OpenTypeVisitorDecoder v(ctx);
85 bool rv = ie.decode(v, cont);
86 if(!rv && static_cast<bool>(ctx))
88 ctx.refErrorCtx().errorNoObject(Container::name());
90 if(ie.is_unknown()) //skip the unknown Open Type
92 size_t size = LengthDeterminantDefault::run(ctx);
93 DecoderCtx::buf_type& buffer = ctx.refBuffer();
94 if (buffer.getBytesLeft() < size)
95 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
102 /******************************************************************
104 *****************************************************************/
105 template <class Container>
108 RootEncoder(EncoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
110 template <typename IE>
111 bool operator() (IE const& ie) const
115 if(IE::optional && !ie.is_valid())
116 return static_cast<bool>(m_ctx);
117 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
119 return static_cast<bool>(m_ctx);
122 Container const& m_cont;
125 /******************************************************************
127 *****************************************************************/
128 template <class Container>
131 RootDecoder(DecoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
133 template <typename IE>
134 bool operator() (IE& ie) const
143 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
146 ie.setpresent(false);
150 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
153 return static_cast<bool>(m_ctx);
156 Container const& m_cont;
159 /******************************************************************
161 *****************************************************************/
162 template <class Container>
165 explicit ExtEncoder(EncoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
167 template <typename IE>
168 bool operator() (IE const& ie) const
171 return static_cast<bool>(m_ctx);
173 if(IE::optional && !ie.is_valid())
174 return static_cast<bool>(m_ctx);
176 size_t reserved_size = 1; //1 byte length is most likely
177 Tools::bit_accessor::padByte(m_ctx.refBuffer());
179 if (m_ctx.refBuffer().getBytesLeft())
181 EncoderCtx::buf_type::pointer p = m_ctx.refBuffer().advance(reserved_size);
182 EncoderCtx::buf_type::pointer start = p + reserved_size;
184 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
188 Tools::bit_accessor::padByte(m_ctx.refBuffer());
189 EncoderCtx::buf_type::pointer p_new = m_ctx.refBuffer().begin();
190 size_t size = p_new - start;
191 size_t needed = LengthDeterminantDefault::bytes_needed(size) - reserved_size;
192 if (needed) //1 byte is not enough for the length determinant. it is hardly possible
194 if (m_ctx.refBuffer().getBytesLeft() < needed) {
195 m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), needed);
198 memmove(start + needed, start, size);
201 m_ctx.refBuffer().set_begin(p, 0);
202 LengthDeterminantDefault::run(m_ctx, size);
204 m_ctx.refBuffer().set_begin(p_new, 0);
205 Tools::bit_accessor::padByte(m_ctx.refBuffer());
211 m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), reserved_size);
214 return static_cast<bool>(m_ctx);
217 Container const& m_cont;
220 /******************************************************************
222 *****************************************************************/
223 template <class Container>
226 explicit ExtDecoder(DecoderCtx& ctx, Container const& cont) : m_ctx(ctx), m_cont(cont) {}
228 template <typename IE>
229 bool operator() (IE& ie) const
232 return static_cast<bool>(m_ctx);
237 size_t size = LengthDeterminantDefault::run(m_ctx);
238 DecoderCtx::buf_type& buffer = m_ctx.refBuffer();
239 if (buffer.getBytesLeft() < size)
241 m_ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
244 DecoderCtx::buf_type::pointer end = buffer.end();
245 buffer.set_end(buffer.begin() + size);
246 Adapter<Container, IE>::run(ie, m_ctx, m_cont);
247 Tools::bit_accessor::padByte(m_ctx.refBuffer());
252 ie.setpresent(false);
255 return static_cast<bool>(m_ctx);
258 Container const& m_cont;
261 /******************************************************************
263 *****************************************************************/
264 template<class IE, class Enabler = void>
269 struct SeqMap<IE, std::enable_if_t< (IE::num_opt_entries > 8) > >
271 static void inline run(EncoderCtx& ctx, size_t val)
273 u8 k = IE::num_opt_entries / 8; // num of full bytes in a seq map mask
274 u8 fb_bits = IE::num_opt_entries % 8; // num of first byte bits (without padding)
277 // Put a part of a first byte (without padding, only seq map own bits)
278 Tools::bit_accessor::put((u8)(val >> 8*k), fb_bits, ctx.refBuffer());
281 // Put other bytes (full bytes)
282 for (int i = (k-1); i >= 0; i--) {
283 Tools::bit_accessor::put((u8)(val >> 8*i), 8, ctx.refBuffer());
287 static DecoderCtx::map_type inline run(DecoderCtx& ctx)
289 uint num_opts = IE::num_opt_entries;
292 u8 lb_bits = IE::num_opt_entries % 8; // num of last byte bits (without padding)
294 while (num_opts >= 8) {
295 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - 8*k;
297 DecoderCtx::map_type rval = Tools::bit_accessor::get(8, ctx.refBuffer());
299 rval = rval << shift;
307 // (8 - lb_bits) - padding in a last byte
308 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - 8*k + 8 - lb_bits;
310 DecoderCtx::map_type rval = Tools::bit_accessor::get(lb_bits, ctx.refBuffer());
312 rval = rval << shift;
323 struct SeqMap<IE, std::enable_if_t< (IE::num_opt_entries <= 8)> > //todo: to add code for more than 8 optional elements
325 static void inline run(EncoderCtx& ctx, size_t val)
327 Tools::bit_accessor::put((u8)val, IE::num_opt_entries, ctx.refBuffer());
329 static DecoderCtx::map_type inline run(DecoderCtx& ctx)
331 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - IE::num_opt_entries;
332 DecoderCtx::map_type rval = Tools::bit_accessor::get(IE::num_opt_entries, ctx.refBuffer());
333 rval = rval << shift;
338 /******************************************************************
340 *****************************************************************/
341 template<class IE, bound_t NumExtEntries, class Enabler = void>
344 static void inline run(EncoderCtx& ctx, size_t val) {}
345 static DecoderCtx::map_type inline run(DecoderCtx& ctx)
347 size_t len = NormallySmallLength<1>::run(ctx);
348 size_t shift = sizeof(DecoderCtx::map_type) * CHAR_BIT - len;
350 DecoderCtx::map_type rval{ 0 };
354 tmp = len > 8 ? 8 : (u8)len;
355 val = Tools::bit_accessor::get(tmp, ctx.refBuffer());
360 rval = rval << shift;
365 template<class IE, bound_t NumExtEntries>
366 struct SeqExtMap<IE, NumExtEntries, std::enable_if_t< ((NumExtEntries <= 8) && (NumExtEntries > 0)) > >
368 static void inline run(EncoderCtx& ctx, size_t val)
370 NormallySmallLength<NumExtEntries>::run(ctx);
371 Tools::bit_accessor::put((u8)val, NumExtEntries, ctx.refBuffer());
375 template<class IE, bound_t NumExtEntries>
376 struct SeqExtMap<IE, NumExtEntries, std::enable_if_t< (NumExtEntries > 8) > >
378 static void inline run(EncoderCtx& ctx, size_t val)
380 NormallySmallLength<NumExtEntries>::run(ctx);
382 size_t len = NumExtEntries;
386 tmp = len > 8 ? 8 : len;
387 Tools::bit_accessor::put((u8)val, tmp, ctx.refBuffer());
394 /******************************************************************
396 *****************************************************************/
399 SeqMapBuilder(uint64_t& map) : m_map(map) {}
401 template<typename IE>
402 bool operator()(IE const& ie)
404 if(!IE::extension && IE::optional)
415 /******************************************************************
417 *****************************************************************/
418 struct SeqExtMapBuilder
420 SeqExtMapBuilder(uint64_t& map) : m_map(map) {}
422 template<typename IE>
423 bool operator()(IE const& ie)
428 if(!IE::optional || (IE::optional && ie.is_valid()))
436 /******************************************************************
438 *****************************************************************/
439 // Default (No OPT/DEF present within the extension root)
441 struct SeqNoExtDefault
443 static void inline run(IE const& ie, EncoderCtx& ctx)
445 RootEncoder<IE> ve(ctx, ie);
448 static void inline run(IE& ie, DecoderCtx& ctx, DecoderCtx::map_type map = 0)
450 RootDecoder<IE> ve(ctx, ie);
452 DecoderCtx::map_type old_map = ctx.set_map(map);
454 ctx.set_map(old_map);
458 /******************************************************************
460 *****************************************************************/
461 // Default (No OPT/DEF present within the extension root)
462 template <class IE, class Enabler = void>
465 static void inline run(IE const& ie, EncoderCtx& ctx)
467 SeqNoExtDefault<IE>::run(ie, ctx);
469 static void inline run(IE& ie, DecoderCtx& ctx)
471 SeqNoExtDefault<IE>::run(ie, ctx);
475 //18.2 OPT/DEF present within the extension root
477 struct SeqNoExt<IE, std::enable_if_t< (IE::num_opt_entries > 0) > >
479 static void inline run(IE const& ie, EncoderCtx& ctx)
482 SeqMapBuilder mb(map);
484 SeqMap<IE>::run(ctx, map);
485 SeqNoExtDefault<IE>::run(ie, ctx);
487 static void inline run(IE& ie, DecoderCtx& ctx)
489 SeqNoExtDefault<IE>::run(ie, ctx, SeqMap<IE>::run(ctx));
493 /******************************************************************
495 *****************************************************************/
496 template <class IE, class Enable = void>
500 struct Seq<IE, std::enable_if_t< (IE::constraint_t::extended == true)> >
502 static void inline run(IE const& ie, EncoderCtx& ctx)
505 SeqExtMapBuilder emb(map);
509 Tools::bit_accessor::put(1, 1, ctx.refBuffer());
510 SeqNoExt<IE>::run(ie, ctx);
511 SeqExtMap<IE, IE::num_ext_entries>::run(ctx, map);
512 ExtEncoder<IE> ove(ctx, ie);
516 Tools::bit_accessor::put(0, 1, ctx.refBuffer());
517 SeqNoExt<IE>::run(ie, ctx);
520 static void inline run(IE& ie, DecoderCtx& ctx)
522 u8 ext = Tools::bit_accessor::get(1, ctx.refBuffer());
525 SeqNoExt<IE>::run(ie, ctx);
527 auto old_map = ctx.set_map(SeqExtMap<IE, 0>::run(ctx)); // we do not know how many exts can be received
529 ExtDecoder<IE> ove(ctx, ie);
532 auto& buffer = ctx.refBuffer();
535 if(ctx.map_elm()) //skip unknown extensions
537 size_t size = LengthDeterminantDefault::run(ctx);
538 if (buffer.getBytesLeft() < size)
540 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
543 buffer.advance(size);
547 ctx.set_map(old_map);
550 SeqNoExt<IE>::run(ie, ctx);
555 struct Seq<IE, std::enable_if_t< (IE::constraint_t::extended == false)> >
557 static void inline run(IE const& ie, EncoderCtx& ctx)
559 SeqNoExt<IE>::run(ie, ctx);
561 static void inline run(IE& ie, DecoderCtx& ctx)
563 SeqNoExt<IE>::run(ie, ctx);