-
Notifications
You must be signed in to change notification settings - Fork 100
/
error_handling_helpers.h
182 lines (164 loc) · 5.58 KB
/
error_handling_helpers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// 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.
// Note: migrated from rmw/error_handling.h in 2017-04
#ifndef ERROR_HANDLING_HELPERS_H_
#define ERROR_HANDLING_HELPERS_H_
// When this define evaluates to true (default), then messages will printed to
// stderr when an error is encountered while setting the error state.
// For example, when memory cannot be allocated or a previous error state is
// being overwritten.
#ifndef RCUTILS_REPORT_ERROR_HANDLING_ERRORS
#define RCUTILS_REPORT_ERROR_HANDLING_ERRORS 1
#endif
// When this define evaluates to true (default), then a warning will be written
// to stderr using RCUTILS_SAFE_FWRITE_TO_STDERR.
#ifndef RCUTILS_WARN_ON_TRUNCATION
#define RCUTILS_WARN_ON_TRUNCATION 1
#endif
#ifndef __STDC_WANT_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1 // indicate we would like memmove_s if available
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <rcutils/error_handling.h>
#ifdef __cplusplus
extern "C"
{
#endif
// do not use externally, internal function which is only to be used by error_handling.c
static
size_t
__rcutils_copy_string(char * dst, size_t dst_size, const char * src)
{
assert(dst != NULL);
assert(dst_size > 0);
assert(src != NULL);
// doesn't matter how long src actually is if it is longer than dst, so limit to dst + 1
size_t src_length = strnlen(src, dst_size);
size_t size_to_copy = src_length;
// the destination must be one byte bigger to store the NULL terminating character
if (src_length >= dst_size) {
size_to_copy = dst_size - 1;
#if RCUTILS_REPORT_ERROR_HANDLING_ERRORS && RCUTILS_WARN_ON_TRUNCATION
// truncation will be required
RCUTILS_SAFE_FWRITE_TO_STDERR(
"[rcutils|error_handling.c:" RCUTILS_STRINGIFY(__LINE__)
"] an error string (message, file name, or formatted message) will be truncated\n");
#endif
}
#ifdef __STDC_LIB_EXT1__
errno_t ret = memmove_s(
dst, dst_size,
src, size_to_copy); // this will always ensure truncation
if (0 != ret) {
# if RCUTILS_REPORT_ERROR_HANDLING_ERRORS
RCUTILS_SAFE_FWRITE_TO_STDERR(
"[rcutils|error_handling.c:" RCUTILS_STRINGIFY(__LINE__)
"] memmove_s failed, the error string may be malformed\n");
# endif
}
#else
(void)memmove(dst, src, size_to_copy);
#endif
dst[size_to_copy] = '\0';
return size_to_copy;
}
// do not use externally, internal function which is only to be used by error_handling.c
static
void
__rcutils_reverse_str(char * string_in, size_t string_len)
{
assert(string_in != NULL);
if (0 == string_len) {
return;
}
size_t i = 0;
size_t j = string_len - 1;
for (; i < j; i++, j--) {
char c = string_in[i];
string_in[i] = string_in[j];
string_in[j] = c;
}
}
// do not use externally, internal function which is only to be used by error_handling.c
static
void
__rcutils_convert_uint64_t_into_c_str(uint64_t number, char * buffer, size_t buffer_size)
{
assert(buffer != NULL);
assert(buffer_size >= 21);
(void)buffer_size; // prevent warning in release builds where there is no assert(...)
size_t i = 0;
// if number is 0, short circuit
if (number == 0) {
buffer[0] = '0';
buffer[1] = '\0';
return;
}
// add the modulo 10 to the string and then integer divide by 10 until 0
while (number != 0) {
buffer[i++] = (char)(number % 10 + '0');
number = number / 10;
}
// null terminate
buffer[i] = '\0';
// reverse the string in place
__rcutils_reverse_str(buffer, strnlen(buffer, 21));
}
// do not use externally, internal function which is only to be used by error_handling.c
static
void
__rcutils_format_error_string(
rcutils_error_string_t * error_string,
const rcutils_error_state_t * error_state)
{
assert(error_string != NULL);
assert(error_state != NULL);
static const char format_1[] = ", at ";
static const char format_2[] = ":";
char line_number_buffer[21];
static_assert(
sizeof(error_string->str) == (
sizeof(error_state->message) +
sizeof(format_1) - 1 /* minus the null-term */ +
sizeof(error_state->file) +
sizeof(format_2) - 1 /* minus the null-term */ +
sizeof(line_number_buffer) - 1 /* minus the null-term */ +
1 // null terminator
), "math error in static string formatting");
char * offset = error_string->str;
size_t bytes_left = sizeof(error_string->str);
size_t written = __rcutils_copy_string(offset, bytes_left, error_state->message);
offset += written;
bytes_left -= written;
written = __rcutils_copy_string(offset, bytes_left, format_1);
offset += written;
bytes_left -= written;
written = __rcutils_copy_string(offset, bytes_left, error_state->file);
offset += written;
bytes_left -= written;
written = __rcutils_copy_string(offset, bytes_left, format_2);
offset += written;
bytes_left -= written;
__rcutils_convert_uint64_t_into_c_str(
error_state->line_number, line_number_buffer, sizeof(line_number_buffer));
written = __rcutils_copy_string(offset, bytes_left, line_number_buffer);
offset += written;
offset[0] = '\0';
}
#ifdef __cplusplus
}
#endif
#endif // ERROR_HANDLING_HELPERS_H_