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 1050186 : DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation)
52 : {
53 1050186 : 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 1050440 : DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation, ErrorStrStorage & storage)
70 : {
71 1050440 : char * formattedError = storage.buff;
72 1050440 : uint16_t formattedSpace = storage.kBufferSize;
73 :
74 : #if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
75 :
76 1050440 : if (const char * const file = err.GetFile(); withSourceLocation && file != nullptr)
77 : {
78 1050135 : int n = snprintf(formattedError, formattedSpace, "%s:%u: ", file, err.GetLine());
79 1050135 : if (n > formattedSpace)
80 : {
81 0 : n = formattedSpace;
82 : }
83 1050135 : formattedError += n;
84 1050135 : formattedSpace = static_cast<uint16_t>(formattedSpace - n);
85 : }
86 : #endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
87 :
88 1050440 : if (err == CHIP_NO_ERROR)
89 : {
90 2556 : (void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING);
91 2556 : return storage.buff;
92 : }
93 :
94 : // Search the registered error formatter for one that will format the given
95 : // error code.
96 1050140 : for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next)
97 : {
98 3561 : if (errFormatter->FormatError(formattedError, formattedSpace, err))
99 : {
100 1305 : return storage.buff;
101 : }
102 : }
103 :
104 : // Use a default formatting if no formatter found.
105 1046579 : FormatError(formattedError, formattedSpace, nullptr, err, nullptr);
106 1046579 : 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 858 : DLL_EXPORT void RegisterErrorFormatter(ErrorFormatter * errFormatter)
120 : {
121 : // Do nothing if a formatter with the same format function is already in the list.
122 1666 : 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 251 : errFormatter->Next = sErrorFormatterList;
133 251 : 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 11 : DLL_EXPORT void DeregisterErrorFormatter(ErrorFormatter * errFormatter)
143 : {
144 : // Remove the formatter if present
145 30 : for (ErrorFormatter ** lfp = &sErrorFormatterList; *lfp != nullptr;)
146 : {
147 : // Remove the formatter from the global list, if found.
148 19 : if (*lfp == errFormatter)
149 : {
150 10 : *lfp = errFormatter->Next;
151 : }
152 : else
153 : {
154 9 : lfp = &(*lfp)->Next;
155 : }
156 : }
157 11 : }
158 :
159 : #if !CHIP_CONFIG_CUSTOM_ERROR_FORMATTER
160 :
161 : /**
162 : * Generates a human-readable NULL-terminated C string describing the provided error.
163 : *
164 : * @param[in] buf Buffer into which the error string will be placed.
165 : * @param[in] bufSize Size of the supplied buffer in bytes.
166 : * @param[in] subsys A short string describing the subsystem that originated
167 : * the error, or NULL if the origin of the error is
168 : * unknown/unavailable. This string should be 10
169 : * characters or less.
170 : * @param[in] err The error to be formatted.
171 : * @param[in] desc A string describing the cause or meaning of the error,
172 : * or NULL if no such information is available.
173 : */
174 1047889 : DLL_EXPORT void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc)
175 : {
176 : #if CHIP_CONFIG_SHORT_ERROR_STR
177 :
178 : if (subsys == nullptr)
179 : {
180 : (void) snprintf(buf, bufSize, "Error " CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, err.AsInteger());
181 : }
182 : else
183 : {
184 : (void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err.AsInteger());
185 : }
186 :
187 : #else // CHIP_CONFIG_SHORT_ERROR_STR
188 :
189 1047889 : const char * subsysSep = " ";
190 1047889 : const char * descSep = ": ";
191 :
192 1047889 : if (subsys == nullptr)
193 : {
194 1046581 : subsys = "";
195 1046581 : subsysSep = "";
196 : }
197 1047889 : if (desc == nullptr)
198 : {
199 1046587 : desc = "";
200 1046587 : descSep = "";
201 : }
202 :
203 1047889 : (void) snprintf(buf, bufSize, "%s%sError 0x%08" PRIX32 "%s%s", subsys, subsysSep, err.AsInteger(), descSep, desc);
204 :
205 : #endif // CHIP_CONFIG_SHORT_ERROR_STR
206 1047889 : }
207 :
208 : #endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER
209 :
210 : } // namespace chip
|