blob: f6cee466679f17805e2baa6c0e0c25dd09e73cc9 [file] [log] [blame]
/*
*
* 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 <core/CHIPCore.h>
#include <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(int32_t err)
{
if (err == 0)
{
return "No Error";
}
// 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(sErrorStr, sizeof(sErrorStr), err))
{
return sErrorStr;
}
}
// Use a default formatting if no formatter found.
FormatError(sErrorStr, sizeof(sErrorStr), 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, int32_t 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);
}
else
{
(void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err);
}
#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 %" PRId32 " (0x%08" PRIX32 ")%s%s", subsys, subsysSep, err, static_cast<uint32_t>(err),
descSep, desc);
#endif // CHIP_CONFIG_SHORT_ERROR_STR
}
#endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER
} // namespace chip