Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#================= Project Setup ==========================

# CMake
cmake_minimum_required(VERSION 3.23.0...3.26.0)
cmake_minimum_required(VERSION 3.23.0...3.31.0)

# Project
# NOTE: For versions stick to w.x.y.z, where z is generally
# avoided and only used for hotfixes. DON'T USE TRAILING
# ZEROS IN VERSIONS
project(Qx
VERSION 0.6.2
VERSION 0.6.3
LANGUAGES CXX
DESCRIPTION "Qt Extensions Library"
)

# Get helper scripts
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake)
fetch_ob_cmake("v0.3.9")
fetch_ob_cmake("v0.3.10")

# Initialize project according to standard rules
include(OB/Project)
Expand Down
16 changes: 8 additions & 8 deletions lib/core/include/qx/core/qx-bitarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class QX_CORE_EXPORT BitArray : public QBitArray
{
//-Constructor--------------------------------------------------------------------------------------------------
public:
BitArray();
BitArray(int size, bool value = false);
BitArray() noexcept;
explicit BitArray(int size, bool value = false);

//-Class Functions----------------------------------------------------------------------------------------------
public:
Expand All @@ -38,7 +38,7 @@ class QX_CORE_EXPORT BitArray : public QBitArray
public:
template<typename T>
requires std::integral<T>
T toInteger()
T toInteger() const
{
int bitCount = sizeof(T)*8;
T integer = 0;
Expand All @@ -49,7 +49,7 @@ class QX_CORE_EXPORT BitArray : public QBitArray
return integer;
}

QByteArray toByteArray(QSysInfo::Endian endianness = QSysInfo::BigEndian);
QByteArray toByteArray(QSysInfo::Endian endianness = QSysInfo::BigEndian) const;

void append(bool bit = false);
void replace(const BitArray& bits, int start = 0, int length = -1);
Expand All @@ -62,15 +62,15 @@ class QX_CORE_EXPORT BitArray : public QBitArray
replace(converted, start, length);
}

BitArray subArray(int start, int length = -1);
BitArray subArray(int start, int length = -1) const;
BitArray takeFromStart(int length = -1);
BitArray takeFromEnd(int length = -1);

BitArray operator<<(int n);
BitArray operator<<(int n) const;
void operator<<=(int n);
BitArray operator>>(int n);
BitArray operator>>(int n) const;
void operator>>=(int n);
BitArray operator+(BitArray rhs);
BitArray operator+(BitArray rhs) const;
void operator+=(const BitArray& rhs);
};

Expand Down
66 changes: 53 additions & 13 deletions lib/core/include/qx/core/qx-json.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ class QX_CORE_EXPORT File
QString string() const;
};

class QX_CORE_EXPORT Data
{
public:
Data();

QString string() const;
};

class QX_CORE_EXPORT Document
{
private:
Expand Down Expand Up @@ -145,7 +153,7 @@ class QX_CORE_EXPORT ArrayElement
QString string() const;
};

using ContextNode = std::variant<File, Document, Object, ObjectKey, Array, ArrayElement>;
using ContextNode = std::variant<File, Data, Document, Object, ObjectKey, Array, ArrayElement>;

} // namespace QxJson

Expand All @@ -163,6 +171,7 @@ class QX_CORE_EXPORT JsonError final : public AbstractError<"Qx::JsonError", 5>
TypeMismatch,
EmptyDoc,
InvalidValue,
InvalidData,
MissingFile,
InaccessibleFile,
FileReadError,
Expand All @@ -177,6 +186,7 @@ class QX_CORE_EXPORT JsonError final : public AbstractError<"Qx::JsonError", 5>
{TypeMismatch, u"Value type mismatch."_s},
{EmptyDoc, u"The document is empty."_s},
{InvalidValue, u"Invalid value for type."_s},
{InvalidData, u"Data parse error."_s},
{MissingFile, u"File does not exist."_s},
{InaccessibleFile, u"Cannot open the file."_s},
{FileReadError, u"File read error."_s},
Expand Down Expand Up @@ -289,6 +299,7 @@ static inline const QString ERR_CONV_TYPE = u"JSON Error: Converting value to %1
static inline const QString ERR_NO_KEY = u"JSON Error: Could not retrieve key '%1'."_s;
static inline const QString ERR_PARSE_DOC = u"JSON Error: Could not parse JSON document."_s;
static inline const QString ERR_READ_FILE = u"JSON Error: Could not read JSON file."_s;
static inline const QString ERR_READ_DATA = u"JSON Error: Could not read JSON data."_s;
static inline const QString ERR_WRITE_FILE = u"JSON Error: Could not write JSON file."_s;

//-Structs---------------------------------------------------------------
Expand Down Expand Up @@ -788,10 +799,45 @@ void serializeJson(QJsonDocument& serialized, const T& root)
serialized = QJsonDocument(QxJson::Converter<T>::toJson(root));
}

template<typename T>
requires json_root<T>
JsonError parseJson(T& parsed, const QByteArray& data)
{
// Check for no data
if(data.isEmpty())
return JsonError(QxJsonPrivate::ERR_READ_DATA, JsonError::EmptyDoc).withContext(QxJson::Data());

// Basic parse
QJsonParseError jpe;
QJsonDocument jd = QJsonDocument::fromJson(data, &jpe);

if(jpe.error != jpe.NoError)
return JsonError(QxJsonPrivate::ERR_READ_DATA, JsonError::InvalidData).withContext(QxJson::Data());

// True parse
return parseJson(parsed, jd).withContext(QxJson::Data());
}

template<typename T>
requires json_root<T>
void serializeJson(QByteArray& serialized, const T& root, QJsonDocument::JsonFormat fmt = QJsonDocument::Indented)
{
// Ensure buffer is clear
serialized.clear();

// Create document
QJsonDocument jd;
serializeJson(jd, root);

// Write data
serialized = jd.toJson(fmt);
}

template<typename T>
requires json_root<T>
JsonError parseJson(T& parsed, QFile& file)
{
// NOTE: Don't utilize the QByteArray "data" overload here as we would lose the better error info
if(!file.exists())
return JsonError(QxJsonPrivate::ERR_READ_FILE, JsonError::MissingFile).withContext(QxJson::File(file.fileName()));

Expand Down Expand Up @@ -828,7 +874,7 @@ JsonError parseJson(T& parsed, QFile& file)

template<typename T>
requires json_root<T>
JsonError serializeJson(QFile& serialized, const T& root)
JsonError serializeJson(QFile& serialized, const T& root, QJsonDocument::JsonFormat fmt = QJsonDocument::Indented)
{
// Close and re-open file, if open, to ensure correct mode and start of file
if(serialized.isOpen())
Expand All @@ -840,15 +886,9 @@ JsonError serializeJson(QFile& serialized, const T& root)
// Close file when finished
QScopeGuard fileGuard([&serialized]{ serialized.close(); });

// Create document
QJsonDocument jd;
serializeJson(jd, root);

// Write data
QByteArray jsonData = jd.toJson();
if(jsonData.isEmpty())
return JsonError(); // No-op

// Serialize
QByteArray jsonData;
serializeJson(jsonData, root, fmt);
if(serialized.write(jsonData) != jsonData.size())
return JsonError(QxJsonPrivate::ERR_WRITE_FILE, JsonError::FileWriteError).withContext(QxJson::File(serialized.fileName(), serialized.errorString()));

Expand All @@ -866,11 +906,11 @@ JsonError parseJson(T& parsed, const QString& filePath)

template<typename T>
requires json_root<T>
JsonError serializeJson(const QString& serializedPath, const T& root)
JsonError serializeJson(const QString& serializedPath, const T& root, QJsonDocument::JsonFormat fmt = QJsonDocument::Indented)
{
QFile file(serializedPath);

return serializeJson(file, root);
return serializeJson(file, root, fmt);
}

QX_CORE_EXPORT QList<QJsonValue> findAllValues(const QJsonValue& rootValue, QStringView key);
Expand Down
2 changes: 2 additions & 0 deletions lib/core/include/qx/core/qx-string.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class QX_CORE_EXPORT String
static QString trimTrailing(const QStringView string);

static QString mapArg(QAnyStringView s, const QMap<QString, QString>& map, Qt::CaseSensitivity cs = Qt::CaseSensitive);

static QString toHeadlineCase(const QString& string);
};

}
Expand Down
15 changes: 6 additions & 9 deletions lib/core/src/qx-bitarray.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Unit Includes
#include "qx/core/qx-bitarray.h"

// Standard Library Includes
#include <stdexcept>

namespace Qx
{
//===============================================================================================================
Expand Down Expand Up @@ -39,7 +36,7 @@ namespace Qx
/*!
* Constructs an empty bit array.
*/
BitArray::BitArray() : QBitArray() {}
BitArray::BitArray() noexcept : QBitArray() {}

/*!
* Constructs a bit array containing @a size bits. The bits are
Expand Down Expand Up @@ -75,7 +72,7 @@ BitArray::BitArray(int size, bool value) : QBitArray(size, value) {}
* @warning The accuracy of the provided @a endianness relies on the contents of the bit array being in
* big-endian order, since using QSysInfo::LittleEndian simply reverses the resultant byte array's byte order.
*/
QByteArray BitArray::toByteArray(QSysInfo::Endian endianness)
QByteArray BitArray::toByteArray(QSysInfo::Endian endianness) const
{
// Byte array
QByteArray ba(std::ceil(count()/8.0), 0);
Expand Down Expand Up @@ -134,7 +131,7 @@ void BitArray::replace(const BitArray& bits, int start, int length)
*
* A value of -1 for @a length will result all bits from @a start to the end of the array being included.
*/
BitArray BitArray::subArray(int start, int length)
BitArray BitArray::subArray(int start, int length) const
{
if(start < 0 || start >= count())
qFatal("Least significant bit index was outside BitArray contents");
Expand Down Expand Up @@ -196,7 +193,7 @@ BitArray BitArray::takeFromEnd(int length)
/*!
* Returns a new bit array with the contents of the original shifted left @a n times.
*/
BitArray BitArray::operator<<(int n)
BitArray BitArray::operator<<(int n) const
{
BitArray shifted(count());

Expand All @@ -220,7 +217,7 @@ void BitArray::operator<<=(int n)
/*!
* Returns a new bit array with the contents of the original shifted right @a n times.
*/
BitArray BitArray::operator>>(int n)
BitArray BitArray::operator>>(int n) const
{
BitArray shifted(count());

Expand All @@ -244,7 +241,7 @@ void BitArray::operator>>=(int n)
/*!
* Returns a bit array which is the result of concatenating this bit array and @a rhs.
*/
BitArray BitArray::operator+(BitArray rhs)
BitArray BitArray::operator+(BitArray rhs) const
{
BitArray sum(count() + rhs.count());
sum |= *this;
Expand Down
50 changes: 46 additions & 4 deletions lib/core/src/qx-json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,28 @@ QString QJsonParseErrorAdapter::deriveSecondary() const { return OFFSET_STR.arg(
* @a T must satisfy the Qx::json_root concept.
*/

/*!
* @fn JsonError parseJson(T& parsed, const QByteArray& data)
*
* @overload
*
* Parses @a data as a JSON document and stores the result in @a parsed.
* @a T must satisfy the Qx::json_root concept.
*/

/*!
* @fn JsonError serializeJson(QByteArray& serialized, const T& root, QJsonDocument::JsonFormat fmt)
*
* @overload
*
* Serializes the entire JSON root structure @a root and writes the result to @a serialized in format @a fmt.
*
* @a T must satisfy the Qx::json_root concept.
*
* If serialization fails, a valid JsonError is returned that describes the cause; otherwise, an invalid
* error is returned.
*/

/*!
* @fn JsonError parseJson(T& parsed, QFile& file)
*
Expand All @@ -334,11 +356,11 @@ QString QJsonParseErrorAdapter::deriveSecondary() const { return OFFSET_STR.arg(
*/

/*!
* @fn JsonError serializeJson(QFile& serialized, const T& root)
* @fn JsonError serializeJson(QFile& serialized, const T& root, QJsonDocument::JsonFormat fmt)
*
* @overload
*
* Serializes the entire JSON root structure @a root and writes the result to @a serialized in indented format,
* Serializes the entire JSON root structure @a root and writes the result to @a serialized in format @a fmt,
* replacing existing contents, if any.
*
* @a T must satisfy the Qx::json_root concept.
Expand All @@ -357,12 +379,12 @@ QString QJsonParseErrorAdapter::deriveSecondary() const { return OFFSET_STR.arg(
*/

/*!
* @fn JsonError serializeJson(const QString& filePath, const T& root)
* @fn JsonError serializeJson(const QString& filePath, const T& root, QJsonDocument::JsonFormat fmt)
*
* @overload
*
* Serializes the entire JSON root structure @a root and writes the result to the file at path @a
* filePath in indented format, replacing existing contents, if any.
* filePath in format @a fmt, replacing existing contents, if any.
*
* @a T must satisfy the Qx::json_root concept.
*
Expand Down Expand Up @@ -476,6 +498,26 @@ QString File::string() const
return str;
}

/*!
* @class Data
* @brief The document class represents a JSON data node for use in error contexts.
*
* @note This class is irrelevant in user code except for some instances of complex
* custom JSON parsing
*
* @sa Qx::JsonError::withContext().
*/

/*!
* Constructs a data element node.
*/
Data::Data() {}

/*!
* Returns the string representation of the node.
*/
QString Data::string() const { return u"Data"_s; }

/*!
* @class Document
* @brief The document class represents a JSON document node for use in error contexts.
Expand Down
Loading
Loading