Files
Alicho/src/common/error.cpp
2025-10-24 18:17:58 +08:00

297 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ================================================================================================
// Audio Backend - 错误处理和异常类实现
// ================================================================================================
#include "error.h"
#include <algorithm>
#include <unordered_map>
#if ALICHO_PLATFORM_WINDOWS
#include <windows.h>
#elif ALICHO_PLATFORM_UNIX
#include <errno.h>
#endif
namespace audio_backend::common {
// ================================================================================================
// 错误码描述映射
// ================================================================================================
static const std::unordered_map<ErrorCode, std::string> error_descriptions = {
// 通用错误
{ErrorCode::SUCCESS, "操作成功"},
{ErrorCode::UNKNOWN_ERROR, "未知错误"},
{ErrorCode::INVALID_ARGUMENT, "无效参数"},
{ErrorCode::INVALID_OPERATION, "无效操作"},
{ErrorCode::NOT_IMPLEMENTED, "功能未实现"},
{ErrorCode::OUT_OF_MEMORY, "内存不足"},
{ErrorCode::OPERATION_TIMED_OUT, "操作超时"},
{ErrorCode::NOT_INITIALIZED, "未初始化"},
{ErrorCode::ALREADY_INITIALIZED, "已经初始化"},
// 文件和I/O错误
{ErrorCode::FILE_NOT_FOUND, "文件未找到"},
{ErrorCode::FILE_ACCESS_DENIED, "文件访问被拒绝"},
{ErrorCode::FILE_READ_ERROR, "文件读取错误"},
{ErrorCode::FILE_WRITE_ERROR, "文件写入错误"},
{ErrorCode::FILE_FORMAT_ERROR, "文件格式错误"},
// 音频处理错误
{ErrorCode::AUDIO_FORMAT_ERROR, "音频格式错误"},
{ErrorCode::AUDIO_DEVICE_ERROR, "音频设备错误"},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, "音频缓冲区欠载"},
{ErrorCode::AUDIO_BUFFER_OVERRUN, "音频缓冲区溢出"},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, "采样率不匹配"},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, "声道数不匹配"},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, "插件加载错误"},
{ErrorCode::PLUGIN_NOT_FOUND, "插件未找到"},
{ErrorCode::PLUGIN_VERSION_MISMATCH, "插件版本不匹配"},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, "插件初始化错误"},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, "插件通信错误"},
{ErrorCode::PLUGIN_EXECUTION_ERROR, "插件执行错误"},
{ErrorCode::PLUGIN_TIMEOUT, "插件超时"},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, "通信错误"},
{ErrorCode::CONNECTION_ERROR, "连接错误"},
{ErrorCode::DISCONNECTED, "连接已断开"},
{ErrorCode::MESSAGE_FORMAT_ERROR, "消息格式错误"},
{ErrorCode::PROTOCOL_ERROR, "协议错误"},
{ErrorCode::TIMEOUT, "超时"},
// 系统错误
{ErrorCode::SYSTEM_ERROR, "系统错误"},
{ErrorCode::PERMISSION_DENIED, "权限被拒绝"},
{ErrorCode::NOT_ENOUGH_RESOURCES, "资源不足"}
};
// ================================================================================================
// 错误分类映射
// ================================================================================================
static const std::unordered_map<ErrorCode, ErrorCategory> error_categories = {
// 通用错误
{ErrorCode::SUCCESS, ErrorCategory::GENERAL},
{ErrorCode::UNKNOWN_ERROR, ErrorCategory::GENERAL},
{ErrorCode::INVALID_ARGUMENT, ErrorCategory::GENERAL},
{ErrorCode::INVALID_OPERATION, ErrorCategory::GENERAL},
{ErrorCode::NOT_IMPLEMENTED, ErrorCategory::GENERAL},
{ErrorCode::OUT_OF_MEMORY, ErrorCategory::GENERAL},
{ErrorCode::OPERATION_TIMED_OUT, ErrorCategory::GENERAL},
{ErrorCode::NOT_INITIALIZED, ErrorCategory::GENERAL},
{ErrorCode::ALREADY_INITIALIZED, ErrorCategory::GENERAL},
// 文件错误
{ErrorCode::FILE_NOT_FOUND, ErrorCategory::FILE},
{ErrorCode::FILE_ACCESS_DENIED, ErrorCategory::FILE},
{ErrorCode::FILE_READ_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_WRITE_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_FORMAT_ERROR, ErrorCategory::FILE},
// 音频错误
{ErrorCode::AUDIO_FORMAT_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_DEVICE_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_OVERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, ErrorCategory::AUDIO},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_NOT_FOUND, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_VERSION_MISMATCH, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_EXECUTION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_TIMEOUT, ErrorCategory::PLUGIN},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::CONNECTION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::DISCONNECTED, ErrorCategory::COMMUNICATION},
{ErrorCode::MESSAGE_FORMAT_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::PROTOCOL_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::TIMEOUT, ErrorCategory::COMMUNICATION},
// 系统错误
{ErrorCode::SYSTEM_ERROR, ErrorCategory::SYSTEM},
{ErrorCode::PERMISSION_DENIED, ErrorCategory::SYSTEM},
{ErrorCode::NOT_ENOUGH_RESOURCES, ErrorCategory::SYSTEM}
};
// ================================================================================================
// 公共函数实现
// ================================================================================================
ErrorCategory get_error_category(ErrorCode code) {
auto it = error_categories.find(code);
if (it != error_categories.end()) {
return it->second;
}
return ErrorCategory::GENERAL;
}
std::string get_error_description(ErrorCode code) {
auto it = error_descriptions.find(code);
if (it != error_descriptions.end()) {
return it->second;
}
return "未知错误代码: " + std::to_string(static_cast<int>(code));
}
std::exception_ptr create_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
ErrorCategory category = get_error_category(code);
try {
switch (category) {
case ErrorCategory::FILE:
throw FileException(code, message, details);
case ErrorCategory::AUDIO:
throw AudioException(code, message, details);
case ErrorCategory::PLUGIN:
throw PluginException(code, message, details);
case ErrorCategory::COMMUNICATION:
throw CommunicationException(code, message, details);
case ErrorCategory::SYSTEM:
throw SystemException(code, message, details);
default:
throw AudioBackendException(code, message, details);
}
} catch (...) {
return std::current_exception();
}
}
void throw_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
std::rethrow_exception(create_exception(code, message, details));
}
void check_error(bool condition,
ErrorCode error_code,
const std::string& message,
const std::string& details) {
if (condition) {
throw_exception(error_code, message, details);
}
}
ErrorCode system_error_to_error_code(int system_error) {
#if ALICHO_PLATFORM_WINDOWS
switch (system_error) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return ErrorCode::FILE_NOT_FOUND;
case ERROR_ACCESS_DENIED:
return ErrorCode::FILE_ACCESS_DENIED;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
return ErrorCode::OUT_OF_MEMORY;
case ERROR_TIMEOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case ERROR_INVALID_PARAMETER:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#elif ALICHO_PLATFORM_UNIX
switch (system_error) {
case ENOENT:
return ErrorCode::FILE_NOT_FOUND;
case EACCES:
case EPERM:
return ErrorCode::FILE_ACCESS_DENIED;
case ENOMEM:
return ErrorCode::OUT_OF_MEMORY;
case ETIMEDOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case EINVAL:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#else
return ErrorCode::SYSTEM_ERROR;
#endif
}
ErrorCode std_error_to_error_code(const std::error_code& ec) {
if (ec.category() == std::generic_category()) {
return system_error_to_error_code(ec.value());
} else if (ec.category() == AudioBackendErrorCategory::instance()) {
return static_cast<ErrorCode>(ec.value());
} else {
return ErrorCode::SYSTEM_ERROR;
}
}
// ================================================================================================
// ErrorHandler实现
// ================================================================================================
void ErrorHandler::add_error_handler(const ErrorCallback& handler) {
handlers_.push_back(handler);
}
void ErrorHandler::remove_error_handler(const ErrorCallback& handler) {
// 注意这个比较可能不会按预期工作因为std::function的比较很复杂
// 在实际使用中可能需要使用其他方式来管理处理器比如返回ID
auto it = std::find_if(handlers_.begin(), handlers_.end(),
[&handler](const ErrorCallback& h) {
// 这里的比较不太可靠,应该考虑使用其他方式
return &h == &handler;
});
if (it != handlers_.end()) {
handlers_.erase(it);
}
}
void ErrorHandler::handle_error(const AudioBackendException& exception) {
for (const auto& handler : handlers_) {
try {
handler(exception);
} catch (...) {
// 忽略错误处理器中的异常,防止无限递归
}
}
}
void ErrorHandler::handle_error(ErrorCode code,
const std::string& message,
const std::string& details) {
try {
AudioBackendException exception(code, message, details);
handle_error(exception);
} catch (...) {
// 忽略创建异常时的错误
}
}
void ErrorHandler::handle_exception(std::exception_ptr eptr) {
if (!eptr) return;
try {
std::rethrow_exception(eptr);
} catch (const AudioBackendException& e) {
handle_error(e);
} catch (const std::exception& e) {
// 对于其他标准异常创建一个通用的AudioBackendException
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, e.what());
handle_error(wrapper);
} catch (...) {
// 对于其他异常,创建一个未知错误
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, "未知异常类型");
handle_error(wrapper);
}
}
void ErrorHandler::clear_handlers() {
handlers_.clear();
}
} // namespace audio_backend::common