--- /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
+#include "type_defs.h"
+
+namespace asn {
+
+class error_context
+{
+public:
+ enum error_e : u8
+ {
+ SUCCESS = 0
+ ,INCORRECT_LENGTH_BITS
+ ,INCORRECT_LENGTH_BYTES
+ ,ALIGNMENT
+ ,INCORRECT_VALUE
+ ,INCORRECT_CHOICE_TAG
+ ,INCORRECT_IE_TAG
+ ,VALUE_OUT_OF_RANGE
+ ,SIZE_OUT_OF_RANGE
+ ,ALLOC_NO_MEMORY
+ ,NO_OBJECT
+ ,NO_MANDATORY
+ ,WRONG_END_OF_CONTENT
+ ,UNSUPPORTED
+ ,UNSPECIFIED
+ };
+
+ explicit operator bool() const { return SUCCESS == m_error; }
+
+ void reset() { m_error = SUCCESS; }
+ error_e getError() const { return m_error; }
+
+ char const* toString() const;
+
+ void alignmentError(u32 shift);
+ void lengthErrorBytes(u32 bytes_left, u32 requested);
+ void lengthErrorBits(u32 bits_left, u32 requested);
+ void valueError(u32 got, u32 expected, u32 ofs);
+ void tagError(u32 tag);
+ void valueRangeError(size_t value);
+ void sizeRangeError(size_t size, size_t low = 0, size_t high = 0);
+ void allocatorNoMem(size_t bytes_left, size_t bytes_required);
+ void errorUnsupported() {setError(UNSUPPORTED);}
+ void errorUnspecified() {setError(UNSPECIFIED);}
+ void errorNoObject(const char* container_name_);
+ void errorNoMandatory();
+ void errorWrongEndOfContent() {setError(WRONG_END_OF_CONTENT);}
+
+ //to inline in choice decoder: TODO: think of changing it!
+ void choiceError(char const* name, u32 id)
+ {
+ m_name = name;
+ m_param[0] = id;
+ setError(INCORRECT_CHOICE_TAG);
+ }
+ //Name of the being processed IE
+ void ie_name(const char* name) { m_ie_name = name; }
+ char const* ie_name() const { return m_ie_name; }
+
+ void container_name(const char* name) { m_container_name = name; }
+ char const* container_name() const { return m_container_name; }
+
+
+private:
+ void setError(error_e n) { m_error = n; }
+
+ enum { MAX_PARAMS = 3 };
+ error_e m_error;
+ char const* m_name;
+ char const* m_ie_name {""};
+ char const* m_container_name {""};
+ size_t m_param[MAX_PARAMS];
+
+};
+
+inline
+void error_context::errorNoObject(const char* c_name)
+{
+ container_name(c_name);
+ m_name = m_ie_name;
+ setError(NO_OBJECT);
+}
+
+inline
+void error_context::errorNoMandatory()
+{
+ m_name = m_ie_name;
+ setError(NO_MANDATORY);
+}
+
+inline
+void error_context::alignmentError(u32 shift)
+{
+ m_name = m_ie_name;
+ m_param[0] = shift;
+ setError(ALIGNMENT);
+}
+
+inline
+void error_context::lengthErrorBytes(u32 bytes_left, u32 requested)
+{
+ m_name = m_ie_name;
+ m_param[0] = bytes_left;
+ m_param[1] = requested;
+ setError(INCORRECT_LENGTH_BYTES);
+}
+
+inline
+void error_context::lengthErrorBits(u32 bits_left, u32 requested)
+{
+ m_name = m_ie_name;
+ m_param[0] = bits_left;
+ m_param[1] = requested;
+ setError(INCORRECT_LENGTH_BITS);
+}
+
+inline
+void error_context::valueError(u32 got, u32 expected, u32 ofs)
+{
+ m_name = m_ie_name;
+ m_param[0] = got;
+ m_param[1] = expected;
+ m_param[2] = ofs;
+ setError(INCORRECT_VALUE);
+}
+
+inline
+void error_context::tagError(u32 tag)
+{
+ m_name = m_ie_name;
+ m_param[0] = tag;
+ setError(INCORRECT_IE_TAG);
+}
+
+inline
+void error_context::valueRangeError(size_t value)
+{
+ m_name = m_ie_name;
+ m_param[0] = value;
+ setError(VALUE_OUT_OF_RANGE);
+}
+
+inline
+void error_context::sizeRangeError(size_t size, size_t low, size_t high)
+{
+ m_name = m_ie_name;
+ m_param[0] = size;
+ m_param[1] = low;
+ m_param[2] = high;
+ setError(SIZE_OUT_OF_RANGE);
+}
+
+inline
+void error_context::allocatorNoMem(size_t bytes_left, size_t bytes_required)
+{
+ m_name = m_ie_name;
+ m_param[0] = bytes_left;
+ m_param[1] = bytes_required;
+ setError(ALLOC_NO_MEMORY);
+}
+
+inline
+char const* error_context::toString() const
+{
+ static char sz[256];
+
+ switch (m_error)
+ {
+ case SUCCESS:
+ return "OK";
+
+ case INCORRECT_LENGTH_BITS:
+ snprintf(sz, sizeof(sz)-1, "%zu bits left, '%s::%s' needs %zu", m_param[0], m_container_name, m_name, m_param[1]);
+ break;
+
+ case INCORRECT_LENGTH_BYTES:
+ snprintf(sz, sizeof(sz)-1, "%zu bytes left, '%s::%s' needs %zu", m_param[0], m_container_name, m_name, m_param[1]);
+ break;
+ case ALIGNMENT:
+ snprintf(sz, sizeof(sz)-1, "misaligned '%s::%s': shift %zu bits", m_container_name, m_name, m_param[0]);
+ break;
+
+ case INCORRECT_VALUE:
+ snprintf(sz, sizeof(sz)-1, "Wrong value of '%s::%s' at %zu: 0x%zX expected=0x%zX", m_container_name, m_name, m_param[2], m_param[0], m_param[1]);
+ break;
+
+ case INCORRECT_CHOICE_TAG:
+ snprintf(sz, sizeof(sz)-1, "Wrong choice tag of '%s::%s': %zu (0x%zX)", m_container_name, m_name, m_param[0], m_param[0]);
+ break;
+
+ case INCORRECT_IE_TAG:
+ snprintf(sz, sizeof(sz)-1, "Wrong tag of '%s::%s': %zu (0x%zX)", m_container_name, m_name, m_param[0], m_param[0]);
+ break;
+
+ case VALUE_OUT_OF_RANGE:
+ snprintf(sz, sizeof(sz) - 1, "Value is out of the range '%s::%s': value: %zu", m_container_name, m_name, m_param[0]);
+ break;
+
+ case SIZE_OUT_OF_RANGE:
+ if (m_param[2])
+ {
+ snprintf(sz, sizeof(sz) - 1, "Size=%zu bytes is out of the range [%zu, %zu] in '%s::%s'", m_param[0], m_param[1], m_param[2], m_container_name, m_name);
+ }
+ else
+ {
+ if (m_param[1])
+ {
+ snprintf(sz, sizeof(sz) - 1, "Size=%zu bytes is less than %zu in '%s::%s'", m_param[0], m_param[1], m_container_name, m_name);
+ }
+ else
+ {
+ snprintf(sz, sizeof(sz) - 1, "Size=%zu bytes is out of the range in '%s::%s'", m_param[0], m_container_name, m_name);
+ }
+ }
+ break;
+
+ case ALLOC_NO_MEMORY:
+ snprintf(sz, sizeof(sz) - 1, "Allocator memory has ended '%s::%s': left bytes: %zu; required bytes: %zu", m_container_name, m_name, m_param[0], m_param[1]);
+ break;
+ case NO_OBJECT:
+ snprintf(sz, sizeof(sz) - 1, "Component relation constraint violated '%s::%s'", m_container_name, m_name);
+ break;
+ case NO_MANDATORY:
+ snprintf(sz, sizeof(sz) - 1, "no mandatory '%s::%s' is found", m_container_name, m_name);
+ break;
+ case UNSUPPORTED:
+ snprintf(sz, sizeof(sz) - 1, "unsupported object '%s::%s' is found", m_container_name, m_name);
+ return "unsupported";
+ break;
+ case UNSPECIFIED:
+ snprintf(sz, sizeof(sz) - 1, "unspecified object '%s::%s' is found", m_container_name, m_name);
+ return "unspecified";
+ break;
+ case WRONG_END_OF_CONTENT:
+ snprintf(sz, sizeof(sz) - 1, "wrong end of content in object '%s::%s'", m_container_name, m_name);
+ return "wrong end of content";
+ break;
+ }
+
+ return sz;
+}
+
+} //end: namespace asn