Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / error_context.hpp
1 #pragma once
2
3 /******************************************************************************
4 *
5 *   Copyright (c) 2019 AT&T Intellectual Property.
6 *   Copyright (c) 2018-2019 Nokia.
7 *
8 *   Licensed under the Apache License, Version 2.0 (the "License");
9 *   you may not use this file except in compliance with the License.
10 *   You may obtain a copy of the License at
11 *
12 *       http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *   Unless required by applicable law or agreed to in writing, software
15 *   distributed under the License is distributed on an "AS IS" BASIS,
16 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *   See the License for the specific language governing permissions and
18 *   limitations under the License.
19 *
20 ******************************************************************************/
21
22 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23
24
25 // Local Includes: Application specific classes, functions, and libraries
26 #include "type_defs.h"
27
28 namespace asn {
29
30 class error_context
31 {
32 public:
33         enum error_e : u8
34         {
35                 SUCCESS = 0
36                 ,INCORRECT_LENGTH_BITS
37                 ,INCORRECT_LENGTH_BYTES
38                 ,ALIGNMENT
39                 ,INCORRECT_VALUE
40                 ,INCORRECT_CHOICE_TAG
41                 ,INCORRECT_IE_TAG
42                 ,VALUE_OUT_OF_RANGE
43                 ,SIZE_OUT_OF_RANGE
44                 ,ALLOC_NO_MEMORY
45                 ,NO_OBJECT
46                 ,NO_MANDATORY
47                 ,WRONG_END_OF_CONTENT
48                 ,UNSUPPORTED
49                 ,UNSPECIFIED
50         };
51
52         explicit operator bool() const          { return SUCCESS == m_error; }
53
54         void reset()                            { m_error = SUCCESS; }
55         error_e getError() const                { return m_error; }
56
57         char const* toString() const;
58
59         void alignmentError(u32 shift);
60         void lengthErrorBytes(u32 bytes_left, u32 requested);
61         void lengthErrorBits(u32 bits_left, u32 requested);
62         void valueError(u32 got, u32 expected, u32 ofs);
63         void tagError(u32 tag);
64         void valueRangeError(size_t value);
65         void sizeRangeError(size_t size, size_t low = 0, size_t high = 0);
66         void allocatorNoMem(size_t bytes_left, size_t bytes_required);
67         void errorUnsupported() {setError(UNSUPPORTED);}
68         void errorUnspecified() {setError(UNSPECIFIED);}
69         void errorNoObject(const char* container_name_);
70         void errorNoMandatory();
71         void errorWrongEndOfContent() {setError(WRONG_END_OF_CONTENT);}
72
73         //to inline in choice decoder: TODO: think of changing it!
74         void choiceError(char const* name, u32 id)
75         {
76                 m_name = name;
77                 m_param[0] = id;
78                 setError(INCORRECT_CHOICE_TAG);
79         }
80         //Name of the being processed IE
81         void ie_name(const char* name)                  { m_ie_name = name; }
82         char const* ie_name() const                             { return m_ie_name; }
83
84         void container_name(const char* name)   { m_container_name = name; }
85         char const* container_name() const              { return m_container_name; }
86
87
88 private:
89         void setError(error_e n)                { m_error = n; }
90
91         enum { MAX_PARAMS = 3 };
92         error_e     m_error;
93         char const* m_name;
94         char const* m_ie_name {""};
95         char const* m_container_name {""};
96         size_t      m_param[MAX_PARAMS];
97
98 };
99
100 inline
101 void error_context::errorNoObject(const char* c_name)
102 {
103         container_name(c_name);
104         m_name = m_ie_name;
105         setError(NO_OBJECT);
106 }
107
108 inline
109 void error_context::errorNoMandatory()
110 {
111         m_name = m_ie_name;
112         setError(NO_MANDATORY);
113 }
114
115 inline
116 void error_context::alignmentError(u32 shift)
117 {
118         m_name = m_ie_name;
119         m_param[0] = shift;
120         setError(ALIGNMENT);
121 }
122
123 inline
124 void error_context::lengthErrorBytes(u32 bytes_left, u32 requested)
125 {
126         m_name = m_ie_name;
127         m_param[0] = bytes_left;
128         m_param[1] = requested;
129         setError(INCORRECT_LENGTH_BYTES);
130 }
131
132 inline
133 void error_context::lengthErrorBits(u32 bits_left, u32 requested)
134 {
135         m_name = m_ie_name;
136         m_param[0] = bits_left;
137         m_param[1] = requested;
138         setError(INCORRECT_LENGTH_BITS);
139 }
140
141 inline
142 void error_context::valueError(u32 got, u32 expected, u32 ofs)
143 {
144         m_name = m_ie_name;
145         m_param[0] = got;
146         m_param[1] = expected;
147         m_param[2] = ofs;
148         setError(INCORRECT_VALUE);
149 }
150
151 inline
152 void error_context::tagError(u32 tag)
153 {
154         m_name = m_ie_name;
155         m_param[0] = tag;
156         setError(INCORRECT_IE_TAG);
157 }
158
159 inline
160 void error_context::valueRangeError(size_t value)
161 {
162         m_name = m_ie_name;
163         m_param[0] = value;
164         setError(VALUE_OUT_OF_RANGE);
165 }
166
167 inline
168 void error_context::sizeRangeError(size_t size, size_t low, size_t high)
169 {
170         m_name = m_ie_name;
171         m_param[0] = size;
172         m_param[1] = low;
173         m_param[2] = high;
174         setError(SIZE_OUT_OF_RANGE);
175 }
176
177 inline
178 void error_context::allocatorNoMem(size_t bytes_left, size_t bytes_required)
179 {
180         m_name = m_ie_name;
181         m_param[0] = bytes_left;
182         m_param[1] = bytes_required;
183         setError(ALLOC_NO_MEMORY);
184 }
185
186 inline
187 char const* error_context::toString() const
188 {
189         static char sz[256];
190
191         switch (m_error)
192         {
193         case SUCCESS:
194                 return "OK";
195
196         case INCORRECT_LENGTH_BITS:
197                 snprintf(sz, sizeof(sz)-1, "%zu bits left, '%s::%s' needs %zu", m_param[0], m_container_name, m_name, m_param[1]);
198                 break;
199
200         case INCORRECT_LENGTH_BYTES:
201                 snprintf(sz, sizeof(sz)-1, "%zu bytes left, '%s::%s' needs %zu", m_param[0], m_container_name, m_name, m_param[1]);
202                 break;
203         case ALIGNMENT:
204                 snprintf(sz, sizeof(sz)-1, "misaligned '%s::%s': shift %zu bits", m_container_name, m_name, m_param[0]);
205                 break;
206
207         case INCORRECT_VALUE:
208                 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]);
209                 break;
210
211         case INCORRECT_CHOICE_TAG:
212                 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]);
213                 break;
214
215         case INCORRECT_IE_TAG:
216                 snprintf(sz, sizeof(sz)-1, "Wrong tag of '%s::%s': %zu (0x%zX)", m_container_name, m_name, m_param[0], m_param[0]);
217                 break;
218
219         case VALUE_OUT_OF_RANGE:
220                 snprintf(sz, sizeof(sz) - 1, "Value is out of the range '%s::%s': value: %zu", m_container_name, m_name, m_param[0]);
221                 break;
222
223         case SIZE_OUT_OF_RANGE:
224                 if (m_param[2])
225                 {
226                         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);
227                 }
228                 else
229                 {
230                         if (m_param[1])
231                         {
232                                 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);
233                         }
234                         else
235                         {
236                                 snprintf(sz, sizeof(sz) - 1, "Size=%zu bytes is out of the range in '%s::%s'", m_param[0], m_container_name, m_name);
237                         }
238                 }
239                 break;
240
241         case ALLOC_NO_MEMORY:
242                 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]);
243                 break;
244         case NO_OBJECT:
245                 snprintf(sz, sizeof(sz) - 1, "Component relation constraint violated '%s::%s'", m_container_name, m_name);
246                 break;
247         case NO_MANDATORY:
248                 snprintf(sz, sizeof(sz) - 1, "no mandatory '%s::%s' is found", m_container_name, m_name);
249                 break;
250         case UNSUPPORTED:
251                 snprintf(sz, sizeof(sz) - 1, "unsupported object '%s::%s' is found", m_container_name, m_name);
252                 return "unsupported";
253                 break;
254         case UNSPECIFIED:
255                 snprintf(sz, sizeof(sz) - 1, "unspecified object '%s::%s' is found", m_container_name, m_name);
256                 return "unspecified";
257                 break;
258         case WRONG_END_OF_CONTENT:
259                 snprintf(sz, sizeof(sz) - 1, "wrong end of content in object '%s::%s'", m_container_name, m_name);
260                 return "wrong end of content";
261                 break;
262         }
263
264         return sz;
265 }
266
267 }       //end: namespace asn