Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / visitor.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 /********************************************************************************
30 VisitorEncoder
31 *********************************************************************************/
32 struct VisitorEncoder
33 {
34         explicit VisitorEncoder(EncoderCtx& ctx) : m_ctx(ctx) {}
35
36         template <typename IE>
37         bool operator() (IE const& ie) const
38         {
39                 Element<IE, IE::ie_type>::run(ie, m_ctx);
40                 return static_cast<bool>(m_ctx);
41         }
42         EncoderCtx&             m_ctx;
43 };
44
45 /********************************************************************************
46 VisitorDecoder
47 *********************************************************************************/
48 struct VisitorDecoder
49 {
50         VisitorDecoder(DecoderCtx& ctx) : m_ctx(ctx) {}
51
52         template <typename IE>
53         bool operator() (IE& ie) const
54         {
55                 Element<IE, IE::ie_type>::run(ie, m_ctx);
56                 return static_cast<bool>(m_ctx);
57         }
58         DecoderCtx& m_ctx;
59 };
60
61 /***************************************************************************************
62 * Open Type Visitor // Encode Open Type (10.2)
63 ***************************************************************************************/
64 struct OpenTypeVisitorEncoder
65 {
66         explicit OpenTypeVisitorEncoder(EncoderCtx& ctx) : m_ctx(ctx) {}
67
68         template <typename IE>
69         bool operator() (IE const& ie) const
70         {
71                 size_t reserved_size = 1; //1 byte length is most likely
72                 Tools::bit_accessor::padByte(m_ctx.refBuffer());
73
74                 if (m_ctx.refBuffer().getBytesLeft())
75                 {
76                         EncoderCtx::buf_type::pointer p = m_ctx.refBuffer().advance(reserved_size);
77                         EncoderCtx::buf_type::pointer start = p + reserved_size;
78
79                         Element<IE, IE::ie_type>::run(ie, m_ctx);
80
81                         if (m_ctx)
82                         {
83                                 Tools::bit_accessor::padByte(m_ctx.refBuffer());
84                                 EncoderCtx::buf_type::pointer p_new = m_ctx.refBuffer().begin();
85                                 size_t size = p_new - start;
86                                 size_t needed = LengthDeterminantDefault::bytes_needed(size) - reserved_size;
87                                 if (needed) //1 byte is not enough for the length determinant. it is hardly possible
88                                 {
89                                         if (m_ctx.refBuffer().getBytesLeft() < needed) {
90                                                 m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), needed);
91                                                 return false;
92                                         }
93                                         memmove(start + needed, start, size);
94                                         p_new += needed;
95                                 }
96                                 m_ctx.refBuffer().set_begin(p, 0);
97                                 LengthDeterminantDefault::run(m_ctx, size);
98                                 if (m_ctx) {
99                                         m_ctx.refBuffer().set_begin(p_new, 0);
100                                         Tools::bit_accessor::padByte(m_ctx.refBuffer());
101                                 }
102                         }
103                 }
104                 else
105                 {
106                         m_ctx.refErrorCtx().lengthErrorBytes(m_ctx.refBuffer().getBytesLeft(), reserved_size);
107                 }
108                 return static_cast<bool>(m_ctx);
109         }
110         EncoderCtx& m_ctx;
111 };
112
113 /***************************************************************************************
114 * Open Type Visitor // Decode Open Type (10.2)
115 ***************************************************************************************/
116 struct OpenTypeVisitorDecoder
117 {
118         explicit OpenTypeVisitorDecoder(DecoderCtx& ctx) : m_ctx(ctx) {}
119
120         template <typename IE>
121         bool operator() (IE& ie) const
122         {
123                 size_t size = LengthDeterminantDefault::run(m_ctx);
124                 DecoderCtx::buf_type& buffer = m_ctx.refBuffer();
125                 if (buffer.getBytesLeft() < size)
126                 {
127                         m_ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), size);
128                         return false;
129                 }
130                 DecoderCtx::buf_type::pointer end = buffer.end();
131                 buffer.set_end(buffer.begin() + size);
132                 Element<IE, IE::ie_type>::run(ie, m_ctx);
133                 buffer.set_end(end);
134
135                 return static_cast<bool>(m_ctx);
136         }
137         DecoderCtx& m_ctx;
138 };
139
140 } //namespace per
141 } //namespace asn