Improvements to XLCellValue

This commit is contained in:
troldal 2021-08-19 21:46:03 +02:00
parent dd408aca44
commit ce19f22f52
4 changed files with 179 additions and 500 deletions

View File

@ -20,7 +20,8 @@ Checks: >-
-bugprone-infinite-loop, -bugprone-infinite-loop,
-abseil-string-find-startswith, -abseil-string-find-startswith,
-abseil-string-find-str-contains, -abseil-string-find-str-contains,
-altera-unroll-loops -altera-unroll-loops,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay
WarningsAsErrors: '*' WarningsAsErrors: '*'
HeaderFilterRegex: '' HeaderFilterRegex: ''

View File

@ -58,6 +58,7 @@ YM M9 MM MM MM MM MM d' `MM. MM MM d' `MM.
// ===== OpenXLSX Includes ===== // // ===== OpenXLSX Includes ===== //
#include "OpenXLSX-Exports.hpp" #include "OpenXLSX-Exports.hpp"
#include "XLException.hpp"
#include "XLXmlParser.hpp" #include "XLXmlParser.hpp"
// ========== CLASS AND ENUM TYPE DEFINITIONS ========== // // ========== CLASS AND ENUM TYPE DEFINITIONS ========== //
@ -101,8 +102,33 @@ namespace OpenXLSX
* @tparam T The type of the argument (will be automatically deduced). * @tparam T The type of the argument (will be automatically deduced).
* @param value The value. * @param value The value.
*/ */
template<typename T> template<typename T,
XLCellValue(T value); // NOLINT typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, char*>>::type* =
nullptr>
XLCellValue(T value)
{ // NOLINT
// ===== If the argument is a bool, set the m_type attribute to Boolean.
if constexpr (std::is_integral_v<T> && std::is_same_v<T, bool>) m_type = XLValueType::Boolean;
// ===== If the argument is an integral type, set the m_type attribute to Integer.
else if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
m_type = XLValueType::Integer;
// ===== If the argument is a string type (i.e. is constructable from *char),
// ===== set the m_type attribute to String.
else if constexpr (std::is_constructible_v<T, char*> && !std::is_same_v<T, bool>)
m_type = XLValueType::String;
// ===== If the argument is a floating point type, set the m_type attribute to Float.
// ===== If not, a static_assert will result in compilation error.
else {
static_assert(std::is_floating_point_v<T>, "Invalid argument for constructing XLCellValue object");
m_type = XLValueType::Float;
}
m_value = value;
}
/** /**
* @brief Constructor taking a XLCellValueProxy object as argument. * @brief Constructor taking a XLCellValueProxy object as argument.
@ -142,84 +168,75 @@ namespace OpenXLSX
XLCellValue& operator=(XLCellValue&& other) noexcept; XLCellValue& operator=(XLCellValue&& other) noexcept;
/** /**
* @brief Templated assignment operator for integral and bool types. * @brief Templated copy assignment operator.
* @tparam T The type of the value argument.
* @param value The value.
* @return A reference to the assigned-to object.
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr>
XLCellValue& operator=(T value);
/**
* @brief Templated assignment operator for floating point types.
* @tparam T The type of the value argument.
* @param value The value.
* @return A reference to the assigned-to object.
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
XLCellValue& operator=(T value);
/**
* @brief Templated assignment operator for string types.
* @tparam T The type of the value argument. * @tparam T The type of the value argument.
* @param value The value. * @param value The value.
* @return A reference to the assigned-to object. * @return A reference to the assigned-to object.
*/ */
template<typename T, template<typename T,
typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type* = nullptr> typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, char*>>::type* =
XLCellValue& operator=(T value); nullptr>
XLCellValue& operator=(T value)
{
// ===== Implemented using copy-and-swap.
XLCellValue temp(value);
std::swap(*this, temp);
return *this;
}
/** /**
* @brief Templated setter for integral and bool types. * @brief Templated setter for integral and bool types.
* @tparam T The type of the value argument. * @tparam T The type of the value argument.
* @param numberValue The value * @param numberValue The value
*/ */
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr> template<typename T,
void set(T numberValue); typename std::enable_if<std::is_same_v<T, XLCellValue> || std::is_integral_v<T> || std::is_floating_point_v<T> ||
std::is_constructible_v<T, char*>>::type* = nullptr>
void set(T numberValue)
{
// ===== Implemented using the assignment operator.
*this = numberValue;
}
/** /**
* @brief Templated setter for floating point types. * @brief Templated getter.
* @tparam T The type of the value argument. * @tparam T The type of the value to be returned.
* @param numberValue The value * @return The value as a type T object.
*/ * @throws XLValueTypeError if the XLCellValue object does not contain a compatible type.
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
void set(T numberValue);
/**
* @brief Templated setter for string types.
* @tparam T The type of the value argument.
* @param numberValue The value
*/ */
template<typename T, template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value && typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, char*>>::type* =
std::is_constructible<T, const char*>::value, nullptr>
T>::type* = nullptr> T get() const
void set(T stringValue); {
try {
if constexpr (std::is_integral_v<T> && std::is_same_v<T, bool>) return std::get<bool>(m_value);
if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>) return static_cast<T>(std::get<int64_t>(m_value));
if constexpr (std::is_floating_point_v<T>) return static_cast<T>(std::get<double>(m_value));
if constexpr (std::is_constructible_v<T, char*> && !std::is_same_v<T, bool>) return std::get<const char*>(m_value);
}
catch (const std::bad_variant_access& e) {
throw XLValueTypeError("XLCellValue object does not contain the requested type.");
}
}
/** /**
* @brief Templated getter for integral and bool types. * @brief Explicit conversion operator for easy conversion to supported types.
* @tparam T The type of the value to be returned. * @tparam T The type to cast to.
* @return The value as a type T object. * @return The XLCellValue object cast to requested type.
*/ * @throws XLValueTypeError if the XLCellValue object does not contain a compatible type.
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr>
T get() const;
/**
* @brief Templated getter for floating point types.
* @tparam T The type of the value to be returned.
* @return The value as a type T object.
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
T get() const;
/**
* @brief Templated getter for string types.
* @tparam T The type of the value to be returned.
* @return The value as a type T object.
*/ */
template<typename T, template<typename T,
typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type* = nullptr> typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, char*>>::type* =
T get() const; nullptr>
explicit operator T() const
{
return this->get<T>();
}
/** /**
* @brief Clears the contents of the XLCellValue object. * @brief Clears the contents of the XLCellValue object.
@ -284,81 +301,64 @@ namespace OpenXLSX
* @param numberValue The value. * @param numberValue The value.
* @return A reference to the current object. * @return A reference to the current object.
*/ */
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr> template<typename T,
XLCellValueProxy& operator=(T numberValue); // NOLINT typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, const char*> ||
std::is_same_v<T, XLCellValue>>::type* = nullptr>
XLCellValueProxy& operator=(T value)
{ // NOLINT
if constexpr (std::is_integral_v<T> && std::is_same_v<T, bool>) // if bool
setBoolean(value);
else if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>) // if integer
setInteger(value);
else if constexpr (std::is_floating_point_v<T>) // if floating point
setFloat(value);
else if constexpr (std::is_constructible_v<T, const char*> && !std::is_same_v<T, bool> && !std::is_same_v<T, XLCellValue>) {
if constexpr (std::is_same<const char*, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value)
setString(value);
else if constexpr (std::is_same<std::string_view, T>::value)
setString(std::string(value).c_str());
else
setString(value.c_str());
}
if constexpr (std::is_same_v<T, XLCellValue>) {
switch (value.type()) {
case XLValueType::Boolean:
setBoolean(value.template get<bool>());
break;
case XLValueType::Integer:
setInteger(value.template get<int64_t>());
break;
case XLValueType::Float:
setFloat(value.template get<double>());
break;
case XLValueType::String:
setString(value.template get<const char*>());
break;
case XLValueType::Empty:
default:
break;
}
}
return *this;
}
/** /**
* @brief * @brief
* @tparam T * @tparam T
* @param numberValue * @param numberValue
* @return
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
XLCellValueProxy& operator=(T numberValue); // NOLINT
/**
* @brief
* @tparam T
* @param stringValue
* @return
*/ */
template<typename T, template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value && typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, const char*> ||
std::is_constructible<T, const char*>::value, std::is_same_v<T, XLCellValue>>::type* = nullptr>
T>::type* = nullptr> void set(T value) {
XLCellValueProxy& operator=(T stringValue); // NOLINT *this = value;
}
/**
* @brief
* @tparam T
* @param value
* @return
*/
template<typename T, typename std::enable_if<std::is_same<T, XLCellValue>::value, T>::type* = nullptr>
XLCellValueProxy& operator=(T value); // NOLINT
/**
* @brief
* @tparam T
* @param numberValue
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr>
void set(T numberValue);
/**
* @brief
* @tparam T
* @param numberValue
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
void set(T numberValue);
/**
* @brief
* @tparam T
* @param stringValue
*/
template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value &&
std::is_constructible<T, const char*>::value,
T>::type* = nullptr>
void set(T stringValue);
/**
* @brief
* @tparam T
* @return
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type* = nullptr>
T get() const;
/**
* @brief
* @tparam T
* @return
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type* = nullptr>
T get() const;
/** /**
* @brief * @brief
@ -366,8 +366,11 @@ namespace OpenXLSX
* @return * @return
*/ */
template<typename T, template<typename T,
typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type* = nullptr> typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_constructible_v<T, char*>>::type* =
T get() const; nullptr>
T get() const {
return getValue().get<T>();
}
/** /**
* @brief Clear the contents of the cell. * @brief Clear the contents of the cell.
@ -466,343 +469,6 @@ namespace OpenXLSX
} // namespace OpenXLSX } // namespace OpenXLSX
// ========== TEMPLATE MEMBER IMPLEMENTATIONS ========== // (XLCellValue)
namespace OpenXLSX
{
/**
* @details This is a templated constructor for XLCellValue, taking any value as an argument; however, the
* argument will be evaluated at compile time to ensure that it is convertible to a valid cell value type.
* @pre The value argument must be convertible to a valid cell type.
* @post A valid XLCellValue object is constructed.
*/
template<typename T>
XLCellValue::XLCellValue(T value)
{
// ===== If the argument is a bool, set the m_type attribute to Boolean.
if constexpr (std::is_integral_v<T> && std::is_same_v<T, bool>)
m_type = XLValueType::Boolean;
// ===== If the argument is an integral type, set the m_type attribute to Integer.
else if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
m_type = XLValueType::Integer;
// ===== If the argument is a string type (i.e. is constructable from *char),
// ===== set the m_type attribute to String.
else if constexpr (std::is_constructible_v<T, char*> && !std::is_same_v<T, bool>)
m_type = XLValueType::String;
// ===== If the argument is a floating point type, set the m_type attribute to Float.
// ===== If not, a static_assert will result in compilation error.
else {
static_assert(std::is_floating_point_v<T>, "Invalid argument for constructing XLCellValue object");
m_type = XLValueType::Float;
}
m_value = value;
}
/**
* @details Templated assignment operator for integral and bool types. This assignment operator function
* accepts only bool and integer type values.
* @pre The value argument must be convertible to an integer or bool value.
* @post The assigned-to object contains a valid value.
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
XLCellValue& XLCellValue::operator=(T value)
{
// ===== Implemented using copy-and-swap.
XLCellValue temp(value);
std::swap(*this, temp);
return *this;
// OLD IMPLEMENTATION:
// if constexpr (std::is_integral_v<T> && std::is_same_v<T, bool>)
// m_type = XLValueType::Boolean;
// else
// m_type = XLValueType::Integer;
//
// m_value = value;
// return *this;
}
/**
* @details Templated assignment operator for floating point types. This assignment operator function
* accepts only floating point type values.
* @pre The value argument must be convertible to a floating-point value.
* @post The assigned-to object contains a valid value.
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
XLCellValue& XLCellValue::operator=(T value)
{
// ===== Implemented using copy-and-swap.
XLCellValue temp(value);
std::swap(*this, temp);
return *this;
// OLD IMPLEMENTATION:
// m_type = XLValueType::Float;
// m_value = value;
// return *this;
}
/**
* @details Templated assignment operator for string types. This assignment operator function
* accepts only types that can be constructed from *char.
* @pre The value argument must be constructible from *char.
* @post The assigned-to object contains a valid value.
*/
template<typename T, typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type*>
XLCellValue& XLCellValue::operator=(T value)
{
// ===== Implemented using copy-and-swap.
XLCellValue temp(value);
std::swap(*this, temp);
return *this;
// OLD IMPLEMENTATION:
// m_type = XLValueType::String;
// m_value = value;
// return *this;
}
/**
* @brief Templated setter for integral and bool types. This setter function
* accepts only bool and integer type values.
* @pre The numberValue argument must be convertible to an integer or bool value.
* @post The assigned-to object contains a valid value.
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
void XLCellValue::set(T numberValue)
{
// ===== Implemented using the assignment operator.
*this = numberValue;
}
/**
* @brief Templated setter for floating point types. This setter function
* accepts only floating point type values.
* @pre The numberValue argument must be convertible to an integer or bool value.
* @post The assigned-to object contains a valid value.
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
void XLCellValue::set(T numberValue)
{
// ===== Implemented using the assignment operator.
*this = numberValue;
}
/**
* @brief Templated setter for string types. This setter function
* accepts only types that can be constructed from *char.
* @pre The numberValue argument must be constructible from *char.
* @post The assigned-to object contains a valid value.
*/
template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value &&
std::is_constructible<T, const char*>::value,
T>::type*>
void XLCellValue::set(T stringValue)
{
// ===== Implemented using the assignment operator.
*this = stringValue;
}
/**
* @details Templated getter for integral and bool types. This getter function
* accepts only bool and integer type template arguments.
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
T XLCellValue::get() const
{
if constexpr (std::is_same<T, bool>::value) {
return std::get<bool>(m_value);
}
else {
return static_cast<T>(std::get<int64_t>(m_value));
}
}
/**
* @details Templated getter for floating point types. This getter function
* accepts only floating point type template arguments.
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
T XLCellValue::get() const
{
return static_cast<T>(std::get<double>(m_value));
}
/**
* @details Templated getter for string types. This getter function
* accepts only template types that can be constructed from *char.
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type*>
T XLCellValue::get() const
{
return std::get<const char*>(m_value);
}
} // namespace OpenXLSX
// ========== TEMPLATE MEMBER IMPLEMENTATIONS ========== // (XLCellValueProxy)
namespace OpenXLSX
{
/**
* @details
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
XLCellValueProxy& XLCellValueProxy::operator=(T numberValue)
{
if constexpr (std::is_same<T, bool>::value) { // if bool
setBoolean(numberValue);
}
else { // if not bool
setInteger(numberValue);
}
return *this;
}
/**
* @details
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
XLCellValueProxy& XLCellValueProxy::operator=(T numberValue)
{
setFloat(numberValue);
return *this;
}
/**
* @details
* @pre
* @post
*/
template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value &&
std::is_constructible<T, const char*>::value,
T>::type*>
XLCellValueProxy& XLCellValueProxy::operator=(T stringValue)
{
if constexpr (std::is_same<const char*, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value)
setString(stringValue);
else if constexpr (std::is_same<std::string_view, T>::value)
setString(std::string(stringValue).c_str());
else
setString(stringValue.c_str());
return *this;
}
/**
* @details
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_same<T, XLCellValue>::value, T>::type*>
XLCellValueProxy& XLCellValueProxy::operator=(T value)
{
switch (value.type()) {
case XLValueType::Boolean:
setBoolean(value.template get<bool>());
break;
case XLValueType::Integer:
setInteger(value.template get<int64_t>());
break;
case XLValueType::Float:
setFloat(value.template get<double>());
break;
case XLValueType::String:
setString(value.template get<const char*>());
break;
case XLValueType::Empty:
default:
break;
}
return *this;
}
/**
* @details
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
void XLCellValueProxy::set(T numberValue)
{
*this = numberValue;
}
/**
* @details
* @pre
* @post
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
void XLCellValueProxy::set(T numberValue)
{
*this = numberValue;
}
/**
* @details
* @pre
* @post
*/
template<typename T,
typename std::enable_if<!std::is_same<T, XLCellValue>::value && !std::is_same<T, bool>::value &&
std::is_constructible<T, const char*>::value,
T>::type*>
void XLCellValueProxy::set(T stringValue)
{
*this = stringValue;
}
/**
* @brief
* @tparam T
* @return
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, int64_t>::type*>
T XLCellValueProxy::get() const
{
return getValue().get<T>();
}
/**
* @brief
* @tparam T
* @return
*/
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, long double>::type*>
T XLCellValueProxy::get() const
{
return getValue().get<T>();
}
/**
* @brief
* @tparam T
* @return
*/
template<typename T, typename std::enable_if<std::is_constructible<T, char*>::value && !std::is_same<T, bool>::value, char*>::type*>
T XLCellValueProxy::get() const
{
return getValue().get<T>();
}
} // namespace OpenXLSX
// ========== FRIEND FUNCTION IMPLEMENTATIONS ========== // // ========== FRIEND FUNCTION IMPLEMENTATIONS ========== //
namespace OpenXLSX namespace OpenXLSX
{ {

View File

@ -58,18 +58,33 @@ YM M9 MM MM MM MM MM d' `MM. MM MM d' `MM.
namespace OpenXLSX namespace OpenXLSX
{ {
/**
* @brief
*/
class OPENXLSX_EXPORT XLException : public std::runtime_error class OPENXLSX_EXPORT XLException : public std::runtime_error
{ {
public: public:
inline explicit XLException(const std::string& err) : runtime_error(err) {}; inline explicit XLException(const std::string& err) : runtime_error(err) {};
}; };
/**
* @brief
*/
class OPENXLSX_EXPORT XLOverflowError : public XLException class OPENXLSX_EXPORT XLOverflowError : public XLException
{ {
public: public:
inline explicit XLOverflowError(const std::string& err) : XLException(err) {}; inline explicit XLOverflowError(const std::string& err) : XLException(err) {};
}; };
/**
* @brief
*/
class OPENXLSX_EXPORT XLValueTypeError : public XLException
{
public:
inline explicit XLValueTypeError(const std::string& err) : XLException(err) {};
};
} // namespace OpenXLSX } // namespace OpenXLSX
#pragma warning(pop) #pragma warning(pop)

View File

@ -127,12 +127,11 @@ std::string XLCellValue::typeAsString() const
* @pre The cell and cellNode pointers must not be nullptr and must point to valid objects. * @pre The cell and cellNode pointers must not be nullptr and must point to valid objects.
* @post A valid XLCellValueProxy has been created. * @post A valid XLCellValueProxy has been created.
*/ */
XLCellValueProxy::XLCellValueProxy(XLCell* cell, XMLNode* cellNode) XLCellValueProxy::XLCellValueProxy(XLCell* cell, XMLNode* cellNode) : m_cell(cell), m_cellNode(cellNode)
: m_cell(cell), m_cellNode(cellNode)
{ {
assert(cell); assert(cell); // NOLINT
assert(cellNode); assert(cellNode); // NOLINT
assert(!cellNode->empty()); assert(!cellNode->empty()); // NOLINT
} }
/** /**
@ -197,8 +196,8 @@ XLCellValueProxy::operator XLCellValue()
XLCellValueProxy& XLCellValueProxy::clear() XLCellValueProxy& XLCellValueProxy::clear()
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== Remove the type attribute // ===== Remove the type attribute
m_cellNode->remove_attribute("t"); m_cellNode->remove_attribute("t");
@ -219,8 +218,8 @@ XLCellValueProxy& XLCellValueProxy::clear()
XLCellValueProxy& XLCellValueProxy::setError() XLCellValueProxy& XLCellValueProxy::setError()
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If the cell node doesn't have a type attribute, create it. // ===== If the cell node doesn't have a type attribute, create it.
if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t"); if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t");
@ -244,8 +243,8 @@ XLCellValueProxy& XLCellValueProxy::setError()
XLValueType XLCellValueProxy::type() const XLValueType XLCellValueProxy::type() const
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If neither a Type attribute or a getValue node is present, the cell is empty. // ===== If neither a Type attribute or a getValue node is present, the cell is empty.
if (!m_cellNode->attribute("t") && !m_cellNode->child("v")) return XLValueType::Empty; if (!m_cellNode->attribute("t") && !m_cellNode->child("v")) return XLValueType::Empty;
@ -313,8 +312,8 @@ std::string XLCellValueProxy::typeAsString() const
void XLCellValueProxy::setInteger(int64_t numberValue) void XLCellValueProxy::setInteger(int64_t numberValue)
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If the cell node doesn't have a value child node, create it. // ===== If the cell node doesn't have a value child node, create it.
if (!m_cellNode->child("v")) m_cellNode->append_child("v"); if (!m_cellNode->child("v")) m_cellNode->append_child("v");
@ -338,8 +337,8 @@ void XLCellValueProxy::setInteger(int64_t numberValue)
void XLCellValueProxy::setBoolean(bool numberValue) void XLCellValueProxy::setBoolean(bool numberValue)
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If the cell node doesn't have a type child node, create it. // ===== If the cell node doesn't have a type child node, create it.
if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t"); if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t");
@ -366,8 +365,8 @@ void XLCellValueProxy::setBoolean(bool numberValue)
void XLCellValueProxy::setFloat(double numberValue) void XLCellValueProxy::setFloat(double numberValue)
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If the cell node doesn't have a value child node, create it. // ===== If the cell node doesn't have a value child node, create it.
if (!m_cellNode->child("v")) m_cellNode->append_child("v"); if (!m_cellNode->child("v")) m_cellNode->append_child("v");
@ -391,8 +390,8 @@ void XLCellValueProxy::setFloat(double numberValue)
void XLCellValueProxy::setString(const char* stringValue) void XLCellValueProxy::setString(const char* stringValue)
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
// ===== If the cell node doesn't have a type child node, create it. // ===== If the cell node doesn't have a type child node, create it.
if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t"); if (!m_cellNode->attribute("t")) m_cellNode->append_attribute("t");
@ -404,9 +403,7 @@ void XLCellValueProxy::setString(const char* stringValue)
m_cellNode->attribute("t").set_value("s"); m_cellNode->attribute("t").set_value("s");
// ===== Get or create the index in the XLSharedStrings object. // ===== Get or create the index in the XLSharedStrings object.
auto index = auto index = (m_cell->m_sharedStrings->stringExists(stringValue) ? m_cell->m_sharedStrings->getStringIndex(stringValue)
(m_cell->m_sharedStrings->stringExists(stringValue)
? m_cell->m_sharedStrings->getStringIndex(stringValue)
: m_cell->m_sharedStrings->appendString(stringValue)); : m_cell->m_sharedStrings->appendString(stringValue));
// ===== Set the text of the value node. // ===== Set the text of the value node.
@ -432,29 +429,29 @@ void XLCellValueProxy::setString(const char* stringValue)
XLCellValue XLCellValueProxy::getValue() const XLCellValue XLCellValueProxy::getValue() const
{ {
// ===== Check that the m_cellNode is valid. // ===== Check that the m_cellNode is valid.
assert(m_cellNode); assert(m_cellNode); // NOLINT
assert(!m_cellNode->empty()); assert(!m_cellNode->empty()); // NOLINT
switch (type()) { switch (type()) {
case XLValueType::Empty: case XLValueType::Empty:
return XLCellValue().clear(); return XLCellValue().clear();
case XLValueType::Float: case XLValueType::Float:
return XLCellValue(m_cellNode->child("v").text().as_double()); return XLCellValue{ m_cellNode->child("v").text().as_double() };
case XLValueType::Integer: case XLValueType::Integer:
return XLCellValue(m_cellNode->child("v").text().as_llong()); return XLCellValue{ m_cellNode->child("v").text().as_llong() };
case XLValueType::String: case XLValueType::String:
if (strcmp(m_cellNode->attribute("t").value(), "s") == 0) if (strcmp(m_cellNode->attribute("t").value(), "s") == 0)
return XLCellValue(m_cell->m_sharedStrings->getString(static_cast<uint32_t>(m_cellNode->child("v").text().as_ullong()))); return XLCellValue{ m_cell->m_sharedStrings->getString(static_cast<uint32_t>(m_cellNode->child("v").text().as_ullong())) };
else if (strcmp(m_cellNode->attribute("t").value(), "str") == 0) else if (strcmp(m_cellNode->attribute("t").value(), "str") == 0)
return XLCellValue(m_cellNode->child("v").text().get()); return XLCellValue{ m_cellNode->child("v").text().get() };
else else
throw XLException("Unknown string type"); throw XLException("Unknown string type");
case XLValueType::Boolean: case XLValueType::Boolean:
return XLCellValue(m_cellNode->child("v").text().as_bool()); return XLCellValue{ m_cellNode->child("v").text().as_bool() };
default: default:
return XLCellValue().setError(); return XLCellValue().setError();