| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * Copyright (c) 2013-2017 Nest Labs, 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. |
| */ |
| |
| /** |
| * @file |
| * This file implements functions to translate error codes used |
| * throughout the CHIP package into human-readable strings. |
| * |
| */ |
| |
| #ifndef __STDC_FORMAT_MACROS |
| #define __STDC_FORMAT_MACROS |
| #endif |
| |
| #include <inttypes.h> |
| #include <stdio.h> |
| |
| #include <lib/core/CHIPCore.h> |
| #include <lib/support/CodeUtils.h> |
| |
| namespace chip { |
| |
| /** |
| * Static buffer to store the formatted error string. |
| */ |
| static char sErrorStr[CHIP_CONFIG_ERROR_STR_SIZE]; |
| |
| /** |
| * Linked-list of error formatter functions. |
| */ |
| static ErrorFormatter * sErrorFormatterList = nullptr; |
| |
| /** |
| * This routine returns a human-readable NULL-terminated C string |
| * describing the provided error. |
| * |
| * @param[in] err The error for format and describe. |
| * |
| * @return A pointer to a NULL-terminated C string describing the |
| * provided error. |
| */ |
| DLL_EXPORT const char * ErrorStr(CHIP_ERROR err) |
| { |
| char * formattedError = sErrorStr; |
| uint16_t formattedSpace = sizeof(sErrorStr); |
| |
| #if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| const char * const file = err.GetFile(); |
| if (file != nullptr) |
| { |
| int n = snprintf(formattedError, formattedSpace, "%s:%u: ", file, err.GetLine()); |
| if (n > formattedSpace) |
| { |
| n = formattedSpace; |
| } |
| formattedError += n; |
| formattedSpace = static_cast<uint16_t>(formattedSpace - n); |
| } |
| if (err == CHIP_NO_ERROR) |
| { |
| (void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING); |
| return sErrorStr; |
| } |
| |
| #else // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| if (err == CHIP_NO_ERROR) |
| { |
| return CHIP_NO_ERROR_STRING; |
| } |
| |
| #endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| // Search the registered error formatter for one that will format the given |
| // error code. |
| for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next) |
| { |
| if (errFormatter->FormatError(formattedError, formattedSpace, err)) |
| { |
| return sErrorStr; |
| } |
| } |
| |
| // Use a default formatting if no formatter found. |
| FormatError(formattedError, formattedSpace, nullptr, err, nullptr); |
| return sErrorStr; |
| } |
| |
| /** |
| * Add a new error formatter function to the global list of error formatters. |
| * |
| * @param[in] errFormatter An ErrorFormatter structure containing a |
| * pointer to the new error function. Note |
| * that a pointer to the supplied ErrorFormatter |
| * structure will be retained by the function. |
| * Thus the memory for the structure must |
| * remain reserved. |
| */ |
| DLL_EXPORT void RegisterErrorFormatter(ErrorFormatter * errFormatter) |
| { |
| // Do nothing if a formatter with the same format function is already in the list. |
| for (ErrorFormatter * existingFormatter = sErrorFormatterList; existingFormatter != nullptr; |
| existingFormatter = existingFormatter->Next) |
| { |
| if (existingFormatter->FormatError == errFormatter->FormatError) |
| { |
| return; |
| } |
| } |
| |
| // Add the formatter to the global list. |
| errFormatter->Next = sErrorFormatterList; |
| sErrorFormatterList = errFormatter; |
| } |
| |
| /** |
| * Remove an error formatter function from the global list of error formatters. |
| * |
| * @param[in] errFormatter An ErrorFormatter structure containing a |
| * pointer to the new error function. |
| */ |
| DLL_EXPORT void DeregisterErrorFormatter(ErrorFormatter * errFormatter) |
| { |
| // Remove the formatter if present |
| for (ErrorFormatter ** lfp = &sErrorFormatterList; *lfp != nullptr; lfp = &(*lfp)->Next) |
| { |
| // Remove the formatter from the global list, if found. |
| if (*lfp == errFormatter) |
| { |
| *lfp = errFormatter->Next; |
| } |
| } |
| } |
| |
| #if !CHIP_CONFIG_CUSTOM_ERROR_FORMATTER |
| |
| /** |
| * Generates a human-readable NULL-terminated C string describing the provided error. |
| * |
| * @param[in] buf Buffer into which the error string will be placed. |
| * @param[in] bufSize Size of the supplied buffer in bytes. |
| * @param[in] subsys A short string describing the subsystem that originated |
| * the error, or NULL if the origin of the error is |
| * unknown/unavailable. This string should be 10 |
| * characters or less. |
| * @param[in] err The error to be formatted. |
| * @param[in] desc A string describing the cause or meaning of the error, |
| * or NULL if no such information is available. |
| */ |
| DLL_EXPORT void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc) |
| { |
| #if CHIP_CONFIG_SHORT_ERROR_STR |
| |
| if (subsys == NULL) |
| { |
| (void) snprintf(buf, bufSize, "Error " CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, err.AsInteger()); |
| } |
| else |
| { |
| (void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err.AsInteger()); |
| } |
| |
| #else // CHIP_CONFIG_SHORT_ERROR_STR |
| |
| const char * subsysSep = " "; |
| const char * descSep = ": "; |
| |
| if (subsys == nullptr) |
| { |
| subsys = ""; |
| subsysSep = ""; |
| } |
| if (desc == nullptr) |
| { |
| desc = ""; |
| descSep = ""; |
| } |
| |
| (void) snprintf(buf, bufSize, "%s%sError 0x%08" PRIX32 "%s%s", subsys, subsysSep, err.AsInteger(), descSep, desc); |
| |
| #endif // CHIP_CONFIG_SHORT_ERROR_STR |
| } |
| |
| #endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER |
| |
| } // namespace chip |