--- /dev/null
+#pragma once
+/******************************************************************************
+*
+* Copyright (c) 2019 AT&T Intellectual Property.
+* Copyright (c) 2018-2019 Nokia.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************************/
+
+// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
+
+// Local Includes: Application specific classes, functions, and libraries
+
+namespace asn {
+namespace ber {
+
+/***************************************************************************************
+* VisitorEncoder
+***************************************************************************************/
+struct VisitorEncoder
+{
+ VisitorEncoder(EncoderCtx& ctx) : m_ctx(ctx){}
+
+ template<typename ELM> bool operator() (ELM const& elm)
+ {
+ if(m_ctx)
+ Element<ELM>::run(elm, m_ctx);
+ return static_cast<bool>(m_ctx);
+ }
+private:
+ EncoderCtx& m_ctx;
+};
+
+/***************************************************************************************
+* VisitorDecoder
+***************************************************************************************/
+struct VisitorDecoder
+{
+ VisitorDecoder(DecoderCtx& ctx, tag_value_t tag) : m_ctx(ctx), m_tag(tag){}
+
+ template<typename ELM> bool operator() (ELM& elm)
+ {
+ if(m_ctx)
+ Element<ELM>::run(elm, m_ctx, &m_tag);
+ return static_cast<bool>(m_ctx);
+ }
+
+private:
+ DecoderCtx& m_ctx;
+ tag_value_t m_tag;
+};
+
+/***************************************************************************************
+* VisitorAdapter
+***************************************************************************************/
+template <class Container, class IE, class Enabler = void>
+struct VisitorAdapter //default
+{
+ static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
+ {
+ Element<IE>::run(ie, ctx);
+ }
+ static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont, tag_value_t tag)
+ {
+ Element<IE>::run(ie, ctx, &tag);
+ }
+};
+
+template <class Container, class IE>
+struct VisitorAdapter<Container, IE, std::enable_if_t<
+ (IE::ie_type == element_type::T_OBJFIELD_FTV)
+ || (IE::ie_type == element_type::T_OBJFIELD_TF)
+ > >
+{
+ static void inline run(IE const& ie, EncoderCtx& ctx, Container const& cont)
+ {
+ VisitorEncoder v(ctx);
+ bool rv = ie.encode(v, cont);
+ if(!rv && static_cast<bool>(ctx))
+ {
+ ctx.refErrorCtx().errorNoObject(Container::name());
+ }
+ }
+ static void inline run(IE& ie, DecoderCtx& ctx, Container const& cont, tag_value_t tag)
+ {
+ VisitorDecoder v(ctx, tag);
+ bool rv = ie.decode(v, cont);
+ if(!rv && static_cast<bool>(ctx))
+ {
+ ctx.refErrorCtx().errorNoObject(Container::name());
+ }
+ }
+};
+
+/***************************************************************************************
+* VisitorEncoderSeq
+***************************************************************************************/
+template<typename CONT>
+struct VisitorEncoderSeq
+{
+ VisitorEncoderSeq(EncoderCtx& ctx, CONT const& cont) : m_ctx(ctx), m_cont(cont){}
+
+ template<typename ELM> void operator() (ELM const& elm)
+ {
+ if(ELM::optional)
+ {
+ if(elm.is_valid())
+ VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont);
+ }
+ else
+ VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont);
+ }
+
+ EncoderCtx& m_ctx;
+ CONT const& m_cont;
+};
+
+
+/***************************************************************************************
+* VisitorDecoderSeq
+***************************************************************************************/
+template<typename CONT>
+struct VisitorDecoderSeq
+{
+ VisitorDecoderSeq(DecoderCtx& ctx, CONT const& cont) : m_ctx(ctx), m_cont(cont){}
+
+ template<typename ELM> void operator() (ELM& elm)
+ {
+ if(m_ctx)
+ {
+ tag_value_t tag;
+
+ if(invalid_tag == m_tag && m_ctx.refBuffer().getBytesLeft())
+ {
+ m_tag = get_tag(m_ctx);
+ }
+ tag = m_tag;
+
+ if(m_ctx)
+ {
+ if (!Element<ELM>::is_matched(tag))
+ {
+ if(!ELM::optional)
+ {
+ m_ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
+ }
+ }
+ else
+ {
+ m_tag = invalid_tag;
+ VisitorAdapter<CONT, ELM>::run(elm, m_ctx, m_cont, tag);
+ elm.setpresent(true);
+ }
+ }
+ }
+ }
+
+ tag_value_t get_unhandled_tag() const {return m_tag;}
+
+ DecoderCtx& m_ctx;
+ tag_value_t m_tag {invalid_tag};
+ CONT const& m_cont;
+};
+
+} //namespace ber
+} //namespace asn