Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #include <lib/core/ErrorStr.h>
19 :
20 : #include <lib/core/CHIPConfig.h>
21 : #include <lib/core/CHIPError.h>
22 : #include <lib/support/DLLUtil.h>
23 :
24 : #include <inttypes.h>
25 : #include <stdio.h>
26 :
27 : namespace chip {
28 :
29 : /**
30 : * Static buffer to store the formatted error string.
31 : */
32 : static ErrorStrStorage sErrorStr;
33 :
34 : /**
35 : * Linked-list of error formatter functions.
36 : */
37 : static ErrorFormatter * sErrorFormatterList = nullptr;
38 :
39 : /**
40 : * This routine returns a human-readable NULL-terminated C string
41 : * describing the provided error. This uses the global static storage.
42 : *
43 : * @param[in] err The error for format and describe.
44 : * @param[in] withSourceLocation Whether or not to include the source
45 : * location in the output string. Only used if CHIP_CONFIG_ERROR_SOURCE &&
46 : * !CHIP_CONFIG_SHORT_ERROR_STR. Defaults to true.
47 : *
48 : * @return A pointer to a NULL-terminated C string describing the
49 : * provided error.
50 : */
51 1067458 : DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation)
52 : {
53 1067458 : return ErrorStr(err, withSourceLocation, sErrorStr);
54 : }
55 :
56 : /**
57 : * This routine writess a human-readable NULL-terminated C string into the buf
58 : * which describes the provided error.
59 : *
60 : * @param[in] err The error for format and describe.
61 : * @param[in] withSourceLocation Whether or not to include the source
62 : * @param[in] storage ErrorStrStorage to write into
63 : * location in the output string. Only used if CHIP_CONFIG_ERROR_SOURCE &&
64 : * !CHIP_CONFIG_SHORT_ERROR_STR. Defaults to true.
65 : *
66 : * @return A pointer to a NULL-terminated C string describing the
67 : * provided error.
68 : */
69 1067712 : DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation, ErrorStrStorage & storage)
70 : {
71 1067712 : char * formattedError = storage.buff;
72 1067712 : uint16_t formattedSpace = storage.kBufferSize;
73 :
74 : #if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
75 :
76 1067712 : if (const char * const file = err.GetFile(); withSourceLocation && file != nullptr)
77 : {
78 1067407 : int n = snprintf(formattedError, formattedSpace, "%s:%u: ", file, err.GetLine());
79 1067407 : if (n > formattedSpace)
80 : {
81 0 : n = formattedSpace;
82 : }
83 1067407 : formattedError += n;
84 1067407 : formattedSpace = static_cast<uint16_t>(formattedSpace - n);
85 : }
86 : #endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
87 :
88 1067712 : if (err == CHIP_NO_ERROR)
89 : {
90 2559 : (void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING);
91 2559 : return storage.buff;
92 : }
93 :
94 : // Search the registered error formatter for one that will format the given
95 : // error code.
96 1067377 : for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next)
97 : {
98 3513 : if (errFormatter->FormatError(formattedError, formattedSpace, err))
99 : {
100 1289 : return storage.buff;
101 : }
102 : }
103 :
104 : // Use a default formatting if no formatter found.
105 1063864 : FormatError(formattedError, formattedSpace, nullptr, err, nullptr);
106 1063864 : return storage.buff;
107 : }
108 :
109 : /**
110 : * Add a new error formatter function to the global list of error formatters.
111 : *
112 : * @param[in] errFormatter An ErrorFormatter structure containing a
113 : * pointer to the new error function. Note
114 : * that a pointer to the supplied ErrorFormatter
115 : * structure will be retained by the function.
116 : * Thus the memory for the structure must
117 : * remain reserved.
118 : */
119 854 : DLL_EXPORT void RegisterErrorFormatter(ErrorFormatter * errFormatter)
120 : {
121 : // Do nothing if a formatter with the same format function is already in the list.
122 1662 : for (ErrorFormatter * existingFormatter = sErrorFormatterList; existingFormatter != nullptr;
123 808 : existingFormatter = existingFormatter->Next)
124 : {
125 1415 : if (existingFormatter->FormatError == errFormatter->FormatError)
126 : {
127 607 : return;
128 : }
129 : }
130 :
131 : // Add the formatter to the global list.
132 247 : errFormatter->Next = sErrorFormatterList;
133 247 : sErrorFormatterList = errFormatter;
134 : }
135 :
136 : /**
137 : * Remove an error formatter function from the global list of error formatters.
138 : *
139 : * @param[in] errFormatter An ErrorFormatter structure containing a
140 : * pointer to the new error function.
141 : */
142 2 : DLL_EXPORT void DeregisterErrorFormatter(ErrorFormatter * errFormatter)
143 : {
144 : // Remove the formatter if present
145 6 : for (ErrorFormatter ** lfp = &sErrorFormatterList; *lfp != nullptr; lfp = &(*lfp)->Next)
146 : {
147 : // Remove the formatter from the global list, if found.
148 4 : if (*lfp == errFormatter)
149 : {
150 1 : *lfp = errFormatter->Next;
151 : }
152 : }
153 2 : }
154 :
155 : #if !CHIP_CONFIG_CUSTOM_ERROR_FORMATTER
156 :
157 : /**
158 : * Generates a human-readable NULL-terminated C string describing the provided error.
159 : *
160 : * @param[in] buf Buffer into which the error string will be placed.
161 : * @param[in] bufSize Size of the supplied buffer in bytes.
162 : * @param[in] subsys A short string describing the subsystem that originated
163 : * the error, or NULL if the origin of the error is
164 : * unknown/unavailable. This string should be 10
165 : * characters or less.
166 : * @param[in] err The error to be formatted.
167 : * @param[in] desc A string describing the cause or meaning of the error,
168 : * or NULL if no such information is available.
169 : */
170 1065158 : DLL_EXPORT void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc)
171 : {
172 : #if CHIP_CONFIG_SHORT_ERROR_STR
173 :
174 : if (subsys == nullptr)
175 : {
176 : (void) snprintf(buf, bufSize, "Error " CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, err.AsInteger());
177 : }
178 : else
179 : {
180 : (void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err.AsInteger());
181 : }
182 :
183 : #else // CHIP_CONFIG_SHORT_ERROR_STR
184 :
185 1065158 : const char * subsysSep = " ";
186 1065158 : const char * descSep = ": ";
187 :
188 1065158 : if (subsys == nullptr)
189 : {
190 1063866 : subsys = "";
191 1063866 : subsysSep = "";
192 : }
193 1065158 : if (desc == nullptr)
194 : {
195 1063872 : desc = "";
196 1063872 : descSep = "";
197 : }
198 :
199 1065158 : (void) snprintf(buf, bufSize, "%s%sError 0x%08" PRIX32 "%s%s", subsys, subsysSep, err.AsInteger(), descSep, desc);
200 :
201 : #endif // CHIP_CONFIG_SHORT_ERROR_STR
202 1065158 : }
203 :
204 : #endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER
205 :
206 : } // namespace chip
|