Add clang-format, clang-tidy; reindent files, increas readability

This commit is contained in:
S David 2024-05-03 22:20:24 -04:00
parent fbff9261ef
commit eb8a3b5ea7
5 changed files with 900 additions and 622 deletions

41
.clang-format Normal file
View File

@ -0,0 +1,41 @@
---
BasedOnStyle: Mozilla
Language: Cpp
IndentWidth: 8
UseTab: AlignWithSpaces
ColumnLimit: 81
AccessModifierOffset: -4
BinPackParameters: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
PenaltyReturnTypeOnItsOwnLine: 50
ContinuationIndentWidth: 4
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
AllowAllArgumentsOnNextLine: true
AlignAfterOpenBracket: BlockIndent
BreakBeforeBraces: WebKit
#BraceWrapping:
# AfterCaseLabel: false
# AfterClass: true
# AfterControlStatement: MultiLine
# AfterEnum: false
# AfterFunction: true
# AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: true
# AfterUnion: true
# AfterExternBlock: false
#
# BeforeCatch: true
# BeforeElse: false
# BeforeLambdaBody: false
# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: false
# SplitEmptyNamespace: true
#
---

79
.clang-tidy Normal file
View File

@ -0,0 +1,79 @@
HeaderFilterRegex: '.*hpp'
Checks: '-*,readability-identifier-naming,readability-identifier-length,readability-function-cognitive-complexity,google-readability-casting,-modernize-use-trailing-return-type,modernize-use-default-member-init,modernize-use-uncaught-exceptions,modernize-type-traits,modernize-use-override,misc-non-copyable-objects'
CheckOptions:
# Modernize constructors
- { key: modernize-use-default-member-init.UseAssignment, value : false}
- { key: modernize-use-default-member-init.IgnoreMacros, value : false}
# Warn about complex functions
- { key: readability-function-cognitive-complexity.Threshold, value: 10 }
- { key: readability-function-cognitive-complexity.DescribeBasicIncrements, value: true }
- { key: readability-function-cognitive-complexity.IgnoreMacros, value: true }
# Minimum Variable Length
- { key: readability-identifier-length.MinimumVariableNameLength, value: 3 }
- { key: readability-identifier-length.IgnoredVariableNames, value: "^(i|j|n|it)$" }
# Minimum Parameter Length
- { key: readability-identifier-length.MinimumParameterNameLength, value: 3 }
- { key: readability-identifier-length.IgnoredParameterNames, value: "^(i|j|n|it)$" }
# Minimum Loop Counter Length
- { key: readability-identifier-length.MinimumLoopCounterNameLength, value: 3 }
- { key: readability-identifier-length.IgnoredLoopCounterNames, value: "^(i|j|n|it)$" }
# Minimum ExceptionName Length:
- { key: readability-identifier-length.MinimumExceptionNameLength, value: 3 }
- { key: readability-identifier-length.IgnoredExceptionVariableNames, value: "^[e]$" }
# Class Names
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.EnumIgnoredRegexp, value: '^.*_t$' }
# Abstract Class Name
# - { key: readability-identifier-naming.AbstractClassPrefix,value: 'I' }
# - { key: readability-identifier-naming.AbstractClassIgnoredRegexp,
# value: '^.*able$|^.*Base$|^Abstract.*|^Component$' }
# Template Parameters
- { key: readability-identifier-naming.TypeTemplateParameterPrefix,
value: '' }
- { key: readability-identifier-naming.TypeTemplateParameterSuffix,
value: '' }
- { key: readability-identifier-naming.TypeTemplateParameterCase,
value: CamelCase }
- { key: readability-identifier-naming.TypeTemplateParameterIgnoredRegexp, value: "^T$" }
# TypeAlias Rules
- { key: readability-identifier-naming.TypeAliasCase, value: CamelCase }
- { key: readability-identifier-naming.TypeAliasIgnoredRegexp,
value: '.*_t|string|.*_string' }
# Function Names
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
- { key: readability-identifier-naming.PublicMethodCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMethodCase, value: camelBack }
# Variable Names
- { key: readability-identifier-naming.VariableCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
# Constants and Enum Values
#- { key: readability-identifier-naming.ConstantPrefix, value: 'k' }
- { key: readability-identifier-naming.ConstantCase, value: camelBack }
- { key: readability-identifier-naming.EnumConstantPrefix, value: '' }
- { key: readability-identifier-naming.EnumConstantCase, value: CamelCase }
# Constant Expression
- { key: readability-identifier-naming.ConstexprVariablePrefix, value: 'k' }
- { key: readability-identifier-naming.ConstexprVariableCase, value: Camel_Snake_Case }
- { key: readability-identifier-naming.ConstexprFunctionCase, value: Camel_Snake_Case }
- { key: readability-identifier-naming.ConstexprMethodCase, value: Camel_Snake_Case }
# vim: set ts=4 noet sw=4 sts=0 colorcolumn=100 :

View File

@ -23,483 +23,595 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// NOLINTBEGIN
#include "QJsonModel.hpp"
#include <QDebug>
#include <QFile>
#include <QFont>
inline bool contains(const QStringList &list, const QString &value) {
for (auto val : list)
if (value.contains(val, Qt::CaseInsensitive))
return true;
inline bool contains(const QStringList& list, const QString& value)
{
for (auto val : list)
if (value.contains(val, Qt::CaseInsensitive))
return true;
return false;
return false;
}
QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) { mParent = parent; }
QJsonTreeItem::~QJsonTreeItem() { qDeleteAll(mChilds); }
void QJsonTreeItem::appendChild(QJsonTreeItem *item) { mChilds.append(item); }
QJsonTreeItem *QJsonTreeItem::child(int row) { return mChilds.value(row); }
QJsonTreeItem *QJsonTreeItem::parent() { return mParent; }
int QJsonTreeItem::childCount() const { return mChilds.count(); }
int QJsonTreeItem::row() const {
if (mParent)
return mParent->mChilds.indexOf(const_cast<QJsonTreeItem *>(this));
return 0;
QJsonTreeItem::QJsonTreeItem(QJsonTreeItem* parent)
{
mParent = parent;
}
void QJsonTreeItem::setKey(const QString &key) { mKey = key; }
QJsonTreeItem::~QJsonTreeItem()
{
qDeleteAll(mChilds);
}
void QJsonTreeItem::setValue(const QVariant &value) { mValue = value; }
void QJsonTreeItem::appendChild(QJsonTreeItem* item)
{
mChilds.append(item);
}
void QJsonTreeItem::setType(const QJsonValue::Type &type) { mType = type; }
QJsonTreeItem* QJsonTreeItem::child(int row)
{
return mChilds.value(row);
}
QString QJsonTreeItem::key() const { return mKey; }
QJsonTreeItem* QJsonTreeItem::parent()
{
return mParent;
}
QVariant QJsonTreeItem::value() const { return mValue; }
int QJsonTreeItem::childCount() const
{
return mChilds.count();
}
QJsonValue::Type QJsonTreeItem::type() const { return mType; }
int QJsonTreeItem::row() const
{
if (mParent)
return mParent->mChilds.indexOf(const_cast<QJsonTreeItem*>(this)
);
QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value,
const QStringList &exceptions,
QJsonTreeItem *parent) {
QJsonTreeItem *rootItem = new QJsonTreeItem(parent);
rootItem->setKey("root");
return 0;
}
if (value.isObject()) {
// Get all QJsonValue childs
const QStringList keys =
value.toObject().keys(); // To prevent clazy-range warning
for (const QString &key : keys) {
if (contains(exceptions, key)) {
continue;
}
QJsonValue v = value.toObject().value(key);
QJsonTreeItem *child = load(v, exceptions, rootItem);
child->setKey(key);
child->setType(v.type());
rootItem->appendChild(child);
}
} else if (value.isArray()) {
// Get all QJsonValue childs
int index = 0;
const QJsonArray array = value.toArray(); // To prevent clazy-range warning
for (const QJsonValue &v : array) {
QJsonTreeItem *child = load(v, exceptions, rootItem);
child->setKey(QString::number(index));
child->setType(v.type());
rootItem->appendChild(child);
++index;
}
} else {
rootItem->setValue(value.toVariant());
rootItem->setType(value.type());
}
void QJsonTreeItem::setKey(const QString& key)
{
mKey = key;
}
return rootItem;
void QJsonTreeItem::setValue(const QVariant& value)
{
mValue = value;
}
void QJsonTreeItem::setType(const QJsonValue::Type& type)
{
mType = type;
}
QString QJsonTreeItem::key() const
{
return mKey;
}
QVariant QJsonTreeItem::value() const
{
return mValue;
}
QJsonValue::Type QJsonTreeItem::type() const
{
return mType;
}
QJsonTreeItem* QJsonTreeItem::load(
const QJsonValue& value, const QStringList& exceptions, QJsonTreeItem* parent
)
{
QJsonTreeItem* rootItem = new QJsonTreeItem(parent);
rootItem->setKey("root");
if (value.isObject()) {
// Get all QJsonValue childs
const QStringList keys =
value.toObject().keys(); // To prevent clazy-range warning
for (const QString& key : keys) {
if (contains(exceptions, key)) {
continue;
}
QJsonValue jsonValue = value.toObject().value(key);
QJsonTreeItem* child = load(jsonValue, exceptions, rootItem);
child->setKey(key);
child->setType(jsonValue.type());
rootItem->appendChild(child);
}
} else if (value.isArray()) {
// Get all QJsonValue childs
int index = 0;
const QJsonArray array =
value.toArray(); // To prevent clazy-range warning
for (const QJsonValue& jsonValue : array) {
QJsonTreeItem* child =
load(jsonValue, exceptions, rootItem);
child->setKey(QString::number(index));
child->setType(jsonValue.type());
rootItem->appendChild(child);
++index;
}
} else {
rootItem->setValue(value.toVariant());
rootItem->setType(value.type());
}
return rootItem;
}
//=========================================================================
inline uchar hexdig(uint u) { return (u < 0xa ? '0' + u : 'a' + u - 0xa); }
QByteArray escapedString(const QString &s) {
QByteArray ba(s.length(), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
const uchar *ba_end = cursor + ba.length();
const ushort *src = reinterpret_cast<const ushort *>(s.constBegin());
const ushort *const end = reinterpret_cast<const ushort *>(s.constEnd());
while (src != end) {
if (cursor >= ba_end - 6) {
// ensure we have enough space
int pos = cursor - reinterpret_cast<const uchar *>(ba.constData());
ba.resize(ba.size() * 2);
cursor = reinterpret_cast<uchar *>(ba.data()) + pos;
ba_end = reinterpret_cast<const uchar *>(ba.constData()) + ba.length();
}
uint u = *src++;
if (u < 0x80) {
if (u < 0x20 || u == 0x22 || u == 0x5c) {
*cursor++ = '\\';
switch (u) {
case 0x22:
*cursor++ = '"';
break;
case 0x5c:
*cursor++ = '\\';
break;
case 0x8:
*cursor++ = 'b';
break;
case 0xc:
*cursor++ = 'f';
break;
case 0xa:
*cursor++ = 'n';
break;
case 0xd:
*cursor++ = 'r';
break;
case 0x9:
*cursor++ = 't';
break;
default:
*cursor++ = 'u';
*cursor++ = '0';
*cursor++ = '0';
*cursor++ = hexdig(u >> 4);
*cursor++ = hexdig(u & 0xf);
}
} else {
*cursor++ = (uchar)u;
}
} else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) <
0) {
// failed to get valid utf8 use JSON escape sequence
*cursor++ = '\\';
*cursor++ = 'u';
*cursor++ = hexdig(u >> 12 & 0x0f);
*cursor++ = hexdig(u >> 8 & 0x0f);
*cursor++ = hexdig(u >> 4 & 0x0f);
*cursor++ = hexdig(u & 0x0f);
}
}
ba.resize(cursor - reinterpret_cast<const uchar *>(ba.constData()));
return ba;
inline uchar hexdig(uint positiveValue)
{
return (
positiveValue < 0xa ? '0' + positiveValue : 'a' + positiveValue - 0xa
);
}
QJsonModel::QJsonModel(QObject *parent)
: QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
mHeaders.append("key");
mHeaders.append("value");
QByteArray escapedString(const QString& text)
{
QByteArray byteArray(text.length(), Qt::Uninitialized);
uchar* cursor =
reinterpret_cast<uchar*>(const_cast<char*>(byteArray.constData()));
const uchar* byteArrayEnd = cursor + byteArray.length();
const ushort* src = reinterpret_cast<const ushort*>(text.constBegin());
const ushort* const end =
reinterpret_cast<const ushort*>(text.constEnd());
while (src != end) {
if (cursor >= byteArrayEnd - 6) {
// ensure we have enough space
int pos = cursor - reinterpret_cast<const uchar*>(
byteArray.constData()
);
byteArray.resize(byteArray.size() * 2);
cursor =
reinterpret_cast<uchar*>(byteArray.data()) + pos;
byteArrayEnd =
reinterpret_cast<const uchar*>(byteArray.constData()
) +
byteArray.length();
}
uint uValue = *src++; // uValue = unsigned value
if (uValue < 0x80) {
if (uValue < 0x20 || uValue == 0x22 || uValue == 0x5c) {
*cursor++ = '\\';
switch (uValue) {
case 0x22:
*cursor++ = '"';
break;
case 0x5c:
*cursor++ = '\\';
break;
case 0x8:
*cursor++ = 'b';
break;
case 0xc:
*cursor++ = 'f';
break;
case 0xa:
*cursor++ = 'n';
break;
case 0xd:
*cursor++ = 'r';
break;
case 0x9:
*cursor++ = 't';
break;
default:
*cursor++ = 'u';
*cursor++ = '0';
*cursor++ = '0';
*cursor++ = hexdig(uValue >> 4);
*cursor++ = hexdig(uValue & 0xf);
}
} else {
*cursor++ = static_cast<uchar>(uValue);
}
} else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(uValue, cursor, src, end) < 0) {
// failed to get valid utf8 use JSON escape sequence
*cursor++ = '\\';
*cursor++ = 'u';
*cursor++ = hexdig(uValue >> 12 & 0x0f);
*cursor++ = hexdig(uValue >> 8 & 0x0f);
*cursor++ = hexdig(uValue >> 4 & 0x0f);
*cursor++ = hexdig(uValue & 0x0f);
}
}
byteArray.resize(
cursor - reinterpret_cast<const uchar*>(byteArray.constData())
);
return byteArray;
}
QJsonModel::QJsonModel(const QString &fileName, QObject *parent)
: QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
mHeaders.append("key");
mHeaders.append("value");
load(fileName);
QJsonModel::QJsonModel(QObject* parent)
: QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
{
mHeaders.append("key");
mHeaders.append("value");
}
QJsonModel::QJsonModel(QIODevice *device, QObject *parent)
: QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
mHeaders.append("key");
mHeaders.append("value");
load(device);
QJsonModel::QJsonModel(const QString& fileName, QObject* parent)
: QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
{
mHeaders.append("key");
mHeaders.append("value");
load(fileName);
}
QJsonModel::QJsonModel(const QByteArray &json, QObject *parent)
: QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} {
mHeaders.append("key");
mHeaders.append("value");
loadJson(json);
QJsonModel::QJsonModel(QIODevice* device, QObject* parent)
: QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
{
mHeaders.append("key");
mHeaders.append("value");
load(device);
}
QJsonModel::~QJsonModel() { delete mRootItem; }
bool QJsonModel::load(const QString &fileName) {
QFile file(fileName);
bool success = false;
if (file.open(QIODevice::ReadOnly)) {
success = load(&file);
file.close();
} else {
success = false;
}
return success;
QJsonModel::QJsonModel(const QByteArray& json, QObject* parent)
: QAbstractItemModel(parent), mRootItem{ new QJsonTreeItem }
{
mHeaders.append("key");
mHeaders.append("value");
loadJson(json);
}
bool QJsonModel::load(QIODevice *device) { return loadJson(device->readAll()); }
bool QJsonModel::loadJson(const QByteArray &json) {
auto const &jdoc = QJsonDocument::fromJson(json);
if (!jdoc.isNull()) {
beginResetModel();
delete mRootItem;
if (jdoc.isArray()) {
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.array()), mExceptions);
mRootItem->setType(QJsonValue::Array);
} else {
mRootItem = QJsonTreeItem::load(QJsonValue(jdoc.object()), mExceptions);
mRootItem->setType(QJsonValue::Object);
}
endResetModel();
return true;
}
qDebug() << Q_FUNC_INFO << "cannot load json";
return false;
QJsonModel::~QJsonModel()
{
delete mRootItem;
}
QVariant QJsonModel::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return {};
bool QJsonModel::load(const QString& fileName)
{
QFile file(fileName);
bool success = false;
if (file.open(QIODevice::ReadOnly)) {
success = load(&file);
file.close();
} else {
success = false;
}
QJsonTreeItem *item = static_cast<QJsonTreeItem *>(index.internalPointer());
if (role == Qt::DisplayRole) {
if (index.column() == 0)
return QString("%1").arg(item->key());
if (index.column() == 1)
return item->value();
} else if (Qt::EditRole == role) {
if (index.column() == 1)
return item->value();
}
return {};
return success;
}
bool QJsonModel::setData(const QModelIndex &index, const QVariant &value,
int role) {
int col = index.column();
if (Qt::EditRole == role) {
if (col == 1) {
QJsonTreeItem *item =
static_cast<QJsonTreeItem *>(index.internalPointer());
item->setValue(value);
emit dataChanged(index, index, {Qt::EditRole});
return true;
}
}
return false;
bool QJsonModel::load(QIODevice* device)
{
return loadJson(device->readAll());
}
QVariant QJsonModel::headerData(int section, Qt::Orientation orientation,
int role) const {
if (role != Qt::DisplayRole)
return {};
bool QJsonModel::loadJson(const QByteArray& json)
{
auto const& jdoc = QJsonDocument::fromJson(json);
if (orientation == Qt::Horizontal)
return mHeaders.value(section);
else
return {};
if (!jdoc.isNull()) {
beginResetModel();
delete mRootItem;
if (jdoc.isArray()) {
mRootItem = QJsonTreeItem::load(
QJsonValue(jdoc.array()), mExceptions
);
mRootItem->setType(QJsonValue::Array);
} else {
mRootItem = QJsonTreeItem::load(
QJsonValue(jdoc.object()), mExceptions
);
mRootItem->setType(QJsonValue::Object);
}
endResetModel();
return true;
}
qDebug() << Q_FUNC_INFO << "cannot load json";
return false;
}
QModelIndex QJsonModel::index(int row, int column,
const QModelIndex &parent) const {
if (!hasIndex(row, column, parent))
return {};
QVariant QJsonModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return {};
QJsonTreeItem *parentItem;
QJsonTreeItem* item =
static_cast<QJsonTreeItem*>(index.internalPointer());
if (!parent.isValid())
parentItem = mRootItem;
else
parentItem = static_cast<QJsonTreeItem *>(parent.internalPointer());
if (role == Qt::DisplayRole) {
if (index.column() == 0)
return QString("%1").arg(item->key());
QJsonTreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return {};
if (index.column() == 1)
return item->value();
} else if (Qt::EditRole == role) {
if (index.column() == 1)
return item->value();
}
return {};
}
QModelIndex QJsonModel::parent(const QModelIndex &index) const {
if (!index.isValid())
return {};
bool QJsonModel::setData(
const QModelIndex& index, const QVariant& value, int role
)
{
int col = index.column();
if (Qt::EditRole == role) {
if (col == 1) {
QJsonTreeItem* item =
static_cast<QJsonTreeItem*>(index.internalPointer());
item->setValue(value);
emit dataChanged(index, index, { Qt::EditRole });
return true;
}
}
QJsonTreeItem *childItem =
static_cast<QJsonTreeItem *>(index.internalPointer());
QJsonTreeItem *parentItem = childItem->parent();
if (parentItem == mRootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
return false;
}
int QJsonModel::rowCount(const QModelIndex &parent) const {
QJsonTreeItem *parentItem;
if (parent.column() > 0)
return 0;
QVariant
QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return {};
if (!parent.isValid())
parentItem = mRootItem;
else
parentItem = static_cast<QJsonTreeItem *>(parent.internalPointer());
return parentItem->childCount();
if (orientation == Qt::Horizontal)
return mHeaders.value(section);
else
return {};
}
int QJsonModel::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent)
return 2;
QModelIndex
QJsonModel::index(int row, int column, const QModelIndex& parent) const
{
if (!hasIndex(row, column, parent))
return {};
QJsonTreeItem* parentItem;
if (!parent.isValid())
parentItem = mRootItem;
else
parentItem =
static_cast<QJsonTreeItem*>(parent.internalPointer());
QJsonTreeItem* childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return {};
}
Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const {
int col = index.column();
auto item = static_cast<QJsonTreeItem *>(index.internalPointer());
QModelIndex QJsonModel::parent(const QModelIndex& index) const
{
if (!index.isValid())
return {};
auto isArray = QJsonValue::Array == item->type();
auto isObject = QJsonValue::Object == item->type();
QJsonTreeItem* childItem =
static_cast<QJsonTreeItem*>(index.internalPointer());
QJsonTreeItem* parentItem = childItem->parent();
if ((col == 1) && !(isArray || isObject))
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
else
return QAbstractItemModel::flags(index);
if (parentItem == mRootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
QByteArray QJsonModel::json(bool compact) {
auto jsonValue = genJson(mRootItem);
QByteArray json;
if (jsonValue.isNull())
return json;
int QJsonModel::rowCount(const QModelIndex& parent) const
{
QJsonTreeItem* parentItem;
if (parent.column() > 0)
return 0;
if (jsonValue.isArray())
arrayToJson(jsonValue.toArray(), json, 0, compact);
else
objectToJson(jsonValue.toObject(), json, 0, compact);
if (!parent.isValid())
parentItem = mRootItem;
else
parentItem =
static_cast<QJsonTreeItem*>(parent.internalPointer());
return json;
return parentItem->childCount();
}
void QJsonModel::objectToJson(QJsonObject jsonObject, QByteArray &json,
int indent, bool compact) {
json += compact ? "{" : "{\n";
objectContentToJson(jsonObject, json, indent + (compact ? 0 : 1), compact);
json += QByteArray(4 * indent, ' ');
json += compact ? "}" : "}\n";
}
void QJsonModel::arrayToJson(QJsonArray jsonArray, QByteArray &json, int indent,
bool compact) {
json += compact ? "[" : "[\n";
arrayContentToJson(jsonArray, json, indent + (compact ? 0 : 1), compact);
json += QByteArray(4 * indent, ' ');
json += compact ? "]" : "]\n";
int QJsonModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
return 2;
}
void QJsonModel::arrayContentToJson(QJsonArray jsonArray, QByteArray &json,
int indent, bool compact) {
if (jsonArray.size() <= 0)
return;
Qt::ItemFlags QJsonModel::flags(const QModelIndex& index) const
{
int col = index.column();
auto item = static_cast<QJsonTreeItem*>(index.internalPointer());
QByteArray indentString(4 * indent, ' ');
int i = 0;
while (1) {
json += indentString;
valueToJson(jsonArray.at(i), json, indent, compact);
if (++i == jsonArray.size()) {
if (!compact)
json += '\n';
break;
}
json += compact ? "," : ",\n";
}
}
void QJsonModel::objectContentToJson(QJsonObject jsonObject, QByteArray &json,
int indent, bool compact) {
if (jsonObject.size() <= 0)
return;
auto isArray = QJsonValue::Array == item->type();
auto isObject = QJsonValue::Object == item->type();
QByteArray indentString(4 * indent, ' ');
int i = 0;
while (1) {
QString key = jsonObject.keys().at(i);
json += indentString;
json += '"';
json += escapedString(key);
json += compact ? "\":" : "\": ";
valueToJson(jsonObject.value(key), json, indent, compact);
if (++i == jsonObject.size()) {
if (!compact)
json += '\n';
break;
}
json += compact ? "," : ",\n";
}
if ((col == 1) && !(isArray || isObject))
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
else
return QAbstractItemModel::flags(index);
}
void QJsonModel::valueToJson(QJsonValue jsonValue, QByteArray &json, int indent,
bool compact) {
QJsonValue::Type type = jsonValue.type();
switch (type) {
case QJsonValue::Bool:
json += jsonValue.toBool() ? "true" : "false";
break;
case QJsonValue::Double: {
const double d = jsonValue.toDouble();
if (qIsFinite(d)) {
json += QByteArray::number(d, 'f', QLocale::FloatingPointShortest);
} else {
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
}
break;
}
case QJsonValue::String:
json += '"';
json += escapedString(jsonValue.toString());
json += '"';
break;
case QJsonValue::Array:
json += compact ? "[" : "[\n";
arrayContentToJson(jsonValue.toArray(), json, indent + (compact ? 0 : 1),
compact);
json += QByteArray(4 * indent, ' ');
json += ']';
break;
case QJsonValue::Object:
json += compact ? "{" : "{\n";
objectContentToJson(jsonValue.toObject(), json, indent + (compact ? 0 : 1),
compact);
json += QByteArray(4 * indent, ' ');
json += '}';
break;
case QJsonValue::Null:
default:
json += "null";
}
QByteArray QJsonModel::json(bool compact)
{
auto jsonValue = genJson(mRootItem);
QByteArray json;
if (jsonValue.isNull())
return json;
if (jsonValue.isArray())
arrayToJson(jsonValue.toArray(), json, 0, compact);
else
objectToJson(jsonValue.toObject(), json, 0, compact);
return json;
}
void QJsonModel::addException(const QStringList &exceptions) {
mExceptions = exceptions;
void QJsonModel::objectToJson(
QJsonObject jsonObject, QByteArray& json, int indent, bool compact
)
{
json += compact ? "{" : "{\n";
objectContentToJson(
jsonObject, json, indent + (compact ? 0 : 1), compact
);
json += QByteArray(4 * indent, ' ');
json += compact ? "}" : "}\n";
}
void QJsonModel::arrayToJson(
QJsonArray jsonArray, QByteArray& json, int indent, bool compact
)
{
json += compact ? "[" : "[\n";
arrayContentToJson(jsonArray, json, indent + (compact ? 0 : 1), compact);
json += QByteArray(4 * indent, ' ');
json += compact ? "]" : "]\n";
}
QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const {
auto type = item->type();
int nchild = item->childCount();
void QJsonModel::arrayContentToJson(
QJsonArray jsonArray, QByteArray& json, int indent, bool compact
)
{
if (jsonArray.size() <= 0)
return;
if (QJsonValue::Object == type) {
QJsonObject jo;
for (int i = 0; i < nchild; ++i) {
auto ch = item->child(i);
auto key = ch->key();
jo.insert(key, genJson(ch));
}
return jo;
} else if (QJsonValue::Array == type) {
QJsonArray arr;
for (int i = 0; i < nchild; ++i) {
auto ch = item->child(i);
arr.append(genJson(ch));
}
return arr;
} else {
QJsonValue va;
switch (item->value().typeId()) {
case QMetaType::Bool: {
va = item->value().toBool();
break;
}
default:
va = item->value().toString();
break;
}
(item->value());
return va;
}
QByteArray indentString(4 * indent, ' ');
int i = 0;
while (1) {
json += indentString;
valueToJson(jsonArray.at(i), json, indent, compact);
if (++i == jsonArray.size()) {
if (!compact)
json += '\n';
break;
}
json += compact ? "," : ",\n";
}
}
void QJsonModel::objectContentToJson(
QJsonObject jsonObject, QByteArray& json, int indent, bool compact
)
{
if (jsonObject.size() <= 0)
return;
QByteArray indentString(4 * indent, ' ');
int i = 0;
while (1) {
QString key = jsonObject.keys().at(i);
json += indentString;
json += '"';
json += escapedString(key);
json += compact ? "\":" : "\": ";
valueToJson(jsonObject.value(key), json, indent, compact);
if (++i == jsonObject.size()) {
if (!compact)
json += '\n';
break;
}
json += compact ? "," : ",\n";
}
}
void QJsonModel::valueToJson(
QJsonValue jsonValue, QByteArray& json, int indent, bool compact
)
{
QJsonValue::Type type = jsonValue.type();
switch (type) {
case QJsonValue::Bool:
json += jsonValue.toBool() ? "true" : "false";
break;
case QJsonValue::Double: {
const double value = jsonValue.toDouble();
if (qIsFinite(value)) {
json += QByteArray::number(
value, 'f', QLocale::FloatingPointShortest
);
} else {
json += "null"; // +INF || -INF || NaN (see
// RFC4627#section2.4)
}
break;
}
case QJsonValue::String:
json += '"';
json += escapedString(jsonValue.toString());
json += '"';
break;
case QJsonValue::Array:
json += compact ? "[" : "[\n";
arrayContentToJson(
jsonValue.toArray(),
json,
indent + (compact ? 0 : 1),
compact
);
json += QByteArray(4 * indent, ' ');
json += ']';
break;
case QJsonValue::Object:
json += compact ? "{" : "{\n";
objectContentToJson(
jsonValue.toObject(),
json,
indent + (compact ? 0 : 1),
compact
);
json += QByteArray(4 * indent, ' ');
json += '}';
break;
case QJsonValue::Null:
default:
json += "null";
}
}
void QJsonModel::addException(const QStringList& exceptions)
{
mExceptions = exceptions;
}
QJsonValue QJsonModel::genJson(QJsonTreeItem* item) const
{
auto type = item->type();
int nchild = item->childCount();
if (QJsonValue::Object == type) {
QJsonObject jo;
for (int i = 0; i < nchild; ++i) {
auto ch = item->child(i);
auto key = ch->key();
jo.insert(key, genJson(ch));
}
return jo;
} else if (QJsonValue::Array == type) {
QJsonArray arr;
for (int i = 0; i < nchild; ++i) {
auto ch = item->child(i);
arr.append(genJson(ch));
}
return arr;
} else {
QJsonValue va;
switch (item->value().typeId()) {
case QMetaType::Bool: {
va = item->value().toBool();
break;
}
default:
va = item->value().toString();
break;
}
(item->value());
return va;
}
}
// clang-format off
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=4 sts=0 sw=8 noexpandtab ft=cpp.doxygen :

View File

@ -38,78 +38,92 @@ class QJsonModel;
class QJsonItem;
class QJsonTreeItem {
public:
QJsonTreeItem(QJsonTreeItem *parent = nullptr);
~QJsonTreeItem();
void appendChild(QJsonTreeItem *item);
QJsonTreeItem *child(int row);
QJsonTreeItem *parent();
int childCount() const;
int row() const;
void setKey(const QString &key);
void setValue(const QVariant &value);
void setType(const QJsonValue::Type &type);
QString key() const;
QVariant value() const;
QJsonValue::Type type() const;
public:
QJsonTreeItem(QJsonTreeItem* parent = nullptr);
~QJsonTreeItem();
void appendChild(QJsonTreeItem* item);
QJsonTreeItem* child(int row);
QJsonTreeItem* parent();
int childCount() const;
int row() const;
void setKey(const QString& key);
void setValue(const QVariant& value);
void setType(const QJsonValue::Type& type);
QString key() const;
QVariant value() const;
QJsonValue::Type type() const;
static QJsonTreeItem *load(const QJsonValue &value,
const QStringList &exceptions = {},
QJsonTreeItem *parent = nullptr);
static QJsonTreeItem* load(
const QJsonValue& value, const QStringList& exceptions = {},
QJsonTreeItem* parent = nullptr
);
protected:
private:
QString mKey;
QVariant mValue;
QJsonValue::Type mType;
QList<QJsonTreeItem *> mChilds;
QJsonTreeItem *mParent = nullptr;
protected:
private:
QString mKey;
QVariant mValue;
QJsonValue::Type mType;
QList<QJsonTreeItem*> mChilds;
QJsonTreeItem* mParent = nullptr;
};
//---------------------------------------------------
class QJsonModel : public QAbstractItemModel {
Q_OBJECT
public:
explicit QJsonModel(QObject *parent = nullptr);
QJsonModel(const QString &fileName, QObject *parent = nullptr);
QJsonModel(QIODevice *device, QObject *parent = nullptr);
QJsonModel(const QByteArray &json, QObject *parent = nullptr);
~QJsonModel();
bool load(const QString &fileName);
bool load(QIODevice *device);
bool loadJson(const QByteArray &json);
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation,
int role) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QByteArray json(bool compact = false);
QByteArray jsonToByte(QJsonValue jsonValue);
void objectToJson(QJsonObject jsonObject, QByteArray &json, int indent,
bool compact);
void arrayToJson(QJsonArray jsonArray, QByteArray &json, int indent,
bool compact);
void arrayContentToJson(QJsonArray jsonArray, QByteArray &json, int indent,
bool compact);
void objectContentToJson(QJsonObject jsonObject, QByteArray &json, int indent,
bool compact);
void valueToJson(QJsonValue jsonValue, QByteArray &json, int indent,
bool compact);
//! List of tags to skip during JSON parsing
void addException(const QStringList &exceptions);
// NOLINTNEXTLINE
Q_OBJECT
public:
explicit QJsonModel(QObject* parent = nullptr);
QJsonModel(const QString& fileName, QObject* parent = nullptr);
QJsonModel(QIODevice* device, QObject* parent = nullptr);
QJsonModel(const QByteArray& json, QObject* parent = nullptr);
~QJsonModel() override;
bool load(const QString& fileName);
bool load(QIODevice* device);
bool loadJson(const QByteArray& json);
QVariant data(const QModelIndex& index, int role) const override;
bool setData(
const QModelIndex& index, const QVariant& value,
int role = Qt::EditRole
) override;
QVariant headerData(int section, Qt::Orientation orientation, int role)
const override;
QModelIndex index(
int row, int column, const QModelIndex& parent = QModelIndex()
) const override;
QModelIndex parent(const QModelIndex& index) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int
columnCount(const QModelIndex& parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
QByteArray json(bool compact = false);
QByteArray jsonToByte(QJsonValue jsonValue);
void objectToJson(
QJsonObject jsonObject, QByteArray& json, int indent, bool compact
);
void arrayToJson(
QJsonArray jsonArray, QByteArray& json, int indent, bool compact
);
void arrayContentToJson(
QJsonArray jsonArray, QByteArray& json, int indent, bool compact
);
void objectContentToJson(
QJsonObject jsonObject, QByteArray& json, int indent, bool compact
);
void valueToJson(
QJsonValue jsonValue, QByteArray& json, int indent, bool compact
);
//! List of tags to skip during JSON parsing
void addException(const QStringList& exceptions);
private:
QJsonValue genJson(QJsonTreeItem *) const;
QJsonTreeItem *mRootItem = nullptr;
QStringList mHeaders;
//! List of exceptions (e.g. comments). Case insensitive, compairs on
//! "contains".
QStringList mExceptions;
private:
QJsonValue genJson(QJsonTreeItem*) const;
QJsonTreeItem* mRootItem = nullptr;
QStringList mHeaders;
//! List of exceptions (e.g. comments). Case insensitive, compairs on
//! "contains".
QStringList mExceptions;
};
// clang-format off
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :

View File

@ -29,166 +29,198 @@ namespace QUtf8Functions {
/// Error if \a u is a low surrogate;
/// if \a u is a high surrogate, Error if the next isn't a low one,
/// EndOfString if we run into the end of the string.
template <typename Traits, typename OutputPtr, typename InputPtr>
inline int toUtf8(ushort u, OutputPtr &dst, InputPtr &src, InputPtr end) {
if (!Traits::skipAsciiHandling && u < 0x80) {
// U+0000 to U+007F (US-ASCII) - one byte
Traits::appendByte(dst, uchar(u));
return 0;
} else if (u < 0x0800) {
// U+0080 to U+07FF - two bytes
// first of two bytes
Traits::appendByte(dst, 0xc0 | uchar(u >> 6));
} else {
if (!QChar::isSurrogate(u)) {
// U+0800 to U+FFFF (except U+D800-U+DFFF) - three bytes
if (!Traits::allowNonCharacters && QChar::isNonCharacter(u))
return Traits::Error;
// first of three bytes
Traits::appendByte(dst, 0xe0 | uchar(u >> 12));
} else {
// U+10000 to U+10FFFF - four bytes
// need to get one extra codepoint
if (Traits::availableUtf16(src, end) == 0)
return Traits::EndOfString;
ushort low = Traits::peekUtf16(src);
if (!QChar::isHighSurrogate(u))
return Traits::Error;
if (!QChar::isLowSurrogate(low))
return Traits::Error;
Traits::advanceUtf16(src);
uint ucs4 = QChar::surrogateToUcs4(u, low);
if (!Traits::allowNonCharacters && QChar::isNonCharacter(ucs4))
return Traits::Error;
// first byte
Traits::appendByte(dst, 0xf0 | (uchar(ucs4 >> 18) & 0xf));
// second of four bytes
Traits::appendByte(dst, 0x80 | (uchar(ucs4 >> 12) & 0x3f));
// for the rest of the bytes
u = ushort(ucs4);
}
// second to last byte
Traits::appendByte(dst, 0x80 | (uchar(u >> 6) & 0x3f));
}
// last byte
Traits::appendByte(dst, 0x80 | (u & 0x3f));
return 0;
template<typename Traits, typename OutputPtr, typename InputPtr>
inline int toUtf8(ushort u, OutputPtr& dst, InputPtr& src, InputPtr end)
{
if (!Traits::skipAsciiHandling && u < 0x80) {
// U+0000 to U+007F (US-ASCII) - one byte
Traits::appendByte(dst, uchar(u));
return 0;
} else if (u < 0x0800) {
// U+0080 to U+07FF - two bytes
// first of two bytes
Traits::appendByte(dst, 0xc0 | uchar(u >> 6));
} else {
if (!QChar::isSurrogate(u)) {
// U+0800 to U+FFFF (except U+D800-U+DFFF) - three bytes
if (!Traits::allowNonCharacters &&
QChar::isNonCharacter(u))
return Traits::Error;
// first of three bytes
Traits::appendByte(dst, 0xe0 | uchar(u >> 12));
} else {
// U+10000 to U+10FFFF - four bytes
// need to get one extra codepoint
if (Traits::availableUtf16(src, end) == 0)
return Traits::EndOfString;
ushort low = Traits::peekUtf16(src);
if (!QChar::isHighSurrogate(u))
return Traits::Error;
if (!QChar::isLowSurrogate(low))
return Traits::Error;
Traits::advanceUtf16(src);
uint ucs4 = QChar::surrogateToUcs4(u, low);
if (!Traits::allowNonCharacters &&
QChar::isNonCharacter(ucs4))
return Traits::Error;
// first byte
Traits::appendByte(
dst, 0xf0 | (uchar(ucs4 >> 18) & 0xf)
);
// second of four bytes
Traits::appendByte(
dst, 0x80 | (uchar(ucs4 >> 12) & 0x3f)
);
// for the rest of the bytes
u = ushort(ucs4);
}
// second to last byte
Traits::appendByte(dst, 0x80 | (uchar(u >> 6) & 0x3f));
}
// last byte
Traits::appendByte(dst, 0x80 | (u & 0x3f));
return 0;
}
inline bool isContinuationByte(uchar b)
{
return (b & 0xc0) == 0x80;
}
inline bool isContinuationByte(uchar b) { return (b & 0xc0) == 0x80; }
/// returns the number of characters consumed (including \a b) in case of
/// success; returns negative in case of error: Traits::Error or
/// Traits::EndOfString
template <typename Traits, typename OutputPtr, typename InputPtr>
inline int fromUtf8(uchar b, OutputPtr &dst, InputPtr &src, InputPtr end) {
int charsNeeded;
uint min_uc;
uint uc;
if (!Traits::skipAsciiHandling && b < 0x80) {
// US-ASCII
Traits::appendUtf16(dst, b);
return 1;
}
if (!Traits::isTrusted && Q_UNLIKELY(b <= 0xC1)) {
// an UTF-8 first character must be at least 0xC0
// however, all 0xC0 and 0xC1 first bytes can only produce overlong
// sequences
return Traits::Error;
} else if (b < 0xe0) {
charsNeeded = 2;
min_uc = 0x80;
uc = b & 0x1f;
} else if (b < 0xf0) {
charsNeeded = 3;
min_uc = 0x800;
uc = b & 0x0f;
} else if (b < 0xf5) {
charsNeeded = 4;
min_uc = 0x10000;
uc = b & 0x07;
} else {
// the last Unicode character is U+10FFFF
// it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF"
// therefore, a byte higher than 0xF4 is not the UTF-8 first byte
return Traits::Error;
}
int bytesAvailable = Traits::availableBytes(src, end);
if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) {
// it's possible that we have an error instead of just unfinished bytes
if (bytesAvailable > 0 && !isContinuationByte(Traits::peekByte(src, 0)))
return Traits::Error;
if (bytesAvailable > 1 && !isContinuationByte(Traits::peekByte(src, 1)))
return Traits::Error;
return Traits::EndOfString;
}
// first continuation character
b = Traits::peekByte(src, 0);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
if (charsNeeded > 2) {
// second continuation character
b = Traits::peekByte(src, 1);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
if (charsNeeded > 3) {
// third continuation character
b = Traits::peekByte(src, 2);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
}
}
// we've decoded something; safety-check it
if (!Traits::isTrusted) {
if (uc < min_uc)
return Traits::Error;
if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint)
return Traits::Error;
if (!Traits::allowNonCharacters && QChar::isNonCharacter(uc))
return Traits::Error;
}
// write the UTF-16 sequence
if (!QChar::requiresSurrogates(uc)) {
// UTF-8 decoded and no surrogates are required
// detach if necessary
Traits::appendUtf16(dst, ushort(uc));
} else {
// UTF-8 decoded to something that requires a surrogate pair
Traits::appendUcs4(dst, uc);
}
Traits::advanceByte(src, charsNeeded - 1);
return charsNeeded;
template<typename Traits, typename OutputPtr, typename InputPtr>
inline int fromUtf8(uchar b, OutputPtr& dst, InputPtr& src, InputPtr end)
{
int charsNeeded;
uint min_uc;
uint uc;
if (!Traits::skipAsciiHandling && b < 0x80) {
// US-ASCII
Traits::appendUtf16(dst, b);
return 1;
}
if (!Traits::isTrusted && Q_UNLIKELY(b <= 0xC1)) {
// an UTF-8 first character must be at least 0xC0
// however, all 0xC0 and 0xC1 first bytes can only produce
// overlong sequences
return Traits::Error;
} else if (b < 0xe0) {
charsNeeded = 2;
min_uc = 0x80;
uc = b & 0x1f;
} else if (b < 0xf0) {
charsNeeded = 3;
min_uc = 0x800;
uc = b & 0x0f;
} else if (b < 0xf5) {
charsNeeded = 4;
min_uc = 0x10000;
uc = b & 0x07;
} else {
// the last Unicode character is U+10FFFF
// it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF"
// therefore, a byte higher than 0xF4 is not the UTF-8 first byte
return Traits::Error;
}
int bytesAvailable = Traits::availableBytes(src, end);
if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) {
// it's possible that we have an error instead of just unfinished
// bytes
if (bytesAvailable > 0 &&
!isContinuationByte(Traits::peekByte(src, 0)))
return Traits::Error;
if (bytesAvailable > 1 &&
!isContinuationByte(Traits::peekByte(src, 1)))
return Traits::Error;
return Traits::EndOfString;
}
// first continuation character
b = Traits::peekByte(src, 0);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
if (charsNeeded > 2) {
// second continuation character
b = Traits::peekByte(src, 1);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
if (charsNeeded > 3) {
// third continuation character
b = Traits::peekByte(src, 2);
if (!isContinuationByte(b))
return Traits::Error;
uc <<= 6;
uc |= b & 0x3f;
}
}
// we've decoded something; safety-check it
if (!Traits::isTrusted) {
if (uc < min_uc)
return Traits::Error;
if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint)
return Traits::Error;
if (!Traits::allowNonCharacters && QChar::isNonCharacter(uc))
return Traits::Error;
}
// write the UTF-16 sequence
if (!QChar::requiresSurrogates(uc)) {
// UTF-8 decoded and no surrogates are required
// detach if necessary
Traits::appendUtf16(dst, ushort(uc));
} else {
// UTF-8 decoded to something that requires a surrogate pair
Traits::appendUcs4(dst, uc);
}
Traits::advanceByte(src, charsNeeded - 1);
return charsNeeded;
}
} // namespace QUtf8Functions
struct QUtf8BaseTraits {
static const bool isTrusted = false;
static const bool allowNonCharacters = true;
static const bool skipAsciiHandling = false;
static const int Error = -1;
static const int EndOfString = -2;
static bool isValidCharacter(uint u) { return int(u) >= 0; }
static void appendByte(uchar *&ptr, uchar b) { *ptr++ = b; }
static uchar peekByte(const uchar *ptr, int n = 0) { return ptr[n]; }
static qptrdiff availableBytes(const uchar *ptr, const uchar *end) {
return end - ptr;
}
static void advanceByte(const uchar *&ptr, int n = 1) { ptr += n; }
static void appendUtf16(ushort *&ptr, ushort uc) { *ptr++ = uc; }
static void appendUcs4(ushort *&ptr, uint uc) {
appendUtf16(ptr, QChar::highSurrogate(uc));
appendUtf16(ptr, QChar::lowSurrogate(uc));
}
static ushort peekUtf16(const ushort *ptr, int n = 0) { return ptr[n]; }
static qptrdiff availableUtf16(const ushort *ptr, const ushort *end) {
return end - ptr;
}
static void advanceUtf16(const ushort *&ptr, int n = 1) { ptr += n; }
// it's possible to output to UCS-4 too
static void appendUtf16(uint *&ptr, ushort uc) { *ptr++ = uc; }
static void appendUcs4(uint *&ptr, uint uc) { *ptr++ = uc; }
static const bool isTrusted = false;
static const bool allowNonCharacters = true;
static const bool skipAsciiHandling = false;
static const int error = -1;
static const int endOfString = -2;
static bool isValidCharacter(uint unsignedInt)
{
return static_cast<int>(unsignedInt) >= 0;
}
static void appendByte(uchar*& ptr, uchar byteVal) { *ptr++ = byteVal; }
static uchar peekByte(const uchar* ptr, int n = 0) { return ptr[n]; }
static qptrdiff availableBytes(const uchar* ptr, const uchar* end)
{
return end - ptr;
}
static void advanceByte(const uchar*& ptr, int n = 1) { ptr += n; }
static void appendUtf16(ushort*& ptr, ushort unicodeChar)
{
*ptr++ = unicodeChar;
}
static void appendUcs4(ushort*& ptr, uint unicodeChar)
{
appendUtf16(ptr, QChar::highSurrogate(unicodeChar));
appendUtf16(ptr, QChar::lowSurrogate(unicodeChar));
}
static ushort peekUtf16(const ushort* ptr, int n = 0) { return ptr[n]; }
static qptrdiff availableUtf16(const ushort* ptr, const ushort* end)
{
return end - ptr;
}
static void advanceUtf16(const ushort*& ptr, int n = 1) { ptr += n; }
// it's possible to output to UCS-4 too
static void appendUtf16(uint*& ptr, ushort unicodeChar)
{
*ptr++ = unicodeChar;
}
static void appendUcs4(uint*& ptr, uint unicodeChar)
{
*ptr++ = unicodeChar;
}
};
// clang-format off
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :