Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / ber / 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
25 namespace asn {
26 namespace ber {
27
28 /***************************************************************************************
29 * VisitorEncoder
30 ***************************************************************************************/
31 struct VisitorEncoder
32 {
33         VisitorEncoder(EncoderCtx& ctx) : m_ctx(ctx){}
34         
35         template<typename ELM> bool operator() (ELM const& elm) 
36         {
37                 if(m_ctx)
38                         Element<ELM>::run(elm, m_ctx);
39                 return static_cast<bool>(m_ctx);
40         }
41 private:
42         EncoderCtx&     m_ctx;
43 };
44
45 /***************************************************************************************
46 * VisitorDecoder
47 ***************************************************************************************/
48 struct VisitorDecoder
49 {
50         VisitorDecoder(DecoderCtx& ctx, tag_value_t tag) : m_ctx(ctx), m_tag(tag){}
51         
52         template<typename ELM> bool operator() (ELM& elm) 
53         {
54                 if(m_ctx)
55                         Element<ELM>::run(elm, m_ctx, &m_tag);
56                 return static_cast<bool>(m_ctx);
57         }
58
59 private:
60         DecoderCtx&     m_ctx;
61         tag_value_t     m_tag;
62 };
63
64 /***************************************************************************************
65 * VisitorAdapter
66 ***************************************************************************************/
67 template <class Container, class IE, class Enabler = void>
68 struct VisitorAdapter //default
69 {
70         static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
71         {
72                 Element<IE>::run(ie, ctx);
73         }
74         static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont, tag_value_t tag)
75         {
76                 Element<IE>::run(ie, ctx, &tag);
77         }
78 };
79
80 template <class Container, class IE>
81 struct VisitorAdapter<Container, IE, std::enable_if_t<
82                                         (IE::ie_type == element_type::T_OBJFIELD_FTV)
83                                         || (IE::ie_type == element_type::T_OBJFIELD_TF)
84                                         > >
85 {
86         static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
87         {
88                 VisitorEncoder v(ctx);
89                 bool rv = ie.encode(v, cont);
90                 if(!rv && static_cast<bool>(ctx))
91                 {
92                         ctx.refErrorCtx().errorNoObject(Container::name());
93                 }
94         }
95         static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont, tag_value_t tag)
96         {
97                 VisitorDecoder v(ctx, tag);
98                 bool rv = ie.decode(v, cont);
99                 if(!rv && static_cast<bool>(ctx))
100                 {
101                         ctx.refErrorCtx().errorNoObject(Container::name());
102                 }
103         }
104 };
105
106 /***************************************************************************************
107 * VisitorEncoderSeq
108 ***************************************************************************************/
109 template<typename CONT>
110 struct VisitorEncoderSeq
111 {
112         VisitorEncoderSeq(EncoderCtx& ctx, CONT const& cont) : m_ctx(ctx), m_cont(cont){}
113         
114         template<typename ELM> void operator() (ELM const& elm) 
115         {
116                 if(ELM::optional)
117                 {
118                         if(elm.is_valid())
119                                 VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont);
120                 }
121                 else
122                         VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont);
123         }
124         
125         EncoderCtx&     m_ctx;
126         CONT const&             m_cont;
127 };
128
129
130 /***************************************************************************************
131 * VisitorDecoderSeq
132 ***************************************************************************************/
133 template<typename CONT>
134 struct VisitorDecoderSeq
135 {
136         VisitorDecoderSeq(DecoderCtx& ctx, CONT const& cont) : m_ctx(ctx), m_cont(cont){}
137         
138         template<typename ELM> void operator() (ELM& elm) 
139         {
140                 if(m_ctx)
141                 {
142                         tag_value_t tag;
143                         
144                         if(invalid_tag == m_tag && m_ctx.refBuffer().getBytesLeft())
145                         {
146                                 m_tag = get_tag(m_ctx);
147                         }
148                         tag = m_tag;
149
150                         if(m_ctx)
151                         {
152                                 if (!Element<ELM>::is_matched(tag))
153                                 {
154                                         if(!ELM::optional)
155                                         {
156                                                 m_ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
157                                         }
158                                 }
159                                 else
160                                 {
161                                         m_tag = invalid_tag;
162                                         VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont, tag);
163           elm.setpresent(true);
164                                 }
165                         }
166                 }
167         }
168         
169         tag_value_t get_unhandled_tag() const {return m_tag;}
170         
171         DecoderCtx&     m_ctx;
172         tag_value_t     m_tag {invalid_tag};
173         CONT const&             m_cont;
174 };
175
176 } //namespace ber
177 } //namespace asn