mirror of
https://github.com/troldal/OpenXLSX.git
synced 2025-05-09 02:11:09 +08:00
Improvements to XLCellValue
This commit is contained in:
parent
dd408aca44
commit
ce19f22f52
@ -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: ''
|
||||||
|
@ -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.
|
||||||
@ -248,7 +265,7 @@ namespace OpenXLSX
|
|||||||
private:
|
private:
|
||||||
//---------- Private Member Variables ---------- //
|
//---------- Private Member Variables ---------- //
|
||||||
|
|
||||||
std::variant<const char*, int64_t, double, bool> m_value { "" }; /**< The value contained in the cell. */
|
std::variant<const char*, int64_t, double, bool> m_value { "" }; /**< The value contained in the cell. */
|
||||||
XLValueType m_type { XLValueType::Empty }; /**< The value type of the cell. */
|
XLValueType m_type { XLValueType::Empty }; /**< The value type of the cell. */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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,10 +403,8 @@ 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->appendString(stringValue));
|
||||||
? m_cell->m_sharedStrings->getStringIndex(stringValue)
|
|
||||||
: m_cell->m_sharedStrings->appendString(stringValue));
|
|
||||||
|
|
||||||
// ===== Set the text of the value node.
|
// ===== Set the text of the value node.
|
||||||
m_cellNode->child("v").text().set(index);
|
m_cellNode->child("v").text().set(index);
|
||||||
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user