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 : #ifndef __STDC_FORMAT_MACROS 21 : #define __STDC_FORMAT_MACROS 22 : #endif 23 : 24 : #include <lib/core/CHIPConfig.h> 25 : #include <lib/core/CHIPError.h> 26 : #include <lib/support/DLLUtil.h> 27 : 28 : #include <inttypes.h> 29 : #include <stdio.h> 30 : 31 : namespace chip { 32 : 33 : /** 34 : * Static buffer to store the formatted error string. 35 : */ 36 : static char sErrorStr[CHIP_CONFIG_ERROR_STR_SIZE]; 37 : 38 : /** 39 : * Linked-list of error formatter functions. 40 : */ 41 : static ErrorFormatter * sErrorFormatterList = nullptr; 42 : 43 : /** 44 : * This routine returns a human-readable NULL-terminated C string 45 : * describing the provided error. 46 : * 47 : * @param[in] err The error for format and describe. 48 : * 49 : * @return A pointer to a NULL-terminated C string describing the 50 : * provided error. 51 : */ 52 3138 : DLL_EXPORT const char * ErrorStr(CHIP_ERROR err) 53 : { 54 3138 : char * formattedError = sErrorStr; 55 3138 : uint16_t formattedSpace = sizeof(sErrorStr); 56 : 57 : #if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR 58 : 59 3138 : const char * const file = err.GetFile(); 60 3138 : if (file != nullptr) 61 : { 62 3123 : int n = snprintf(formattedError, formattedSpace, "%s:%u: ", file, err.GetLine()); 63 3123 : if (n > formattedSpace) 64 : { 65 0 : n = formattedSpace; 66 : } 67 3123 : formattedError += n; 68 3123 : formattedSpace = static_cast<uint16_t>(formattedSpace - n); 69 : } 70 3138 : if (err == CHIP_NO_ERROR) 71 : { 72 2446 : (void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING); 73 2446 : return sErrorStr; 74 : } 75 : 76 : #else // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR 77 : 78 : if (err == CHIP_NO_ERROR) 79 : { 80 : return CHIP_NO_ERROR_STRING; 81 : } 82 : 83 : #endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR 84 : 85 : // Search the registered error formatter for one that will format the given 86 : // error code. 87 2054 : for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next) 88 : { 89 1977 : if (errFormatter->FormatError(formattedError, formattedSpace, err)) 90 : { 91 615 : return sErrorStr; 92 : } 93 : } 94 : 95 : // Use a default formatting if no formatter found. 96 77 : FormatError(formattedError, formattedSpace, nullptr, err, nullptr); 97 77 : return sErrorStr; 98 : } 99 : 100 : /** 101 : * Add a new error formatter function to the global list of error formatters. 102 : * 103 : * @param[in] errFormatter An ErrorFormatter structure containing a 104 : * pointer to the new error function. Note 105 : * that a pointer to the supplied ErrorFormatter 106 : * structure will be retained by the function. 107 : * Thus the memory for the structure must 108 : * remain reserved. 109 : */ 110 692 : DLL_EXPORT void RegisterErrorFormatter(ErrorFormatter * errFormatter) 111 : { 112 : // Do nothing if a formatter with the same format function is already in the list. 113 1379 : for (ErrorFormatter * existingFormatter = sErrorFormatterList; existingFormatter != nullptr; 114 687 : existingFormatter = existingFormatter->Next) 115 : { 116 1152 : if (existingFormatter->FormatError == errFormatter->FormatError) 117 : { 118 465 : return; 119 : } 120 : } 121 : 122 : // Add the formatter to the global list. 123 227 : errFormatter->Next = sErrorFormatterList; 124 227 : sErrorFormatterList = errFormatter; 125 : } 126 : 127 : /** 128 : * Remove an error formatter function from the global list of error formatters. 129 : * 130 : * @param[in] errFormatter An ErrorFormatter structure containing a 131 : * pointer to the new error function. 132 : */ 133 2 : DLL_EXPORT void DeregisterErrorFormatter(ErrorFormatter * errFormatter) 134 : { 135 : // Remove the formatter if present 136 6 : for (ErrorFormatter ** lfp = &sErrorFormatterList; *lfp != nullptr; lfp = &(*lfp)->Next) 137 : { 138 : // Remove the formatter from the global list, if found. 139 4 : if (*lfp == errFormatter) 140 : { 141 1 : *lfp = errFormatter->Next; 142 : } 143 : } 144 2 : } 145 : 146 : #if !CHIP_CONFIG_CUSTOM_ERROR_FORMATTER 147 : 148 : /** 149 : * Generates a human-readable NULL-terminated C string describing the provided error. 150 : * 151 : * @param[in] buf Buffer into which the error string will be placed. 152 : * @param[in] bufSize Size of the supplied buffer in bytes. 153 : * @param[in] subsys A short string describing the subsystem that originated 154 : * the error, or NULL if the origin of the error is 155 : * unknown/unavailable. This string should be 10 156 : * characters or less. 157 : * @param[in] err The error to be formatted. 158 : * @param[in] desc A string describing the cause or meaning of the error, 159 : * or NULL if no such information is available. 160 : */ 161 697 : DLL_EXPORT void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc) 162 : { 163 : #if CHIP_CONFIG_SHORT_ERROR_STR 164 : 165 : if (subsys == nullptr) 166 : { 167 : (void) snprintf(buf, bufSize, "Error " CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, err.AsInteger()); 168 : } 169 : else 170 : { 171 : (void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err.AsInteger()); 172 : } 173 : 174 : #else // CHIP_CONFIG_SHORT_ERROR_STR 175 : 176 697 : const char * subsysSep = " "; 177 697 : const char * descSep = ": "; 178 : 179 697 : if (subsys == nullptr) 180 : { 181 79 : subsys = ""; 182 79 : subsysSep = ""; 183 : } 184 697 : if (desc == nullptr) 185 : { 186 79 : desc = ""; 187 79 : descSep = ""; 188 : } 189 : 190 697 : (void) snprintf(buf, bufSize, "%s%sError 0x%08" PRIX32 "%s%s", subsys, subsysSep, err.AsInteger(), descSep, desc); 191 : 192 : #endif // CHIP_CONFIG_SHORT_ERROR_STR 193 697 : } 194 : 195 : #endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER 196 : 197 : } // namespace chip