-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#1] Add CppRuntimeException from Zserio C++ runtime
* without support for bitmasks * new support for std::string_view
- Loading branch information
Showing
5 changed files
with
395 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#include <algorithm> | ||
#include <array> | ||
#include <cstring> | ||
|
||
#include "zserio/CppRuntimeException.h" | ||
|
||
namespace zserio | ||
{ | ||
|
||
CppRuntimeException::CppRuntimeException(const char* message) : | ||
m_buffer() | ||
{ | ||
append(message); | ||
} | ||
|
||
const char* CppRuntimeException::what() const noexcept | ||
{ | ||
return m_buffer.data(); | ||
} | ||
|
||
void CppRuntimeException::append(const char* message) | ||
{ | ||
const size_t available = m_buffer.size() - 1 - m_len; | ||
const size_t numCharsToAppend = strnlen(message, available); | ||
appendImpl(Span<const char>(message, numCharsToAppend)); | ||
} | ||
|
||
void CppRuntimeException::append(const char* message, size_t messageLen) | ||
{ | ||
const size_t available = m_buffer.size() - 1 - m_len; | ||
const size_t numCharsToAppend = std::min(messageLen, available); | ||
appendImpl(Span<const char>(message, numCharsToAppend)); | ||
} | ||
|
||
void CppRuntimeException::appendImpl(Span<const char> message) | ||
{ | ||
if (message.size() > 0) | ||
{ | ||
(void)std::copy(message.begin(), message.end(), m_buffer.begin() + m_len); | ||
m_len += message.size(); | ||
} | ||
m_buffer.at(m_len) = '\0'; | ||
} | ||
|
||
CppRuntimeException& operator<<(CppRuntimeException& exception, const char* message) | ||
{ | ||
exception.append(message); | ||
return exception; | ||
} | ||
|
||
CppRuntimeException& operator<<(CppRuntimeException& exception, bool value) | ||
{ | ||
return exception << (value ? "true" : "false"); | ||
} | ||
|
||
CppRuntimeException& operator<<(CppRuntimeException& exception, float value) | ||
{ | ||
std::array<char, 24> integerPartBuffer = {}; | ||
std::array<char, 24> floatingPartBuffer = {}; | ||
const char* integerPartString = nullptr; | ||
const char* floatingPartString = nullptr; | ||
convertFloatToString(integerPartBuffer, floatingPartBuffer, value, integerPartString, floatingPartString); | ||
CppRuntimeException& result = exception << integerPartString; | ||
if (floatingPartString != nullptr) | ||
{ | ||
result = result << "." << floatingPartString; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
CppRuntimeException& operator<<(CppRuntimeException& exception, double value) | ||
{ | ||
return exception << (static_cast<float>(value)); | ||
} | ||
|
||
CppRuntimeException& operator<<(CppRuntimeException& exception, std::string_view value) | ||
{ | ||
exception.append(value.data(), value.size()); | ||
return exception; | ||
} | ||
|
||
} // namespace zserio |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
#ifndef ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC | ||
#define ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC | ||
|
||
#include <array> | ||
#include <exception> | ||
#include <string> | ||
#include <string_view> | ||
#include <type_traits> | ||
#include <vector> | ||
|
||
#include "zserio/Span.h" | ||
#include "zserio/StringConvertUtil.h" | ||
|
||
namespace zserio | ||
{ | ||
|
||
/** | ||
* Exception thrown when an error within the Zserio C++ runtime library occurs. | ||
*/ | ||
class CppRuntimeException : public std::exception | ||
{ | ||
public: | ||
/** | ||
* Constructor. | ||
* | ||
* \param message Description of the error. | ||
*/ | ||
explicit CppRuntimeException(const char* message = ""); | ||
|
||
/** | ||
* Method generated by default. | ||
* \{ | ||
*/ | ||
~CppRuntimeException() override = default; | ||
|
||
CppRuntimeException(const CppRuntimeException& other) = default; | ||
CppRuntimeException& operator=(const CppRuntimeException& other) = default; | ||
|
||
CppRuntimeException(CppRuntimeException&& other) = default; | ||
CppRuntimeException& operator=(CppRuntimeException&& other) = default; | ||
/** | ||
* \} | ||
*/ | ||
|
||
const char* what() const noexcept override; | ||
|
||
/** | ||
* Appends a message to the description. | ||
* | ||
* \param message Description of the error to append. | ||
*/ | ||
void append(const char* message); | ||
|
||
/** | ||
* Appends a message of a known length to the description. | ||
* | ||
* \param message Description of the error to append. | ||
* \param messageLen Length of the message. | ||
*/ | ||
void append(const char* message, size_t messageLen); | ||
|
||
private: | ||
void appendImpl(Span<const char> message); | ||
|
||
std::array<char, 512> m_buffer; // note fixed sized array is deeply copied on copy operations and it's OK | ||
size_t m_len = 0; | ||
}; | ||
|
||
/** | ||
* Appends a message to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param message Description of the error to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, const char* message); | ||
|
||
/** | ||
* Appends a bool value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Bool value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, bool value); | ||
|
||
/** | ||
* Appends a float value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Float value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, float value); | ||
|
||
/** | ||
* Appends a double value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Double value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, double value); | ||
|
||
/** | ||
* Appends a string_view to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value String view to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, std::string_view value); | ||
|
||
/** | ||
* Appends an integral value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Integral value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, T value) | ||
{ | ||
std::array<char, 24> buffer = {}; | ||
const char* stringValue = convertIntToString(buffer, value); | ||
return exception << stringValue; | ||
} | ||
|
||
/** | ||
* Appends a string value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value String value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
template <typename ALLOC> | ||
CppRuntimeException& operator<<( | ||
CppRuntimeException& exception, const std::basic_string<char, std::char_traits<char>, ALLOC>& value) | ||
{ | ||
exception.append(value.c_str(), value.size()); | ||
return exception; | ||
} | ||
|
||
/** | ||
* Appends a vector value to the exception's description. | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Vector value to append. | ||
* | ||
* \return Reference to the exception to allow operator chaining. | ||
*/ | ||
template <typename T, typename ALLOC> | ||
CppRuntimeException& operator<<(CppRuntimeException& exception, const std::vector<T, ALLOC>& value) | ||
{ | ||
return exception << "vector([...], " << value.size() << ")"; | ||
} | ||
|
||
namespace detail | ||
{ | ||
|
||
// inspired by C++ ostreams - see https://cplusplus.github.io/LWG/issue1203 | ||
// note that e.g. in gcc implementation of ostreams there are two constraints, but the second one: | ||
// typename = decltype(std::declval<EXCEPTION&>() << std::declval<const VALUE&>()) | ||
// is probably unnecessary and since it caused a compilation error in MSVC 2017 Conformance Mode, | ||
// we intentionally skipped it (even though it was probably a compiler bug) | ||
template <typename EXCEPTION, typename VALUE, | ||
typename = typename std::enable_if<std::is_base_of<CppRuntimeException, EXCEPTION>::value, int>::type> | ||
using CppRuntimeExceptionRValueInsertion = EXCEPTION&&; | ||
|
||
} // namespace detail | ||
|
||
/** | ||
* Appends any value for which operator<< is implemented to the exception's description. | ||
* | ||
* Overload for rvalue to enable operator<< on a temporary object, .e.g. CppRuntimeException() << "value". | ||
* Moreover note that this overload preserves the concrete type of the exception! | ||
* | ||
* \param exception Exception to modify. | ||
* \param value Value to append. | ||
* | ||
* \return R-value reference to the original exception to allow operator chaining. | ||
*/ | ||
template <typename CPP_RUNTIME_EXCEPTION, typename T> | ||
detail::CppRuntimeExceptionRValueInsertion<CPP_RUNTIME_EXCEPTION, T> operator<<( | ||
CPP_RUNTIME_EXCEPTION&& exception, const T& value) | ||
{ | ||
exception << value; | ||
return std::forward<CPP_RUNTIME_EXCEPTION>(exception); | ||
} | ||
|
||
} // namespace zserio | ||
|
||
#endif // ifndef ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.