#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