Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / per / whole_number.hpp
diff --git a/e2sim/e2apv1sim/src/ASN1/asn/per/whole_number.hpp b/e2sim/e2apv1sim/src/ASN1/asn/per/whole_number.hpp
new file mode 100755 (executable)
index 0000000..c614998
--- /dev/null
@@ -0,0 +1,147 @@
+#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
+#include <cmath>
+#include <boost/integer/static_log2.hpp>
+
+// Local Includes: Application specific classes, functions, and libraries
+#include "asn/per/common.hpp"
+#include "asn/per/binary_integer.hpp"
+
+namespace asn {
+namespace per {
+
+/***************************************************************************************
+* Encoding of a constrained whole number (X.691 10.5)
+***************************************************************************************/
+
+template<bound_t R, class E = void>
+struct length_determinant;
+
+template<bound_t R>
+struct length_determinant<R, std::enable_if_t< R == 0 > > { static constexpr bound_t value = 0; };
+
+template<bound_t R>
+struct length_determinant<R, std::enable_if_t< R == 1 > > { static constexpr bound_t value = 1; };
+
+template<bound_t R>
+struct length_determinant<R, std::enable_if_t< (R  > 1) > > { static constexpr bound_t value = boost::static_log2<(R - 1)>::value + 1; };
+
+/***************************************************************************************
+***************************************************************************************/
+
+template <class Range, class V, class Enable = void>
+struct ConstrainedWholeNumber;
+
+//Bit-field case
+template <class Range, class V>
+struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound < (Range::lower_bound + 255))> >
+{
+       //non-negative-binary-integer X.691 10.5
+       static void inline run(EncoderCtx& ctx, const V& val)
+       {
+               Tools::bit_accessor::put(static_cast<u8>(val - Range::lower_bound),
+                       length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
+                       ctx.refBuffer());
+       }
+       static V inline run(DecoderCtx& ctx)
+       {
+               return Range::lower_bound + Tools::bit_accessor::get(
+                       length_determinant<(Range::upper_bound - Range::lower_bound + 1)>::value,
+                       ctx.refBuffer());
+       }
+};
+
+//One octet case
+template <class Range, class V>
+struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound == (Range::lower_bound + 255))> >
+{
+       //non-negative-binary-integer X.691 10.5
+       static void inline run(EncoderCtx& ctx, const V& val)
+       {
+               Tools::bit_accessor::padByte(ctx.refBuffer());
+               ctx.refBuffer().putByte(static_cast<u8>(val - Range::lower_bound));
+       }
+       static V inline run(DecoderCtx& ctx)
+       {
+               V rval = 0;
+               Tools::bit_accessor::padByte(ctx.refBuffer());
+               u8 const* data = ctx.refBuffer().getBytes(1);
+               if (data)
+                       rval = Range::lower_bound + data[0];
+               return rval;
+       }
+};
+
+//Two octets case
+template <class Range, class V>
+struct ConstrainedWholeNumber<Range, V, std::enable_if_t<(Range::upper_bound > (Range::lower_bound + 255)) && (Range::upper_bound <= (Range::lower_bound + 65535))> >
+{
+       //non-negative-binary-integer X.691 10.5
+       static void inline run(EncoderCtx& ctx, const V& v)
+       {
+               u64 val = static_cast<u64>(v - Range::lower_bound);
+               Tools::bit_accessor::padByte(ctx.refBuffer());
+               ctx.refBuffer().putByte((u8)(val >> 8));
+               ctx.refBuffer().putByte((u8)val);
+       }
+       static V inline run(DecoderCtx& ctx)
+       {
+               V rval = 0;
+               Tools::bit_accessor::padByte(ctx.refBuffer());
+               u8 const* data = ctx.refBuffer().getBytes(2);
+               if (data) {
+                       rval = data[0];
+                       rval = rval << 8;
+                       rval |= data[1];
+                       rval += Range::lower_bound;
+               }
+               return rval;
+       }
+};
+
+//Indefinite case
+template <class Range, class V>
+struct ConstrainedWholeNumber<Range, V, std::enable_if_t< (Range::upper_bound > Range::lower_bound + 65535) > >
+{
+       struct NormalizedValueRange
+       {
+               using boundary_type = typename Range::boundary_type;
+               static constexpr bool extended = Range::extended;
+               static constexpr boundary_type lower_bound = 0;
+               static constexpr boundary_type upper_bound = Range::upper_bound - Range::lower_bound;
+       };
+       
+       //non-negative-binary-integer X.691 10.5
+       static void inline run(EncoderCtx& ctx, const V& val)
+       {
+               NonnegativeBinaryInteger<NormalizedValueRange>::run(val - Range::lower_bound, ctx);
+       }
+       static V inline run(DecoderCtx& ctx)
+       {
+               V rval = 0;
+               NonnegativeBinaryInteger<NormalizedValueRange>::run(rval, ctx, false);
+               return rval + Range::lower_bound;
+       }
+};
+
+} //namespace per
+} //namespace asn