mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-23 18:32:55 +00:00
reimplement QJsonDocument via Jansson
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
62371e5749
commit
31f76bdcd1
43 changed files with 2185 additions and 8884 deletions
|
@ -215,6 +215,15 @@ set_package_properties(ZSTD PROPERTIES
|
|||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
# v2.0+ required for json_loads() with three arguments
|
||||
find_package(Jansson 2.0)
|
||||
set_package_properties(Jansson PROPERTIES
|
||||
PURPOSE "Required for JSON support"
|
||||
DESCRIPTION "C library for encoding, decoding and manipulating JSON data"
|
||||
URL "https://github.com/akheron/jansson"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
# v0.9.8+ required for SHA-224...SHA-512 support
|
||||
find_package(OpenSSL 0.9.8)
|
||||
set_package_properties(OpenSSL PROPERTIES
|
||||
|
@ -742,7 +751,6 @@ katie_generate_obsolete(QItemEditorCreatorBase QtGui qitemeditorfactory.h)
|
|||
katie_generate_obsolete(QItemEditorCreator QtGui qitemeditorfactory.h)
|
||||
katie_generate_obsolete(QItemSelection QtGui qitemselectionmodel.h)
|
||||
katie_generate_obsolete(QItemSelectionRange QtGui qitemselectionmodel.h)
|
||||
katie_generate_obsolete(QJsonParseError QtCore qjsondocument.h)
|
||||
katie_generate_obsolete(QKeyEvent QtGui qevent.h)
|
||||
katie_generate_obsolete(QLatin1Char QtCore qchar.h)
|
||||
katie_generate_obsolete(QLatin1String QtCore qstring.h)
|
||||
|
|
|
@ -12,7 +12,7 @@ build_script:
|
|||
sudo apt-get install -qq libpcre3-dev libssl-dev zlib1g-dev libzstd-dev libc6-dev libpng-dev \
|
||||
libjpeg-dev libtiff-dev libcups2-dev libfreetype6-dev libfontconfig1-dev libdbus-1-dev \
|
||||
libicu-dev unixodbc-dev libpq-dev libmariadbclient-dev libmariadbd-dev liblz4-dev \
|
||||
libsqlite3-dev xorg-dev dbus-x11
|
||||
libsqlite3-dev xorg-dev dbus-x11 libjansson-dev
|
||||
|
||||
cmake . -Wno-dev -DKATIE_TESTS=ON -DKATIE_BENCHMARKS=ON -DKATIE_UTILS=ON -DKATIE_PCH=ON -DCMAKE_UNITY_BUILD=ON
|
||||
|
||||
|
|
32
cmake/modules/FindJansson.cmake
Normal file
32
cmake/modules/FindJansson.cmake
Normal file
|
@ -0,0 +1,32 @@
|
|||
# - Try to find Jansson
|
||||
# Once done this will define
|
||||
#
|
||||
# JANSSON_FOUND - system has Jansson
|
||||
# JANSSON_INCLUDES - the Jansson include directory
|
||||
# JANSSON_LIBRARIES - the libraries needed to use Jansson
|
||||
#
|
||||
# Copyright (C) 2021, Ivailo Monev, <xakepa10@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
|
||||
include(FindPkgConfig)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
pkg_check_modules(PC_JANSSON QUIET jansson)
|
||||
|
||||
find_path(JANSSON_INCLUDES
|
||||
NAMES jansson.h
|
||||
HINTS $ENV{JANSSONDIR}/include ${PC_JANSSON_INCLUDEDIR}
|
||||
)
|
||||
|
||||
find_library(JANSSON_LIBRARIES
|
||||
NAMES jansson
|
||||
HINTS $ENV{JANSSONDIR}/lib ${PC_JANSSON_LIBDIR}
|
||||
)
|
||||
|
||||
find_package_handle_standard_args(Jansson
|
||||
VERSION_VAR PC_JANSSON_VERSION
|
||||
REQUIRED_VARS JANSSON_LIBRARIES JANSSON_INCLUDES
|
||||
)
|
||||
|
||||
mark_as_advanced(JANSSON_INCLUDES JANSSON_LIBRARIES)
|
|
@ -10,8 +10,8 @@ pkgdesc='C++ toolkit derived from the Qt 4.8 framework'
|
|||
arch=('i486' 'i686' 'pentium4' 'x86_64' 'arm')
|
||||
url='https://github.com/fluxer/katie'
|
||||
license=('LGPL' 'BSD')
|
||||
depends=('libsm' 'libxcursor' 'libxinerama' 'icu' 'libcups' 'libxrandr' 'sqlite' 'fontconfig'
|
||||
'xdg-utils')
|
||||
depends=('libsm' 'libxcursor' 'libxinerama' 'icu' 'libcups' 'libxrandr' 'sqlite'
|
||||
'fontconfig' 'xdg-utils' 'jansson')
|
||||
makedepends=('cmake' 'git' 'postgresql' 'mariadb-libs' 'unixodbc' 'unifdef')
|
||||
optdepends=('postgresql-libs: PostgreSQL driver'
|
||||
'mariadb-libs: MariaDB driver'
|
||||
|
|
|
@ -6,11 +6,12 @@ Vcs-Git: git://github.com/fluxer/katie.git
|
|||
Vcs-browser: https://github.com/fluxer/katie
|
||||
Standards-Version: 4.10.0
|
||||
Build-Depends: debhelper (>= 9~), libssl-dev, zlib1g-dev, libzstd-dev,
|
||||
libc6-dev, libpng-dev, libjpeg-dev, libtiff5-dev, libcups2-dev,
|
||||
libfreetype6-dev, libfontconfig1-dev, libpcre3-dev, libdbus-1-dev,
|
||||
unixodbc-dev, libicu-dev, libsqlite3-dev, cmake, git, xserver-xorg-dev,
|
||||
libxinerama-dev, libxrandr-dev, libxrender-dev, libxcursor-dev, libsm-dev,
|
||||
libpq-dev, libmariadbclient-dev, libmariadbd-dev, unifdef | dpkg
|
||||
libc6-dev, libjansson-dev, libpng-dev, libjpeg-dev, libtiff5-dev,
|
||||
libcups2-dev, libfreetype6-dev, libfontconfig1-dev, libpcre3-dev,
|
||||
libdbus-1-dev, unixodbc-dev, libicu-dev, libsqlite3-dev, cmake, git,
|
||||
xserver-xorg-dev, libxinerama-dev, libxrandr-dev, libxrender-dev,
|
||||
libxcursor-dev, libsm-dev, libpq-dev, libmariadbclient-dev, libmariadbd-dev,
|
||||
unifdef | dpkg
|
||||
|
||||
Package: katie-runtime
|
||||
Architecture: amd64 arm64 armel armhf i386 mips mips64el mipsel ppc64el s390x hurd-i386
|
||||
|
|
|
@ -7,7 +7,7 @@ Summary: C++ toolkit derived from the Qt 4.8 framework
|
|||
License: BSD and LGPLv2+
|
||||
URL: https://github.com/fluxer/katie
|
||||
|
||||
BuildRequires: gcc-c++ cmake libicu-devel libzstd-devel zlib-devel libsq3-devel libpng-devel freetype-devel pcre-devel openssl-devel libX11-devel libXinerama-devel libXrandr-devel libXrender-devel libXfixes-devel libXcursor-devel libSM-devel libICE-devel dbus-devel libtiff-devel libjpeg-turbo-devel fontconfig-devel cups-devel libiodbc-devel libpq-devel mariadb-embedded-devel unifdef
|
||||
BuildRequires: gcc-c++ cmake libicu-devel libzstd-devel jansson-devel zlib-devel libsq3-devel libpng-devel freetype-devel pcre-devel openssl-devel libX11-devel libXinerama-devel libXrandr-devel libXrender-devel libXfixes-devel libXcursor-devel libSM-devel libICE-devel dbus-devel libtiff-devel libjpeg-turbo-devel fontconfig-devel cups-devel libiodbc-devel libpq-devel mariadb-embedded-devel unifdef
|
||||
Requires: xdg-utils
|
||||
Requires(post): /sbin/ldconfig
|
||||
Requires(postun): /sbin/ldconfig
|
||||
|
|
|
@ -19,10 +19,12 @@ USES = compiler:c++11-lang pkgconfig cmake ssl xorg sqlite:3 desktop-file-utils
|
|||
USE_XORG = xinerama xrandr xrender xfixes xcursor xext sm ice
|
||||
USE_LDCONFIG = yes
|
||||
RUN_DEPENDS = xdg-open:devel/xdg-utils
|
||||
LIB_DEPENDS = libzstd.so:archivers/zstd libicuuc.so:devel/icu libicui18n.so:devel/icu \
|
||||
libpcre.so:devel/pcre libpng.so:graphics/png libjpeg.so:graphics/jpeg-turbo \
|
||||
libtiff.so:graphics/tiff libfreetype.so:print/freetype2 \
|
||||
libfontconfig.so:x11-fonts/fontconfig libdbus-1.so:devel/dbus libcups.so:print/cups \
|
||||
LIB_DEPENDS = libzstd.so:archivers/zstd libicuuc.so:devel/icu \
|
||||
libicui18n.so:devel/icu libjansson.so:devel/jansson \
|
||||
libpcre.so:devel/pcre libpng.so:graphics/png \
|
||||
libjpeg.so:graphics/jpeg-turbo libtiff.so:graphics/tiff \
|
||||
libfreetype.so:print/freetype2 libfontconfig.so:x11-fonts/fontconfig \
|
||||
libdbus-1.so:devel/dbus libcups.so:print/cups \
|
||||
libiodbc.so:databases/libiodbc
|
||||
CMAKE_ARGS = -DKATIE_TOOLS_SUFFIX="-katie"
|
||||
|
||||
|
|
|
@ -71,11 +71,7 @@ include/katie/QtCore/QHashNode
|
|||
include/katie/QtCore/QIODevice
|
||||
include/katie/QtCore/QIncompatibleFlag
|
||||
include/katie/QtCore/QInternal
|
||||
include/katie/QtCore/QJsonArray
|
||||
include/katie/QtCore/QJsonDocument
|
||||
include/katie/QtCore/QJsonObject
|
||||
include/katie/QtCore/QJsonParseError
|
||||
include/katie/QtCore/QJsonValue
|
||||
include/katie/QtCore/QLatin1Char
|
||||
include/katie/QtCore/QLatin1String
|
||||
include/katie/QtCore/QLibrary
|
||||
|
@ -256,10 +252,7 @@ include/katie/QtCore/qglobal.h
|
|||
include/katie/QtCore/qhash.h
|
||||
include/katie/QtCore/qiodevice.h
|
||||
include/katie/QtCore/qiterator.h
|
||||
include/katie/QtCore/qjsonarray.h
|
||||
include/katie/QtCore/qjsondocument.h
|
||||
include/katie/QtCore/qjsonobject.h
|
||||
include/katie/QtCore/qjsonvalue.h
|
||||
include/katie/QtCore/qlibrary.h
|
||||
include/katie/QtCore/qlibraryinfo.h
|
||||
include/katie/QtCore/qline.h
|
||||
|
|
|
@ -26,6 +26,7 @@ DEPENDS = xdg-utils-[0-9]*:../../misc/xdg-utils
|
|||
|
||||
.include "../../sysutils/desktop-file-utils/desktopdb.mk"
|
||||
.include "../../archivers/zstd/buildlink3.mk"
|
||||
.include "../../textproc/jansson/buildlink3.mk"
|
||||
.include "../../textproc/icu/buildlink3.mk"
|
||||
.include "../../devel/pcre/buildlink3.mk"
|
||||
.include "../../devel/zlib/buildlink3.mk"
|
||||
|
|
|
@ -74,11 +74,7 @@ include/katie/QtCore/QHashNode
|
|||
include/katie/QtCore/QIODevice
|
||||
include/katie/QtCore/QIncompatibleFlag
|
||||
include/katie/QtCore/QInternal
|
||||
include/katie/QtCore/QJsonArray
|
||||
include/katie/QtCore/QJsonDocument
|
||||
include/katie/QtCore/QJsonObject
|
||||
include/katie/QtCore/QJsonParseError
|
||||
include/katie/QtCore/QJsonValue
|
||||
include/katie/QtCore/QLatin1Char
|
||||
include/katie/QtCore/QLatin1String
|
||||
include/katie/QtCore/QLibrary
|
||||
|
@ -259,10 +255,7 @@ include/katie/QtCore/qglobal.h
|
|||
include/katie/QtCore/qhash.h
|
||||
include/katie/QtCore/qiodevice.h
|
||||
include/katie/QtCore/qiterator.h
|
||||
include/katie/QtCore/qjsonarray.h
|
||||
include/katie/QtCore/qjsondocument.h
|
||||
include/katie/QtCore/qjsonobject.h
|
||||
include/katie/QtCore/qjsonvalue.h
|
||||
include/katie/QtCore/qlibrary.h
|
||||
include/katie/QtCore/qlibraryinfo.h
|
||||
include/katie/QtCore/qline.h
|
||||
|
|
|
@ -21,9 +21,9 @@ COMPILER = base-clang ports-gcc
|
|||
MODULES = devel/cmake
|
||||
BUILD_DEPENDS = devel/gettext,-tools
|
||||
RUN_DEPENDS = devel/desktop-file-utils devel/xdg-utils
|
||||
LIB_DEPENDS = archivers/zstd textproc/icu4c devel/pcre graphics/png \
|
||||
graphics/jpeg graphics/tiff x11/dbus print/cups,-libs databases/iodbc \
|
||||
databases/sqlite3 devel/gettext,-runtime
|
||||
LIB_DEPENDS = archivers/zstd textproc/icu4c devel/jansson devel/pcre \
|
||||
graphics/png graphics/jpeg graphics/tiff x11/dbus print/cups,-libs \
|
||||
databases/iodbc databases/sqlite3 devel/gettext,-runtime
|
||||
WANTLIB = ${COMPILER_LIBCXX} ICE SM X11 Xcursor Xext Xfixes Xinerama Xrandr \
|
||||
Xrender fontconfig freetype zstd icui18n icuuc pcre png jpeg tiff \
|
||||
dbus-1 cups iodbc sqlite3 intl ssl z c crypto m
|
||||
|
|
|
@ -74,11 +74,7 @@ include/katie/QtCore/QHashNode
|
|||
include/katie/QtCore/QIODevice
|
||||
include/katie/QtCore/QIncompatibleFlag
|
||||
include/katie/QtCore/QInternal
|
||||
include/katie/QtCore/QJsonArray
|
||||
include/katie/QtCore/QJsonDocument
|
||||
include/katie/QtCore/QJsonObject
|
||||
include/katie/QtCore/QJsonParseError
|
||||
include/katie/QtCore/QJsonValue
|
||||
include/katie/QtCore/QLatin1Char
|
||||
include/katie/QtCore/QLatin1String
|
||||
include/katie/QtCore/QLibrary
|
||||
|
@ -259,10 +255,7 @@ include/katie/QtCore/qglobal.h
|
|||
include/katie/QtCore/qhash.h
|
||||
include/katie/QtCore/qiodevice.h
|
||||
include/katie/QtCore/qiterator.h
|
||||
include/katie/QtCore/qjsonarray.h
|
||||
include/katie/QtCore/qjsondocument.h
|
||||
include/katie/QtCore/qjsonobject.h
|
||||
include/katie/QtCore/qjsonvalue.h
|
||||
include/katie/QtCore/qlibrary.h
|
||||
include/katie/QtCore/qlibraryinfo.h
|
||||
include/katie/QtCore/qline.h
|
||||
|
|
|
@ -36,7 +36,6 @@ incmap = {
|
|||
'QHashNode': 'qhash.h',
|
||||
'QIncompatibleFlag': 'qglobal.h',
|
||||
'QInternal': 'qnamespace.h',
|
||||
'QJsonParseError': 'qjsondocument.h',
|
||||
'QLatin1Char': 'qchar.h',
|
||||
'QLatin1String': 'qstring.h',
|
||||
'QLineF': 'qline.h',
|
||||
|
|
|
@ -362,11 +362,7 @@ classlist = [
|
|||
"QItemSelection",
|
||||
"QItemSelectionModel",
|
||||
"QItemSelectionRange",
|
||||
"QJsonArray",
|
||||
"QJsonDocument",
|
||||
"QJsonObject",
|
||||
"QJsonParseError",
|
||||
"QJsonValue",
|
||||
"QKeyEvent",
|
||||
"QKeySequence",
|
||||
"QLabel",
|
||||
|
|
|
@ -3,6 +3,7 @@ set(EXTRA_CORE_LIBS
|
|||
${ZLIB_LIBRARIES}
|
||||
${ICU_LIBRARIES}
|
||||
${ZSTD_LIBRARIES}
|
||||
${JANSSON_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
# libm should be present by default becaue this is C++
|
||||
m
|
||||
|
@ -101,10 +102,7 @@ set(CORE_PUBLIC_HEADERS
|
|||
QBasicTimer
|
||||
QThread
|
||||
QSocketNotifier
|
||||
QJsonArray
|
||||
QJsonDocument
|
||||
QJsonObject
|
||||
QJsonValue
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
@ -114,6 +112,7 @@ include_directories(
|
|||
${ZLIB_INCLUDE_DIRS}
|
||||
${ICU_INCLUDES}
|
||||
${ZSTD_INCLUDES}
|
||||
${JANSSON_INCLUDES}
|
||||
)
|
||||
|
||||
set(CORE_HEADERS
|
||||
|
@ -188,13 +187,6 @@ set(CORE_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/io/qfilesystemengine_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/qfilesystemmetadata_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/qfilesystemiterator_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonarray.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsondocument.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonobject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonparser_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjson_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonvalue.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonwriter_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qabstracteventdispatcher.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qabstractitemmodel.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qabstractitemmodel_p.h
|
||||
|
@ -255,6 +247,7 @@ set(CORE_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qdatetime_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qeasingcurve.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qhash.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qjsondocument.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qline.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qlinkedlist.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qlist.h
|
||||
|
@ -339,13 +332,6 @@ set(CORE_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/io/qprocess_unix.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/qfilesystemiterator_unix.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/qstandardpaths_unix.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonarray.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjson.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsondocument.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonobject.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonparser.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonvalue.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json/qjsonwriter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qabstracteventdispatcher.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qabstractitemmodel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel/qbasictimer.cpp
|
||||
|
@ -390,6 +376,7 @@ set(CORE_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qeasingcurve.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qelapsedtimer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qhash.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qjsondocument.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qline.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qlinkedlist.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/qlist.cpp
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "qplatformdefs.h"
|
||||
#include "qsettings.h"
|
||||
#include "qjsondocument.h"
|
||||
#include "qjsonobject.h"
|
||||
#include "qstandardpaths.h"
|
||||
#include "qmutex.h"
|
||||
#include "qcoreapplication.h"
|
||||
|
@ -63,14 +62,13 @@ static bool json_settings_read(QIODevice &device, QSettings::SettingsMap &map)
|
|||
return false;
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsondoc = QJsonDocument::fromJson(data, &error);
|
||||
QJsonDocument jsondoc = QJsonDocument::fromJson(data);
|
||||
if (Q_UNLIKELY(jsondoc.isNull())) {
|
||||
qWarning("json_settings_read: %s", error.errorString().toUtf8().constData());
|
||||
qWarning("json_settings_read: %s", jsondoc.errorString().toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
|
||||
map = jsondoc.object().toVariantMap();
|
||||
map = jsondoc.toVariant().toMap();
|
||||
|
||||
// qDebug() << "json_settings_read" << jsondoc.toJson();
|
||||
return true;
|
||||
|
@ -78,7 +76,7 @@ static bool json_settings_read(QIODevice &device, QSettings::SettingsMap &map)
|
|||
|
||||
static bool json_settings_write(QIODevice &device, const QSettings::SettingsMap &map)
|
||||
{
|
||||
QJsonDocument jsondoc = QJsonDocument(QJsonObject::fromVariantMap(map));
|
||||
QJsonDocument jsondoc = QJsonDocument::fromVariant(map);
|
||||
QByteArray jsondata = jsondoc.toJson();
|
||||
if (Q_UNLIKELY(jsondoc.isNull() || jsondata.isNull())) {
|
||||
return false;
|
||||
|
|
|
@ -1,438 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qjson_p.h"
|
||||
#include "qalgorithms.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QJsonPrivate {
|
||||
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
#define Q_TO_LITTLE_ENDIAN(x) (x)
|
||||
#else
|
||||
#define Q_TO_LITTLE_ENDIAN(x) ( ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24) )
|
||||
#endif
|
||||
|
||||
static const Base emptyArray = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
|
||||
static const Base emptyObject = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
|
||||
|
||||
|
||||
void Data::compact()
|
||||
{
|
||||
Q_ASSERT(sizeof(Value) == sizeof(offset));
|
||||
|
||||
if (!compactionCounter) {
|
||||
return;
|
||||
}
|
||||
|
||||
Base *base = header->root();
|
||||
int reserve = 0;
|
||||
if (base->is_object) {
|
||||
Object *o = static_cast<Object *>(base);
|
||||
for (int i = 0; i < (int)o->length; ++i) {
|
||||
reserve += o->entryAt(i)->usedStorage(o);
|
||||
}
|
||||
} else {
|
||||
Array *a = static_cast<Array *>(base);
|
||||
for (int i = 0; i < (int)a->length; ++i) {
|
||||
reserve += (*a)[i].usedStorage(a);
|
||||
}
|
||||
}
|
||||
|
||||
int size = sizeof(Base) + reserve + base->length * sizeof(offset);
|
||||
int alloc = sizeof(Header) + size;
|
||||
Header *h = (Header *) malloc(alloc);
|
||||
h->tag = QJsonDocument::BinaryFormatTag;
|
||||
h->version = 1;
|
||||
Base *b = h->root();
|
||||
b->size = size;
|
||||
b->is_object = header->root()->is_object;
|
||||
b->length = base->length;
|
||||
b->tableOffset = reserve + sizeof(Array);
|
||||
|
||||
int offset = sizeof(Base);
|
||||
if (b->is_object) {
|
||||
Object *o = static_cast<Object *>(base);
|
||||
Object *no = static_cast<Object *>(b);
|
||||
|
||||
for (int i = 0; i < (int)o->length; ++i) {
|
||||
no->table()[i] = offset;
|
||||
|
||||
const Entry *e = o->entryAt(i);
|
||||
Entry *ne = no->entryAt(i);
|
||||
int s = e->size();
|
||||
memcpy(ne, e, s);
|
||||
offset += s;
|
||||
int dataSize = e->value.usedStorage(o);
|
||||
if (dataSize) {
|
||||
memcpy((char *)no + offset, e->value.data(o), dataSize);
|
||||
ne->value.value = offset;
|
||||
offset += dataSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Array *a = static_cast<Array *>(base);
|
||||
Array *na = static_cast<Array *>(b);
|
||||
|
||||
for (int i = 0; i < (int)a->length; ++i) {
|
||||
const Value &v = (*a)[i];
|
||||
Value &nv = (*na)[i];
|
||||
nv = v;
|
||||
int dataSize = v.usedStorage(a);
|
||||
if (dataSize) {
|
||||
memcpy((char *)na + offset, v.data(a), dataSize);
|
||||
nv.value = offset;
|
||||
offset += dataSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
Q_ASSERT(offset == (int)b->tableOffset);
|
||||
|
||||
free(header);
|
||||
header = h;
|
||||
this->alloc = alloc;
|
||||
compactionCounter = 0;
|
||||
}
|
||||
|
||||
bool Data::valid() const
|
||||
{
|
||||
if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
if (header->root()->is_object) {
|
||||
res = static_cast<Object *>(header->root())->isValid();
|
||||
} else {
|
||||
res = static_cast<Array *>(header->root())->isValid();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int Base::reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace)
|
||||
{
|
||||
Q_ASSERT(posInTable >= 0 && posInTable <= (int)length);
|
||||
if (size + dataSize >= Value::MaxSize) {
|
||||
qWarning("QJson: Document too large to store in data structure %d %d %d", (uint)size, dataSize, Value::MaxSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset off = tableOffset;
|
||||
// move table to new position
|
||||
if (replace) {
|
||||
memmove((char *)(table()) + dataSize, table(), length * sizeof(offset));
|
||||
} else {
|
||||
memmove((char *)(table() + posInTable + numItems) + dataSize, table() + posInTable,
|
||||
(length - posInTable)*sizeof(offset));
|
||||
memmove((char *)(table()) + dataSize, table(), posInTable * sizeof(offset));
|
||||
}
|
||||
tableOffset += dataSize;
|
||||
for (int i = 0; i < (int)numItems; ++i) {
|
||||
table()[posInTable + i] = off;
|
||||
}
|
||||
size += dataSize;
|
||||
if (!replace) {
|
||||
length += numItems;
|
||||
size += numItems * sizeof(offset);
|
||||
}
|
||||
return off;
|
||||
}
|
||||
|
||||
void Base::removeItems(int pos, int numItems)
|
||||
{
|
||||
Q_ASSERT(pos >= 0 && pos <= (int)length);
|
||||
if (pos + numItems < (int)length) {
|
||||
memmove(table() + pos, table() + pos + numItems, (length - pos - numItems)*sizeof(offset));
|
||||
}
|
||||
length -= numItems;
|
||||
}
|
||||
|
||||
int Object::indexOf(const QString &key, bool *exists)
|
||||
{
|
||||
int min = 0;
|
||||
int n = length;
|
||||
while (n > 0) {
|
||||
int half = n >> 1;
|
||||
int middle = min + half;
|
||||
if (*entryAt(middle) >= key) {
|
||||
n = half;
|
||||
} else {
|
||||
min = middle + 1;
|
||||
n -= half + 1;
|
||||
}
|
||||
}
|
||||
if (min < (int)length && *entryAt(min) == key) {
|
||||
*exists = true;
|
||||
return min;
|
||||
}
|
||||
*exists = false;
|
||||
return min;
|
||||
}
|
||||
|
||||
bool Object::isValid() const
|
||||
{
|
||||
if (tableOffset + length * sizeof(offset) > size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < length; ++i) {
|
||||
offset entryOffset = table()[i];
|
||||
if (entryOffset + sizeof(Entry) >= tableOffset) {
|
||||
return false;
|
||||
}
|
||||
Entry *e = entryAt(i);
|
||||
int s = e->size();
|
||||
if (table()[i] + s > tableOffset) {
|
||||
return false;
|
||||
}
|
||||
if (!e->value.isValid(this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Array::isValid() const
|
||||
{
|
||||
if (tableOffset + length * sizeof(offset) > size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < length; ++i) {
|
||||
if (!at(i).isValid(this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Entry::operator ==(const QString &key) const
|
||||
{
|
||||
if (value.latinKey) {
|
||||
return (shallowLatin1Key() == key);
|
||||
} else {
|
||||
return (shallowKey() == key);
|
||||
}
|
||||
}
|
||||
|
||||
bool Entry::operator ==(const Entry &other) const
|
||||
{
|
||||
if (value.latinKey) {
|
||||
if (other.value.latinKey) {
|
||||
return shallowLatin1Key() == other.shallowLatin1Key();
|
||||
}
|
||||
return shallowLatin1Key() == other.shallowKey();
|
||||
} else if (other.value.latinKey) {
|
||||
return shallowKey() == other.shallowLatin1Key();
|
||||
}
|
||||
return shallowKey() == other.shallowKey();
|
||||
}
|
||||
|
||||
bool Entry::operator >=(const Entry &other) const
|
||||
{
|
||||
if (value.latinKey) {
|
||||
if (other.value.latinKey) {
|
||||
return shallowLatin1Key() >= other.shallowLatin1Key();
|
||||
}
|
||||
return shallowLatin1Key() >= other.shallowKey();
|
||||
} else if (other.value.latinKey) {
|
||||
return shallowKey() >= other.shallowLatin1Key();
|
||||
}
|
||||
return shallowKey() >= other.shallowKey();
|
||||
}
|
||||
|
||||
|
||||
int Value::usedStorage(const Base *b) const
|
||||
{
|
||||
int s = 0;
|
||||
switch (type) {
|
||||
case QJsonValue::Double:
|
||||
if (latinOrIntValue) {
|
||||
break;
|
||||
}
|
||||
s = sizeof(double);
|
||||
break;
|
||||
case QJsonValue::String: {
|
||||
char *d = data(b);
|
||||
if (latinOrIntValue) {
|
||||
s = sizeof(ushort) + qFromLittleEndian(*(ushort *)d);
|
||||
} else {
|
||||
s = sizeof(int) + sizeof(ushort) * qFromLittleEndian(*(int *)d);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object:
|
||||
s = base(b)->size;
|
||||
break;
|
||||
case QJsonValue::Null:
|
||||
case QJsonValue::Bool:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return alignedSize(s);
|
||||
}
|
||||
|
||||
bool Value::isValid(const Base *b) const
|
||||
{
|
||||
int offset = 0;
|
||||
switch (type) {
|
||||
case QJsonValue::Double:
|
||||
if (latinOrIntValue) {
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case QJsonValue::String:
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object:
|
||||
offset = value;
|
||||
break;
|
||||
case QJsonValue::Null:
|
||||
case QJsonValue::Bool:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!offset) {
|
||||
return true;
|
||||
}
|
||||
if (offset + sizeof(uint) > b->tableOffset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int s = usedStorage(b);
|
||||
if (!s) {
|
||||
return true;
|
||||
}
|
||||
if (s < 0 || offset + s > (int)b->tableOffset) {
|
||||
return false;
|
||||
}
|
||||
if (type == QJsonValue::Array) {
|
||||
return static_cast<Array *>(base(b))->isValid();
|
||||
}
|
||||
if (type == QJsonValue::Object) {
|
||||
return static_cast<Object *>(base(b))->isValid();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
int Value::requiredStorage(QJsonValue &v, bool *compressed)
|
||||
{
|
||||
*compressed = false;
|
||||
switch (v.t) {
|
||||
case QJsonValue::Double:
|
||||
if (QJsonPrivate::compressedNumber(v.dbl) != INT_MAX) {
|
||||
*compressed = true;
|
||||
return 0;
|
||||
}
|
||||
return sizeof(double);
|
||||
case QJsonValue::String: {
|
||||
QString s = v.toString();
|
||||
*compressed = QJsonPrivate::useCompressed(s);
|
||||
return QJsonPrivate::qStringSize(s, *compressed);
|
||||
}
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object:
|
||||
if (v.d && v.d->compactionCounter) {
|
||||
v.detach();
|
||||
v.d->compact();
|
||||
v.base = static_cast<QJsonPrivate::Base *>(v.d->header->root());
|
||||
}
|
||||
return v.base ? v.base->size : sizeof(QJsonPrivate::Base);
|
||||
case QJsonValue::Undefined:
|
||||
case QJsonValue::Null:
|
||||
case QJsonValue::Bool:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
uint Value::valueToStore(const QJsonValue &v, uint offset)
|
||||
{
|
||||
switch (v.t) {
|
||||
case QJsonValue::Undefined:
|
||||
case QJsonValue::Null:
|
||||
break;
|
||||
case QJsonValue::Bool:
|
||||
return v.b;
|
||||
case QJsonValue::Double: {
|
||||
int c = QJsonPrivate::compressedNumber(v.dbl);
|
||||
if (c != INT_MAX) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
// fall through
|
||||
case QJsonValue::String:
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object:
|
||||
return offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void Value::copyData(const QJsonValue &v, char *dest, bool compressed)
|
||||
{
|
||||
switch (v.t) {
|
||||
case QJsonValue::Double:
|
||||
if (!compressed) {
|
||||
qToLittleEndian(v.dbl, (uchar *)dest);
|
||||
}
|
||||
break;
|
||||
case QJsonValue::String: {
|
||||
QString str = v.toString();
|
||||
QJsonPrivate::copyString(dest, str, compressed);
|
||||
break;
|
||||
}
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object: {
|
||||
const QJsonPrivate::Base *b = v.base;
|
||||
if (!b) {
|
||||
b = (v.t == QJsonValue::Array ? &emptyArray : &emptyObject);
|
||||
}
|
||||
memcpy(dest, b, b->size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QJsonPrivate
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -1,849 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSON_P_H
|
||||
#define QJSON_P_H
|
||||
|
||||
#include "qjsonobject.h"
|
||||
#include "qjsonvalue.h"
|
||||
#include "qjsondocument.h"
|
||||
#include "qjsonarray.h"
|
||||
#include "qatomic.h"
|
||||
#include "qstring.h"
|
||||
#include "qendian.h"
|
||||
#include "qnumeric.h"
|
||||
#include <limits.h>
|
||||
#include <limits>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*
|
||||
This defines a binary data structure for Json data. The data structure is optimised for fast reading
|
||||
and minimum allocations. The whole data structure can be mmap'ed and used directly.
|
||||
|
||||
In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but
|
||||
much faster to access.
|
||||
|
||||
The size requirements are:
|
||||
|
||||
String:
|
||||
Latin1 data: 2 bytes header + string.length()
|
||||
Full Unicode: 4 bytes header + 2*(string.length())
|
||||
|
||||
Values: 4 bytes + size of data (size can be 0 for some data)
|
||||
bool: 0 bytes
|
||||
double: 8 bytes (0 if integer with less than 27bits)
|
||||
string: see above
|
||||
array: size of array
|
||||
object: size of object
|
||||
Array: 12 bytes + 4*length + size of Value data
|
||||
Object: 12 bytes + 8*length + size of Key Strings + size of Value data
|
||||
|
||||
For an example such as
|
||||
|
||||
{ // object: 12 + 5*8 = 52
|
||||
"firstName": "John", // key 12, value 8 = 20
|
||||
"lastName" : "Smith", // key 12, value 8 = 20
|
||||
"age" : 25, // key 8, value 0 = 8
|
||||
"address" : // key 12, object below = 140
|
||||
{ // object: 12 + 4*8
|
||||
"streetAddress": "21 2nd Street", // key 16, value 16
|
||||
"city" : "New York", // key 8, value 12
|
||||
"state" : "NY", // key 8, value 4
|
||||
"postalCode" : "10021" // key 12, value 8
|
||||
}, // object total: 128
|
||||
"phoneNumber": // key: 16, value array below = 172
|
||||
[ // array: 12 + 2*4 + values below: 156
|
||||
{ // object 12 + 2*8
|
||||
"type" : "home", // key 8, value 8
|
||||
"number": "212 555-1234" // key 8, value 16
|
||||
}, // object total: 68
|
||||
{ // object 12 + 2*8
|
||||
"type" : "fax", // key 8, value 8
|
||||
"number": "646 555-4567" // key 8, value 16
|
||||
} // object total: 68
|
||||
] // array total: 156
|
||||
} // great total: 412 bytes
|
||||
|
||||
The uncompressed text file used roughly 500 bytes, so in this case we end up using about
|
||||
the same space as the text representation.
|
||||
|
||||
Other measurements have shown a slightly bigger binary size than a compact text
|
||||
representation where all possible whitespace was stripped out.
|
||||
*/
|
||||
namespace QJsonPrivate {
|
||||
|
||||
class Array;
|
||||
class Object;
|
||||
class Value;
|
||||
class Entry;
|
||||
|
||||
template<typename T>
|
||||
class q_littleendian
|
||||
{
|
||||
public:
|
||||
T val;
|
||||
|
||||
q_littleendian &operator =(T i) {
|
||||
val = qToLittleEndian(i);
|
||||
return *this;
|
||||
}
|
||||
operator T() const {
|
||||
return qFromLittleEndian(val);
|
||||
}
|
||||
|
||||
bool operator ==(T i) {
|
||||
return qFromLittleEndian(val) == i;
|
||||
}
|
||||
bool operator !=(T i) {
|
||||
return qFromLittleEndian(val) != i;
|
||||
}
|
||||
bool operator ==(q_littleendian<T> i) {
|
||||
return val == i.val;
|
||||
}
|
||||
bool operator !=(q_littleendian<T> i) {
|
||||
return val != i.val;
|
||||
}
|
||||
bool operator <(T i) {
|
||||
return qFromLittleEndian(val) < i;
|
||||
}
|
||||
bool operator >(T i) {
|
||||
return qFromLittleEndian(val) > i;
|
||||
}
|
||||
bool operator <=(T i) {
|
||||
return qFromLittleEndian(val) <= i;
|
||||
}
|
||||
bool operator >=(T i) {
|
||||
return qFromLittleEndian(val) >= i;
|
||||
}
|
||||
q_littleendian &operator +=(T i) {
|
||||
val = qToLittleEndian(qFromLittleEndian(val) + i);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef q_littleendian<short> qle_short;
|
||||
typedef q_littleendian<unsigned short> qle_ushort;
|
||||
typedef q_littleendian<int> qle_int;
|
||||
typedef q_littleendian<unsigned int> qle_uint;
|
||||
|
||||
template<int pos, int width>
|
||||
class qle_bitfield
|
||||
{
|
||||
public:
|
||||
uint val;
|
||||
|
||||
enum {
|
||||
mask = ((1u << width) - 1) << pos
|
||||
};
|
||||
|
||||
void operator =(uint t) {
|
||||
uint i = qFromLittleEndian(val);
|
||||
i &= ~mask;
|
||||
i |= t << pos;
|
||||
val = qToLittleEndian(i);
|
||||
}
|
||||
operator uint() const {
|
||||
uint t = qFromLittleEndian(val);
|
||||
t &= mask;
|
||||
t >>= pos;
|
||||
return t;
|
||||
}
|
||||
bool operator !() const {
|
||||
return !operator uint();
|
||||
}
|
||||
|
||||
bool operator ==(uint t) {
|
||||
return uint(*this) == t;
|
||||
}
|
||||
bool operator !=(uint t) {
|
||||
return uint(*this) != t;
|
||||
}
|
||||
bool operator <(uint t) {
|
||||
return uint(*this) < t;
|
||||
}
|
||||
bool operator >(uint t) {
|
||||
return uint(*this) > t;
|
||||
}
|
||||
bool operator <=(uint t) {
|
||||
return uint(*this) <= t;
|
||||
}
|
||||
bool operator >=(uint t) {
|
||||
return uint(*this) >= t;
|
||||
}
|
||||
qle_bitfield &operator +=(uint i) {
|
||||
*this = (uint(*this) + i);
|
||||
return *this;
|
||||
}
|
||||
qle_bitfield &operator -=(uint i) {
|
||||
*this = (uint(*this) - i);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<int pos, int width>
|
||||
class qle_signedbitfield
|
||||
{
|
||||
public:
|
||||
uint val;
|
||||
|
||||
enum {
|
||||
mask = ((1u << width) - 1) << pos
|
||||
};
|
||||
|
||||
void operator =(int t) {
|
||||
uint i = qFromLittleEndian(val);
|
||||
i &= ~mask;
|
||||
i |= t << pos;
|
||||
val = qToLittleEndian(i);
|
||||
}
|
||||
operator int() const {
|
||||
uint i = qFromLittleEndian(val);
|
||||
i <<= 32 - width - pos;
|
||||
int t = (int) i;
|
||||
t >>= pos;
|
||||
return t;
|
||||
}
|
||||
bool operator !() const {
|
||||
return !operator int();
|
||||
}
|
||||
|
||||
bool operator ==(int t) {
|
||||
return int(*this) == t;
|
||||
}
|
||||
bool operator !=(int t) {
|
||||
return int(*this) != t;
|
||||
}
|
||||
bool operator <(int t) {
|
||||
return int(*this) < t;
|
||||
}
|
||||
bool operator >(int t) {
|
||||
return int(*this) > t;
|
||||
}
|
||||
bool operator <=(int t) {
|
||||
return int(*this) <= t;
|
||||
}
|
||||
bool operator >=(int t) {
|
||||
return int(*this) >= t;
|
||||
}
|
||||
qle_signedbitfield &operator +=(int i) {
|
||||
*this = (int(*this) + i);
|
||||
return *this;
|
||||
}
|
||||
qle_signedbitfield &operator -=(int i) {
|
||||
*this = (int(*this) - i);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef qle_uint offset;
|
||||
|
||||
// round the size up to the next 4 byte boundary
|
||||
inline int alignedSize(int size)
|
||||
{
|
||||
return (size + 3) & ~3;
|
||||
}
|
||||
|
||||
static inline bool useCompressed(const QString &s)
|
||||
{
|
||||
if (s.length() >= 0x8000) {
|
||||
return false;
|
||||
}
|
||||
const ushort *uc = (const ushort *)s.constData();
|
||||
const ushort *e = uc + s.length();
|
||||
while (uc < e) {
|
||||
if (*uc > 0xff) {
|
||||
return false;
|
||||
}
|
||||
++uc;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int qStringSize(const QString &string, bool compress)
|
||||
{
|
||||
int l = 2 + string.length();
|
||||
if (!compress) {
|
||||
l *= 2;
|
||||
}
|
||||
return alignedSize(l);
|
||||
}
|
||||
|
||||
// returns INT_MAX if it can't compress it into 28 bits
|
||||
static inline int compressedNumber(double d)
|
||||
{
|
||||
// this relies on details of how ieee floats are represented
|
||||
const int exponent_off = 52;
|
||||
const quint64 fraction_mask = 0x000fffffffffffffull;
|
||||
const quint64 exponent_mask = 0x7ff0000000000000ull;
|
||||
|
||||
quint64 val;
|
||||
memcpy (&val, &d, sizeof(double));
|
||||
int exp = (int)((val & exponent_mask) >> exponent_off) - 1023;
|
||||
if (exp < 0 || exp > 25) {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
quint64 non_int = val & (fraction_mask >> exp);
|
||||
if (non_int) {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
bool neg = (val >> 63);
|
||||
val &= fraction_mask;
|
||||
val |= ((quint64)1 << 52);
|
||||
int res = (int)(val >> (52 - exp));
|
||||
return neg ? -res : res;
|
||||
}
|
||||
|
||||
class Latin1String;
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
String(const char *data) {
|
||||
d = (Data *)data;
|
||||
}
|
||||
|
||||
struct Data {
|
||||
qle_int length;
|
||||
qle_ushort utf16[1];
|
||||
};
|
||||
|
||||
Data *d;
|
||||
|
||||
inline String &operator=(const QString &str) {
|
||||
d->length = str.length();
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
const qle_ushort *uc = (const qle_ushort *)str.unicode();
|
||||
for (int i = 0; i < str.length(); ++i) {
|
||||
d->utf16[i] = uc[i];
|
||||
}
|
||||
#else
|
||||
memcpy(d->utf16, str.unicode(), str.length()*sizeof(ushort));
|
||||
#endif
|
||||
if (str.length() & 1) {
|
||||
d->utf16[str.length()] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator ==(const QString &str) const {
|
||||
int slen = str.length();
|
||||
int l = d->length;
|
||||
if (slen != l) {
|
||||
return false;
|
||||
}
|
||||
const ushort *s = (const ushort *)str.constData();
|
||||
const qle_ushort *a = d->utf16;
|
||||
const ushort *b = s;
|
||||
while (l-- && *a == *b) {
|
||||
a++, b++;
|
||||
}
|
||||
return (l == -1);
|
||||
}
|
||||
inline bool operator !=(const QString &str) const {
|
||||
return !operator ==(str);
|
||||
}
|
||||
inline bool operator >=(const QString &str) const {
|
||||
// ###
|
||||
return toString() >= str;
|
||||
}
|
||||
|
||||
inline bool operator<(const Latin1String &str) const;
|
||||
inline bool operator>=(const Latin1String &str) const {
|
||||
return !operator <(str);
|
||||
}
|
||||
inline bool operator ==(const Latin1String &str) const;
|
||||
|
||||
inline bool operator ==(const String &str) const {
|
||||
if (d->length != str.d->length) {
|
||||
return false;
|
||||
}
|
||||
return !memcmp(d->utf16, str.d->utf16, d->length * sizeof(ushort));
|
||||
}
|
||||
inline bool operator<(const String &other) const;
|
||||
inline bool operator >=(const String &other) const {
|
||||
return other < *this;
|
||||
}
|
||||
|
||||
inline QString toString() const {
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
return QString((QChar *)d->utf16, d->length);
|
||||
#else
|
||||
int l = d->length;
|
||||
QString str(l, Qt::Uninitialized);
|
||||
QChar *ch = str.data();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
ch[i] = QChar(d->utf16[i]);
|
||||
}
|
||||
return str;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Latin1String
|
||||
{
|
||||
public:
|
||||
Latin1String(const char *data) {
|
||||
d = (Data *)data;
|
||||
}
|
||||
|
||||
struct Data {
|
||||
qle_short length;
|
||||
char latin1[1];
|
||||
};
|
||||
Data *d;
|
||||
|
||||
inline Latin1String &operator=(const QString &str) {
|
||||
d->length = str.length();
|
||||
uchar *l = (uchar *)d->latin1;
|
||||
const ushort *uc = (const ushort *)str.unicode();
|
||||
for (int i = 0; i < str.length(); ++i) {
|
||||
*l++ = uc[i];
|
||||
}
|
||||
while ((quintptr)l & 0x3) {
|
||||
*l++ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator ==(const QString &str) const {
|
||||
return QLatin1String(d->latin1) == str;
|
||||
}
|
||||
inline bool operator !=(const QString &str) const {
|
||||
return !operator ==(str);
|
||||
}
|
||||
inline bool operator >=(const QString &str) const {
|
||||
// ###
|
||||
return toString() >= str;
|
||||
}
|
||||
|
||||
inline bool operator ==(const Latin1String &str) const {
|
||||
return d->length == str.d->length && !strcmp(d->latin1, str.d->latin1);
|
||||
}
|
||||
inline bool operator >=(const Latin1String &str) const {
|
||||
int l = qMin(d->length, str.d->length);
|
||||
int val = strncmp(d->latin1, str.d->latin1, l);
|
||||
if (!val) {
|
||||
val = d->length - str.d->length;
|
||||
}
|
||||
return val >= 0;
|
||||
}
|
||||
|
||||
inline bool operator ==(const String &str) const {
|
||||
return (str == *this);
|
||||
}
|
||||
inline bool operator >=(const String &str) const {
|
||||
return (str < *this);
|
||||
}
|
||||
|
||||
inline QString toString() const {
|
||||
return QString::fromLatin1(d->latin1, d->length);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool String::operator ==(const Latin1String &str) const
|
||||
{
|
||||
if ((int)d->length != (int)str.d->length) {
|
||||
return false;
|
||||
}
|
||||
const qle_ushort *uc = d->utf16;
|
||||
const qle_ushort *e = uc + d->length;
|
||||
const uchar *c = (uchar *)str.d->latin1;
|
||||
|
||||
while (uc < e) {
|
||||
if (*uc != *c) {
|
||||
return false;
|
||||
}
|
||||
++uc;
|
||||
++c;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool String::operator <(const String &other) const
|
||||
{
|
||||
int alen = d->length;
|
||||
int blen = other.d->length;
|
||||
int l = qMin(alen, blen);
|
||||
qle_ushort *a = d->utf16;
|
||||
qle_ushort *b = other.d->utf16;
|
||||
|
||||
while (l-- && *a == *b) {
|
||||
a++, b++;
|
||||
}
|
||||
if (l == -1) {
|
||||
return (alen < blen);
|
||||
}
|
||||
return (ushort) * a - (ushort) * b;
|
||||
}
|
||||
|
||||
inline bool String::operator<(const Latin1String &str) const
|
||||
{
|
||||
const uchar *c = (uchar *) str.d->latin1;
|
||||
if (!c || *c == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const qle_ushort *uc = d->utf16;
|
||||
const qle_ushort *e = uc + qMin((int)d->length, (int)str.d->length);
|
||||
|
||||
while (uc < e) {
|
||||
if (*uc != *c) {
|
||||
break;
|
||||
}
|
||||
++uc;
|
||||
++c;
|
||||
}
|
||||
return (uc == e ? (int)d->length < (int)str.d->length : (ushort) * uc < *c);
|
||||
|
||||
}
|
||||
|
||||
static inline void copyString(char *dest, const QString &str, bool compress)
|
||||
{
|
||||
if (compress) {
|
||||
Latin1String string(dest);
|
||||
string = str;
|
||||
} else {
|
||||
String string(dest);
|
||||
string = str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Base is the base class for both Object and Array. Both classe work more or less the same way.
|
||||
The class starts with a header (defined by the struct below), then followed by data (the data for
|
||||
values in the Array case and Entry's (see below) for objects.
|
||||
|
||||
After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and
|
||||
offsets from the beginning of the object to Entry's in the case of Object.
|
||||
|
||||
Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage
|
||||
of a binary search over the keys in an Object.
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
qle_uint size;
|
||||
union {
|
||||
uint _dummy;
|
||||
qle_bitfield<0, 1> is_object;
|
||||
qle_bitfield<1, 31> length;
|
||||
};
|
||||
offset tableOffset;
|
||||
// content follows here
|
||||
|
||||
inline bool isObject() const {
|
||||
return is_object;
|
||||
}
|
||||
inline bool isArray() const {
|
||||
return !isObject();
|
||||
}
|
||||
|
||||
inline offset *table() const {
|
||||
return (offset *) (((char *) this) + tableOffset);
|
||||
}
|
||||
|
||||
int reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace);
|
||||
void removeItems(int pos, int numItems);
|
||||
};
|
||||
|
||||
class Object : public Base
|
||||
{
|
||||
public:
|
||||
Entry *entryAt(int i) const {
|
||||
return reinterpret_cast<Entry *>(((char *)this) + table()[i]);
|
||||
}
|
||||
int indexOf(const QString &key, bool *exists);
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
|
||||
class Array : public Base
|
||||
{
|
||||
public:
|
||||
inline Value at(int i) const;
|
||||
inline Value &operator [](int i);
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
MaxSize = (1 << 27) - 1
|
||||
};
|
||||
union {
|
||||
uint _dummy;
|
||||
qle_bitfield<0, 3> type;
|
||||
qle_bitfield<3, 1> latinOrIntValue;
|
||||
qle_bitfield<4, 1> latinKey;
|
||||
qle_bitfield<5, 27> value;
|
||||
qle_signedbitfield<5, 27> int_value;
|
||||
};
|
||||
|
||||
inline char *data(const Base *b) const {
|
||||
return ((char *)b) + value;
|
||||
}
|
||||
int usedStorage(const Base *b) const;
|
||||
|
||||
bool toBoolean() const;
|
||||
double toDouble(const Base *b) const;
|
||||
QString toString(const Base *b) const;
|
||||
String asString(const Base *b) const;
|
||||
Latin1String asLatin1String(const Base *b) const;
|
||||
Base *base(const Base *b) const;
|
||||
|
||||
bool isValid(const Base *b) const;
|
||||
|
||||
static int requiredStorage(QJsonValue &v, bool *compressed);
|
||||
static uint valueToStore(const QJsonValue &v, uint offset);
|
||||
static void copyData(const QJsonValue &v, char *dest, bool compressed);
|
||||
};
|
||||
|
||||
inline Value Array::at(int i) const
|
||||
{
|
||||
return *(Value *) (table() + i);
|
||||
}
|
||||
|
||||
inline Value &Array::operator [](int i)
|
||||
{
|
||||
return *(Value *) (table() + i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Entry
|
||||
{
|
||||
public:
|
||||
Value value;
|
||||
// key
|
||||
// value data follows key
|
||||
|
||||
int size() const {
|
||||
int s = sizeof(Entry);
|
||||
if (value.latinKey) {
|
||||
s += sizeof(ushort) + qFromLittleEndian(*(ushort *) ((const char *)this + sizeof(Entry)));
|
||||
} else {
|
||||
s += sizeof(uint) + qFromLittleEndian(*(int *) ((const char *)this + sizeof(Entry)));
|
||||
}
|
||||
return alignedSize(s);
|
||||
}
|
||||
|
||||
int usedStorage(Base *b) const {
|
||||
return size() + value.usedStorage(b);
|
||||
}
|
||||
|
||||
String shallowKey() const {
|
||||
Q_ASSERT(!value.latinKey);
|
||||
return String((const char *)this + sizeof(Entry));
|
||||
}
|
||||
Latin1String shallowLatin1Key() const {
|
||||
Q_ASSERT(value.latinKey);
|
||||
return Latin1String((const char *)this + sizeof(Entry));
|
||||
}
|
||||
QString key() const {
|
||||
if (value.latinKey) {
|
||||
return shallowLatin1Key().toString();
|
||||
}
|
||||
return shallowKey().toString();
|
||||
}
|
||||
|
||||
bool operator ==(const QString &key) const;
|
||||
inline bool operator !=(const QString &key) const {
|
||||
return !operator ==(key);
|
||||
}
|
||||
inline bool operator >=(const QString &key) const;
|
||||
|
||||
bool operator ==(const Entry &other) const;
|
||||
bool operator >=(const Entry &other) const;
|
||||
};
|
||||
|
||||
inline bool Entry::operator >=(const QString &key) const
|
||||
{
|
||||
if (value.latinKey) {
|
||||
return (shallowLatin1Key() >= key);
|
||||
} else {
|
||||
return (shallowKey() >= key);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator <(const QString &key, const Entry &e)
|
||||
{
|
||||
return e >= key;
|
||||
}
|
||||
|
||||
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
qle_uint tag; // 'qbjs'
|
||||
qle_uint version; // 1
|
||||
Base *root() {
|
||||
return (Base *)(this + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline bool Value::toBoolean() const
|
||||
{
|
||||
Q_ASSERT(type == QJsonValue::Bool);
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
inline double Value::toDouble(const Base *b) const
|
||||
{
|
||||
Q_ASSERT(type == QJsonValue::Double);
|
||||
if (latinOrIntValue) {
|
||||
return int_value;
|
||||
}
|
||||
|
||||
quint64 i = qFromLittleEndian<quint64>((const uchar *)b + value);
|
||||
double d;
|
||||
memcpy(&d, &i, sizeof(double));
|
||||
return d;
|
||||
}
|
||||
|
||||
inline String Value::asString(const Base *b) const
|
||||
{
|
||||
Q_ASSERT(type == QJsonValue::String && !latinOrIntValue);
|
||||
return String(data(b));
|
||||
}
|
||||
|
||||
inline Latin1String Value::asLatin1String(const Base *b) const
|
||||
{
|
||||
Q_ASSERT(type == QJsonValue::String && latinOrIntValue);
|
||||
return Latin1String(data(b));
|
||||
}
|
||||
|
||||
inline QString Value::toString(const Base *b) const
|
||||
{
|
||||
if (latinOrIntValue) {
|
||||
return asLatin1String(b).toString();
|
||||
} else {
|
||||
return asString(b).toString();
|
||||
}
|
||||
}
|
||||
|
||||
inline Base *Value::base(const Base *b) const
|
||||
{
|
||||
Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object);
|
||||
return reinterpret_cast<Base *>(data(b));
|
||||
}
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
enum Validation {
|
||||
Unchecked,
|
||||
Validated,
|
||||
Invalid
|
||||
};
|
||||
|
||||
QAtomicInt ref;
|
||||
int alloc;
|
||||
union {
|
||||
char *rawData;
|
||||
Header *header;
|
||||
};
|
||||
uint compactionCounter;
|
||||
bool ownsData;
|
||||
|
||||
inline Data(char *raw, int a)
|
||||
: alloc(a), rawData(raw), compactionCounter(0), ownsData(true) {
|
||||
}
|
||||
inline Data(int reserved, QJsonValue::Type valueType)
|
||||
: rawData(0), compactionCounter(0), ownsData(true) {
|
||||
Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object);
|
||||
|
||||
alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset);
|
||||
header = (Header *)malloc(alloc);
|
||||
Q_CHECK_PTR(header);
|
||||
header->tag = QJsonDocument::BinaryFormatTag;
|
||||
header->version = 1;
|
||||
Base *b = header->root();
|
||||
b->size = sizeof(Base);
|
||||
b->is_object = (valueType == QJsonValue::Object);
|
||||
b->tableOffset = sizeof(Base);
|
||||
b->length = 0;
|
||||
}
|
||||
inline ~Data() {
|
||||
if (ownsData) {
|
||||
free(rawData);
|
||||
}
|
||||
}
|
||||
|
||||
uint offsetOf(const void *ptr) const {
|
||||
return (uint)(((char *)ptr - rawData));
|
||||
}
|
||||
|
||||
QJsonObject toObject(Object *o) const {
|
||||
return QJsonObject(const_cast<Data *>(this), o);
|
||||
}
|
||||
|
||||
QJsonArray toArray(Array *a) const {
|
||||
return QJsonArray(const_cast<Data *>(this), a);
|
||||
}
|
||||
|
||||
Data *clone(Base *b, int reserve = 0) {
|
||||
int size = sizeof(Header) + b->size;
|
||||
if (b == header->root() && ref == 1 && alloc >= size + reserve) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (reserve) {
|
||||
if (reserve < 128) {
|
||||
reserve = 128;
|
||||
}
|
||||
size = qMax(size + reserve, size * 2);
|
||||
}
|
||||
char *raw = (char *)malloc(size);
|
||||
Q_CHECK_PTR(raw);
|
||||
memcpy(raw + sizeof(Header), b, b->size);
|
||||
Header *h = (Header *)raw;
|
||||
h->tag = QJsonDocument::BinaryFormatTag;
|
||||
h->version = 1;
|
||||
Data *d = new Data(raw, size);
|
||||
d->compactionCounter = (b == header->root()) ? compactionCounter : 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
void compact();
|
||||
bool valid() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Data)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSON_P_H
|
File diff suppressed because it is too large
Load diff
|
@ -1,340 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONARRAY_H
|
||||
#define QJSONARRAY_H
|
||||
|
||||
#include <QtCore/qjsonvalue.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QDebug;
|
||||
class QStringList;
|
||||
|
||||
template <typename T> class QList;
|
||||
typedef QList<QVariant> QVariantList;
|
||||
|
||||
class Q_CORE_EXPORT QJsonArray
|
||||
{
|
||||
public:
|
||||
QJsonArray();
|
||||
~QJsonArray();
|
||||
|
||||
QJsonArray(const QJsonArray &other);
|
||||
QJsonArray &operator =(const QJsonArray &other);
|
||||
|
||||
static QJsonArray fromStringList(const QStringList &list);
|
||||
static QJsonArray fromVariantList(const QVariantList &list);
|
||||
QVariantList toVariantList() const;
|
||||
|
||||
int size() const;
|
||||
inline int count() const {
|
||||
return size();
|
||||
}
|
||||
|
||||
bool isEmpty() const;
|
||||
QJsonValue at(int i) const;
|
||||
QJsonValue first() const;
|
||||
QJsonValue last() const;
|
||||
|
||||
void prepend(const QJsonValue &value);
|
||||
void append(const QJsonValue &value);
|
||||
void removeAt(int i);
|
||||
QJsonValue takeAt(int i);
|
||||
inline void removeFirst() {
|
||||
removeAt(0);
|
||||
}
|
||||
inline void removeLast() {
|
||||
removeAt(size() - 1);
|
||||
}
|
||||
|
||||
void insert(int i, const QJsonValue &value);
|
||||
void replace(int i, const QJsonValue &value);
|
||||
|
||||
bool contains(const QJsonValue &element) const;
|
||||
QJsonValueRef operator[](int i);
|
||||
QJsonValue operator[](int i) const;
|
||||
|
||||
bool operator==(const QJsonArray &other) const;
|
||||
bool operator!=(const QJsonArray &other) const;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
QJsonArray *a;
|
||||
int i;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef QJsonValueRefPtr pointer;
|
||||
typedef QJsonValueRef reference;
|
||||
|
||||
inline iterator() : a(0), i(0) { }
|
||||
explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { }
|
||||
|
||||
inline QJsonValueRef operator*() const {
|
||||
return QJsonValueRef(a, i);
|
||||
}
|
||||
inline QJsonValueRefPtr operator->() const {
|
||||
return QJsonValueRefPtr(a, i);
|
||||
}
|
||||
inline QJsonValueRef operator[](int j) const {
|
||||
return QJsonValueRef(a, i + j);
|
||||
}
|
||||
|
||||
inline bool operator==(const iterator &o) const {
|
||||
return i == o.i;
|
||||
}
|
||||
inline bool operator!=(const iterator &o) const {
|
||||
return i != o.i;
|
||||
}
|
||||
inline bool operator<(const iterator &other) const {
|
||||
return i < other.i;
|
||||
}
|
||||
inline bool operator<=(const iterator &other) const {
|
||||
return i <= other.i;
|
||||
}
|
||||
inline bool operator>(const iterator &other) const {
|
||||
return i > other.i;
|
||||
}
|
||||
inline bool operator>=(const iterator &other) const {
|
||||
return i >= other.i;
|
||||
}
|
||||
inline bool operator==(const const_iterator &o) const {
|
||||
return i == o.i;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &o) const {
|
||||
return i != o.i;
|
||||
}
|
||||
inline bool operator<(const const_iterator &other) const {
|
||||
return i < other.i;
|
||||
}
|
||||
inline bool operator<=(const const_iterator &other) const {
|
||||
return i <= other.i;
|
||||
}
|
||||
inline bool operator>(const const_iterator &other) const {
|
||||
return i > other.i;
|
||||
}
|
||||
inline bool operator>=(const const_iterator &other) const {
|
||||
return i >= other.i;
|
||||
}
|
||||
inline iterator &operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator++(int) {
|
||||
iterator n = *this;
|
||||
++i;
|
||||
return n;
|
||||
}
|
||||
inline iterator &operator--() {
|
||||
i--;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator--(int) {
|
||||
iterator n = *this;
|
||||
i--;
|
||||
return n;
|
||||
}
|
||||
inline iterator &operator+=(int j) {
|
||||
i += j;
|
||||
return *this;
|
||||
}
|
||||
inline iterator &operator-=(int j) {
|
||||
i -= j;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator+(int j) const {
|
||||
return iterator(a, i + j);
|
||||
}
|
||||
inline iterator operator-(int j) const {
|
||||
return iterator(a, i - j);
|
||||
}
|
||||
inline int operator-(iterator j) const {
|
||||
return i - j.i;
|
||||
}
|
||||
};
|
||||
friend class iterator;
|
||||
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const QJsonArray *a;
|
||||
int i;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef qptrdiff difference_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef QJsonValuePtr pointer;
|
||||
typedef QJsonValue reference;
|
||||
|
||||
inline const_iterator() : a(0), i(0) { }
|
||||
explicit inline const_iterator(const QJsonArray *array, int index) : a(array), i(index) { }
|
||||
inline const_iterator(const const_iterator &o) : a(o.a), i(o.i) {}
|
||||
inline const_iterator(const iterator &o) : a(o.a), i(o.i) {}
|
||||
|
||||
inline QJsonValue operator*() const {
|
||||
return a->at(i);
|
||||
}
|
||||
inline QJsonValuePtr operator->() const {
|
||||
return QJsonValuePtr(a->at(i));
|
||||
}
|
||||
inline QJsonValue operator[](int j) const {
|
||||
return a->at(i + j);
|
||||
}
|
||||
inline bool operator==(const const_iterator &o) const {
|
||||
return i == o.i;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &o) const {
|
||||
return i != o.i;
|
||||
}
|
||||
inline bool operator<(const const_iterator &other) const {
|
||||
return i < other.i;
|
||||
}
|
||||
inline bool operator<=(const const_iterator &other) const {
|
||||
return i <= other.i;
|
||||
}
|
||||
inline bool operator>(const const_iterator &other) const {
|
||||
return i > other.i;
|
||||
}
|
||||
inline bool operator>=(const const_iterator &other) const {
|
||||
return i >= other.i;
|
||||
}
|
||||
inline const_iterator &operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator++(int) {
|
||||
const_iterator n = *this;
|
||||
++i;
|
||||
return n;
|
||||
}
|
||||
inline const_iterator &operator--() {
|
||||
i--;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator--(int) {
|
||||
const_iterator n = *this;
|
||||
i--;
|
||||
return n;
|
||||
}
|
||||
inline const_iterator &operator+=(int j) {
|
||||
i += j;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator &operator-=(int j) {
|
||||
i -= j;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator+(int j) const {
|
||||
return const_iterator(a, i + j);
|
||||
}
|
||||
inline const_iterator operator-(int j) const {
|
||||
return const_iterator(a, i - j);
|
||||
}
|
||||
inline int operator-(const_iterator j) const {
|
||||
return i - j.i;
|
||||
}
|
||||
};
|
||||
friend class const_iterator;
|
||||
|
||||
// stl style
|
||||
inline iterator begin() {
|
||||
detach();
|
||||
return iterator(this, 0);
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
inline const_iterator constBegin() const {
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
inline iterator end() {
|
||||
detach();
|
||||
return iterator(this, size());
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(this, size());
|
||||
}
|
||||
inline const_iterator constEnd() const {
|
||||
return const_iterator(this, size());
|
||||
}
|
||||
iterator insert(iterator before, const QJsonValue &value) {
|
||||
insert(before.i, value);
|
||||
return before;
|
||||
}
|
||||
iterator erase(iterator it) {
|
||||
removeAt(it.i);
|
||||
return it;
|
||||
}
|
||||
|
||||
// more Qt
|
||||
typedef iterator Iterator;
|
||||
typedef const_iterator ConstIterator;
|
||||
|
||||
// stl compatibility
|
||||
inline void push_back(const QJsonValue &t) {
|
||||
append(t);
|
||||
}
|
||||
inline void push_front(const QJsonValue &t) {
|
||||
prepend(t);
|
||||
}
|
||||
inline void pop_front() {
|
||||
removeFirst();
|
||||
}
|
||||
inline void pop_back() {
|
||||
removeLast();
|
||||
}
|
||||
inline bool empty() const {
|
||||
return isEmpty();
|
||||
}
|
||||
typedef int size_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef const value_type *const_pointer;
|
||||
typedef QJsonValueRef reference;
|
||||
typedef QJsonValue const_reference;
|
||||
typedef int difference_type;
|
||||
|
||||
private:
|
||||
friend class QJsonPrivate::Data;
|
||||
friend class QJsonValue;
|
||||
friend class QJsonDocument;
|
||||
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
|
||||
|
||||
QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array);
|
||||
void compact();
|
||||
void detach(uint reserve = 0);
|
||||
|
||||
QJsonPrivate::Data *d;
|
||||
QJsonPrivate::Array *a;
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSONARRAY_H
|
|
@ -1,503 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qjsondocument.h"
|
||||
#include "qjsonobject.h"
|
||||
#include "qjsonvalue.h"
|
||||
#include "qjsonarray.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qvariant.h"
|
||||
#include "qdebug.h"
|
||||
#include "qjsonwriter_p.h"
|
||||
#include "qjsonparser_p.h"
|
||||
#include "qjson_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QJsonDocument::QJsonDocument()
|
||||
: d(0)
|
||||
{
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument(const QJsonObject &object)
|
||||
: d(0)
|
||||
{
|
||||
setObject(object);
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument(const QJsonArray &array)
|
||||
: d(0)
|
||||
{
|
||||
setArray(array);
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument(QJsonPrivate::Data *data)
|
||||
: d(data)
|
||||
{
|
||||
Q_ASSERT(d);
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
QJsonDocument::~QJsonDocument()
|
||||
{
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument(const QJsonDocument &other)
|
||||
{
|
||||
d = other.d;
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Assigns the \a other document to this QJsonDocument.
|
||||
* Returns a reference to this object.
|
||||
*/
|
||||
QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
|
||||
{
|
||||
if (d != other.d) {
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
d = other.d;
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*! \enum QJsonDocument::DataValidation
|
||||
|
||||
This value is used to tell QJsonDocument whether to validate the binary data
|
||||
when converting to a QJsonDocument using fromBinaryData() or fromRawData().
|
||||
|
||||
\value Validate Validate the data before using it. This is the default.
|
||||
\value BypassValidation Bypasses data validation. Only use if you received the
|
||||
data from a trusted place and know it's valid, as using of invalid data can crash
|
||||
the application.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates a QJsonDocument that uses the first \a size bytes from
|
||||
\a data. It assumes \a data contains a binary encoded JSON document.
|
||||
The created document does not take ownership of \a data and the caller
|
||||
has to guarantee that \a data will not be deleted or modified as long as
|
||||
any QJsonDocument, QJsonObject or QJsonArray still references the data.
|
||||
|
||||
\a data has to be aligned to a 4 byte boundary.
|
||||
|
||||
\a validation decides whether the data is checked for validity before being used.
|
||||
By default the data is validated. If the \a data is not valid, the method returns
|
||||
a null document.
|
||||
|
||||
Returns a QJsonDocument representing the data.
|
||||
|
||||
\sa rawData(), fromBinaryData(), isNull(), DataValidation
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation)
|
||||
{
|
||||
if (quintptr(data) & 3) {
|
||||
qWarning() << "QJsonDocument::fromRawData: data has to have 4 byte alignment";
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
QJsonPrivate::Data *d = new QJsonPrivate::Data((char *)data, size);
|
||||
d->ownsData = false;
|
||||
|
||||
if (validation != BypassValidation && !d->valid()) {
|
||||
delete d;
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
return QJsonDocument(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the raw binary representation of the data
|
||||
\a size will contain the size of the returned data.
|
||||
|
||||
This method is useful to e.g. stream the JSON document
|
||||
in it's binary form to a file.
|
||||
*/
|
||||
const char *QJsonDocument::rawData(int *size) const
|
||||
{
|
||||
if (!d) {
|
||||
*size = 0;
|
||||
return 0;
|
||||
}
|
||||
*size = d->alloc;
|
||||
return d->rawData;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a QJsonDocument from \a data.
|
||||
|
||||
\a validation decides whether the data is checked for validity before being used.
|
||||
By default the data is validated. If the \a data is not valid, the method returns
|
||||
a null document.
|
||||
|
||||
\sa toBinaryData(), fromRawData(), isNull(), DataValidation
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation)
|
||||
{
|
||||
if (data.size() < (int)(sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base))) {
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
QJsonPrivate::Header h;
|
||||
memcpy(&h, data.constData(), sizeof(QJsonPrivate::Header));
|
||||
QJsonPrivate::Base root;
|
||||
memcpy(&root, data.constData() + sizeof(QJsonPrivate::Header), sizeof(QJsonPrivate::Base));
|
||||
|
||||
// do basic checks here, so we don't try to allocate more memory than we can.
|
||||
if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1u ||
|
||||
sizeof(QJsonPrivate::Header) + root.size > (uint)data.size()) {
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
const uint size = sizeof(QJsonPrivate::Header) + root.size;
|
||||
char *raw = (char *)malloc(size);
|
||||
if (!raw) {
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
memcpy(raw, data.constData(), size);
|
||||
QJsonPrivate::Data *d = new QJsonPrivate::Data(raw, size);
|
||||
|
||||
if (validation != BypassValidation && !d->valid()) {
|
||||
delete d;
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
return QJsonDocument(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a QJsonDocument from the QVariant \a variant.
|
||||
|
||||
If the \a variant contains any other type than a QVariant::Map,
|
||||
QVariant::List or QVariant::StringList, the returned document
|
||||
document is invalid.
|
||||
|
||||
\sa toVariant()
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
|
||||
{
|
||||
QJsonDocument doc;
|
||||
if (variant.type() == QVariant::Map) {
|
||||
doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));
|
||||
} else if (variant.type() == QVariant::List) {
|
||||
doc.setArray(QJsonArray::fromVariantList(variant.toList()));
|
||||
} else if (variant.type() == QVariant::StringList) {
|
||||
doc.setArray(QJsonArray::fromStringList(variant.toStringList()));
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QVariant representing the Json document.
|
||||
|
||||
The returned variant will be a QVariantList if the document is
|
||||
a QJsonArray and a QVariantMap if the document is a QJsonObject.
|
||||
|
||||
\sa fromVariant(), QJsonValue::toVariant()
|
||||
*/
|
||||
QVariant QJsonDocument::toVariant() const
|
||||
{
|
||||
if (!d) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (d->header->root()->isArray()) {
|
||||
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root())).toVariantList();
|
||||
} else {
|
||||
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root())).toVariantMap();
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray QJsonDocument::toJson(JsonFormat format) const
|
||||
{
|
||||
if (!d) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray json;
|
||||
|
||||
if (d->header->root()->isArray()) {
|
||||
QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(d->header->root()), json, 0, (format == Compact));
|
||||
} else {
|
||||
QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(d->header->root()), json, 0,
|
||||
(format == Compact));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/*!
|
||||
Parses a UTF-8 encoded JSON document and creates a QJsonDocument
|
||||
from it.
|
||||
|
||||
\a json contains the json document to be parsed.
|
||||
|
||||
The optional \a error variable can be used to pass in a QJsonParseError data
|
||||
structure that will contain information about possible errors encountered during
|
||||
parsing.
|
||||
|
||||
\sa toJson(), QJsonParseError
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error)
|
||||
{
|
||||
QJsonPrivate::Parser parser(json.constData(), json.length());
|
||||
return parser.parse(error);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the document doesn't contain any data.
|
||||
*/
|
||||
bool QJsonDocument::isEmpty() const
|
||||
{
|
||||
if (!d) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a binary representation of the document.
|
||||
|
||||
The binary representation is also the native format used internally in Qt,
|
||||
and is very efficient and fast to convert to and from.
|
||||
|
||||
The binary format can be stored on disk and interchanged with other applications
|
||||
or computers. fromBinaryData() can be used to convert it back into a
|
||||
JSON document.
|
||||
|
||||
\sa fromBinaryData()
|
||||
*/
|
||||
QByteArray QJsonDocument::toBinaryData() const
|
||||
{
|
||||
if (!d || !d->rawData) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray(d->rawData, d->header->root()->size + sizeof(QJsonPrivate::Header));
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the document contains an array.
|
||||
|
||||
\sa array(), isObject()
|
||||
*/
|
||||
bool QJsonDocument::isArray() const
|
||||
{
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData;
|
||||
return h->root()->isArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the document contains an object.
|
||||
|
||||
\sa object(), isArray()
|
||||
*/
|
||||
bool QJsonDocument::isObject() const
|
||||
{
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData;
|
||||
return h->root()->isObject();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the QJsonObject contained in the document.
|
||||
|
||||
Returns an empty object if the document contains an
|
||||
array.
|
||||
|
||||
\sa isObject(), array(), setObject()
|
||||
*/
|
||||
QJsonObject QJsonDocument::object() const
|
||||
{
|
||||
if (d) {
|
||||
QJsonPrivate::Base *b = d->header->root();
|
||||
if (b->isObject()) {
|
||||
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(b));
|
||||
}
|
||||
}
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the QJsonArray contained in the document.
|
||||
|
||||
Returns an empty array if the document contains an
|
||||
object.
|
||||
|
||||
\sa isArray(), object(), setArray()
|
||||
*/
|
||||
QJsonArray QJsonDocument::array() const
|
||||
{
|
||||
if (d) {
|
||||
QJsonPrivate::Base *b = d->header->root();
|
||||
if (b->isArray()) {
|
||||
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(b));
|
||||
}
|
||||
}
|
||||
return QJsonArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a object as the main object of this document.
|
||||
|
||||
\sa setArray(), object()
|
||||
*/
|
||||
void QJsonDocument::setObject(const QJsonObject &object)
|
||||
{
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
|
||||
d = object.d;
|
||||
|
||||
if (!d) {
|
||||
d = new QJsonPrivate::Data(0, QJsonValue::Object);
|
||||
} else if (d->compactionCounter || object.o != d->header->root()) {
|
||||
QJsonObject o(object);
|
||||
if (d->compactionCounter) {
|
||||
o.compact();
|
||||
} else {
|
||||
o.detach();
|
||||
}
|
||||
d = o.d;
|
||||
d->ref.ref();
|
||||
return;
|
||||
}
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a array as the main object of this document.
|
||||
|
||||
\sa setObject(), array()
|
||||
*/
|
||||
void QJsonDocument::setArray(const QJsonArray &array)
|
||||
{
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
|
||||
d = array.d;
|
||||
|
||||
if (!d) {
|
||||
d = new QJsonPrivate::Data(0, QJsonValue::Array);
|
||||
} else if (d->compactionCounter || array.a != d->header->root()) {
|
||||
QJsonArray a(array);
|
||||
if (d->compactionCounter) {
|
||||
a.compact();
|
||||
} else {
|
||||
a.detach();
|
||||
}
|
||||
d = a.d;
|
||||
d->ref.ref();
|
||||
return;
|
||||
}
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the \a other document is equal to this document.
|
||||
*/
|
||||
bool QJsonDocument::operator==(const QJsonDocument &other) const
|
||||
{
|
||||
if (d == other.d) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!d || !other.d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d->header->root()->isArray() != other.d->header->root()->isArray()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d->header->root()->isObject())
|
||||
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root()))
|
||||
== QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.d->header->root()));
|
||||
else
|
||||
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root()))
|
||||
== QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.d->header->root()));
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QJsonDocument::operator!=(const QJsonDocument &other) const
|
||||
|
||||
returns \c true if \a other is not equal to this document
|
||||
*/
|
||||
|
||||
/*!
|
||||
returns true if this document is null.
|
||||
|
||||
Null documents are documents created through the default constructor.
|
||||
|
||||
Documents created from UTF-8 encoded text or the binary format are
|
||||
validated during parsing. If validation fails, the returned document
|
||||
will also be null.
|
||||
*/
|
||||
bool QJsonDocument::isNull() const
|
||||
{
|
||||
return (d == 0);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const QJsonDocument &o)
|
||||
{
|
||||
if (!o.d) {
|
||||
dbg << "QJsonDocument()";
|
||||
return dbg;
|
||||
}
|
||||
QByteArray json;
|
||||
if (o.d->header->root()->isArray()) {
|
||||
QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(o.d->header->root()), json, 0, true);
|
||||
} else {
|
||||
QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(o.d->header->root()), json, 0, true);
|
||||
}
|
||||
dbg.nospace() << "QJsonDocument("
|
||||
<< json.constData() // print as utf-8 string without extra quotation marks
|
||||
<< ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -1,136 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONDOCUMENT_H
|
||||
#define QJSONDOCUMENT_H
|
||||
|
||||
#include <QtCore/qjsonvalue.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QDebug;
|
||||
|
||||
namespace QJsonPrivate {
|
||||
class Parser;
|
||||
}
|
||||
|
||||
struct Q_CORE_EXPORT QJsonParseError {
|
||||
enum ParseError {
|
||||
NoError = 0,
|
||||
UnterminatedObject,
|
||||
MissingNameSeparator,
|
||||
UnterminatedArray,
|
||||
MissingValueSeparator,
|
||||
IllegalValue,
|
||||
TerminationByNumber,
|
||||
IllegalNumber,
|
||||
IllegalEscapeSequence,
|
||||
IllegalUTF8String,
|
||||
UnterminatedString,
|
||||
MissingObject,
|
||||
DeepNesting,
|
||||
DocumentTooLarge
|
||||
};
|
||||
|
||||
QString errorString() const;
|
||||
|
||||
int offset;
|
||||
ParseError error;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QJsonDocument
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef Q_LITTLE_ENDIAN
|
||||
static const uint BinaryFormatTag = ('q') | ('b' << 8) | ('j' << 16) | ('s' << 24);
|
||||
#else
|
||||
static const uint BinaryFormatTag = ('q' << 24) | ('b' << 16) | ('j' << 8) | ('s');
|
||||
#endif
|
||||
|
||||
QJsonDocument();
|
||||
explicit QJsonDocument(const QJsonObject &object);
|
||||
explicit QJsonDocument(const QJsonArray &array);
|
||||
~QJsonDocument();
|
||||
|
||||
QJsonDocument(const QJsonDocument &other);
|
||||
QJsonDocument &operator =(const QJsonDocument &other);
|
||||
|
||||
enum DataValidation {
|
||||
Validate,
|
||||
BypassValidation
|
||||
};
|
||||
|
||||
static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate);
|
||||
const char *rawData(int *size) const;
|
||||
|
||||
static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
|
||||
QByteArray toBinaryData() const;
|
||||
|
||||
static QJsonDocument fromVariant(const QVariant &variant);
|
||||
QVariant toVariant() const;
|
||||
|
||||
enum JsonFormat {
|
||||
Indented,
|
||||
Compact
|
||||
};
|
||||
|
||||
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = 0);
|
||||
|
||||
QByteArray toJson(JsonFormat format = Indented) const;
|
||||
|
||||
bool isEmpty() const;
|
||||
bool isArray() const;
|
||||
bool isObject() const;
|
||||
|
||||
QJsonObject object() const;
|
||||
QJsonArray array() const;
|
||||
|
||||
void setObject(const QJsonObject &object);
|
||||
void setArray(const QJsonArray &array);
|
||||
|
||||
bool operator==(const QJsonDocument &other) const;
|
||||
bool operator!=(const QJsonDocument &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
private:
|
||||
friend class QJsonValue;
|
||||
friend class QJsonPrivate::Data;
|
||||
friend class QJsonPrivate::Parser;
|
||||
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
|
||||
|
||||
QJsonDocument(QJsonPrivate::Data *data);
|
||||
|
||||
QJsonPrivate::Data *d;
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSONDOCUMENT_H
|
File diff suppressed because it is too large
Load diff
|
@ -1,305 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONOBJECT_H
|
||||
#define QJSONOBJECT_H
|
||||
|
||||
#include "qjsonvalue.h"
|
||||
#include <QtCore/qcontainerfwd.h>
|
||||
#include <QtCore/qiterator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QDebug;
|
||||
typedef QMap<QString, QVariant> QVariantMap;
|
||||
typedef QHash<QString, QVariant> QVariantHash;
|
||||
|
||||
class Q_CORE_EXPORT QJsonObject
|
||||
{
|
||||
public:
|
||||
QJsonObject();
|
||||
~QJsonObject();
|
||||
|
||||
QJsonObject(const QJsonObject &other);
|
||||
QJsonObject &operator =(const QJsonObject &other);
|
||||
|
||||
static QJsonObject fromVariantMap(const QVariantMap &map);
|
||||
QVariantMap toVariantMap() const;
|
||||
static QJsonObject fromVariantHash(const QVariantHash &map);
|
||||
QVariantHash toVariantHash() const;
|
||||
|
||||
QStringList keys() const;
|
||||
int size() const;
|
||||
inline int count() const {
|
||||
return size();
|
||||
}
|
||||
inline int length() const {
|
||||
return size();
|
||||
}
|
||||
bool isEmpty() const;
|
||||
|
||||
QJsonValue value(const QString &key) const;
|
||||
QJsonValue operator[] (const QString &key) const;
|
||||
QJsonValueRef operator[] (const QString &key);
|
||||
|
||||
void remove(const QString &key);
|
||||
QJsonValue take(const QString &key);
|
||||
bool contains(const QString &key) const;
|
||||
|
||||
bool operator==(const QJsonObject &other) const;
|
||||
bool operator!=(const QJsonObject &other) const;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
class iterator
|
||||
{
|
||||
friend class const_iterator;
|
||||
friend class QJsonObject;
|
||||
QJsonObject *o;
|
||||
int i;
|
||||
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef QJsonValueRefPtr pointer;
|
||||
typedef QJsonValueRef reference;
|
||||
|
||||
inline iterator() : o(0), i(0) {}
|
||||
inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
|
||||
|
||||
inline QString key() const {
|
||||
return o->keyAt(i);
|
||||
}
|
||||
inline QJsonValueRef value() const {
|
||||
return QJsonValueRef(o, i);
|
||||
}
|
||||
inline QJsonValueRef operator*() const {
|
||||
return QJsonValueRef(o, i);
|
||||
}
|
||||
inline QJsonValueRefPtr operator->() const {
|
||||
return QJsonValueRefPtr(o, i);
|
||||
}
|
||||
inline bool operator==(const iterator &other) const {
|
||||
return i == other.i;
|
||||
}
|
||||
inline bool operator!=(const iterator &other) const {
|
||||
return i != other.i;
|
||||
}
|
||||
|
||||
inline iterator &operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator++(int) {
|
||||
iterator r = *this;
|
||||
++i;
|
||||
return r;
|
||||
}
|
||||
inline iterator &operator--() {
|
||||
--i;
|
||||
return *this;
|
||||
}
|
||||
inline iterator operator--(int) {
|
||||
iterator r = *this;
|
||||
--i;
|
||||
return r;
|
||||
}
|
||||
inline iterator operator+(int j) const {
|
||||
iterator r = *this;
|
||||
r.i += j;
|
||||
return r;
|
||||
}
|
||||
inline iterator operator-(int j) const {
|
||||
return operator+(-j);
|
||||
}
|
||||
inline iterator &operator+=(int j) {
|
||||
i += j;
|
||||
return *this;
|
||||
}
|
||||
inline iterator &operator-=(int j) {
|
||||
i -= j;
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool operator==(const const_iterator &other) const {
|
||||
return i == other.i;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &other) const {
|
||||
return i != other.i;
|
||||
}
|
||||
};
|
||||
friend class iterator;
|
||||
|
||||
class const_iterator
|
||||
{
|
||||
friend class iterator;
|
||||
const QJsonObject *o;
|
||||
int i;
|
||||
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef QJsonValue* value_type;
|
||||
typedef QJsonValuePtr pointer;
|
||||
typedef QJsonValue reference;
|
||||
|
||||
inline const_iterator() : o(0), i(0) {}
|
||||
inline const_iterator(const QJsonObject *obj, int index)
|
||||
: o(obj), i(index) {}
|
||||
inline const_iterator(const iterator &other)
|
||||
: o(other.o), i(other.i) {}
|
||||
|
||||
inline QString key() const {
|
||||
return o->keyAt(i);
|
||||
}
|
||||
inline QJsonValue value() const {
|
||||
return o->valueAt(i);
|
||||
}
|
||||
inline QJsonValue operator*() const {
|
||||
return o->valueAt(i);
|
||||
}
|
||||
inline QJsonValuePtr operator->() const {
|
||||
return QJsonValuePtr(o->valueAt(i));
|
||||
}
|
||||
inline bool operator==(const const_iterator &other) const {
|
||||
return i == other.i;
|
||||
}
|
||||
inline bool operator!=(const const_iterator &other) const {
|
||||
return i != other.i;
|
||||
}
|
||||
|
||||
inline const_iterator &operator++() {
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator++(int) {
|
||||
const_iterator r = *this;
|
||||
++i;
|
||||
return r;
|
||||
}
|
||||
inline const_iterator &operator--() {
|
||||
--i;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator operator--(int) {
|
||||
const_iterator r = *this;
|
||||
--i;
|
||||
return r;
|
||||
}
|
||||
inline const_iterator operator+(int j) const {
|
||||
const_iterator r = *this;
|
||||
r.i += j;
|
||||
return r;
|
||||
}
|
||||
inline const_iterator operator-(int j) const {
|
||||
return operator+(-j);
|
||||
}
|
||||
inline const_iterator &operator+=(int j) {
|
||||
i += j;
|
||||
return *this;
|
||||
}
|
||||
inline const_iterator &operator-=(int j) {
|
||||
i -= j;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const iterator &other) const {
|
||||
return i == other.i;
|
||||
}
|
||||
inline bool operator!=(const iterator &other) const {
|
||||
return i != other.i;
|
||||
}
|
||||
};
|
||||
friend class const_iterator;
|
||||
|
||||
// STL style
|
||||
inline iterator begin() {
|
||||
detach();
|
||||
return iterator(this, 0);
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
inline const_iterator constBegin() const {
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
inline iterator end() {
|
||||
detach();
|
||||
return iterator(this, size());
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(this, size());
|
||||
}
|
||||
inline const_iterator constEnd() const {
|
||||
return const_iterator(this, size());
|
||||
}
|
||||
iterator erase(iterator it);
|
||||
|
||||
// more Qt
|
||||
typedef iterator Iterator;
|
||||
typedef const_iterator ConstIterator;
|
||||
iterator find(const QString &key);
|
||||
const_iterator find(const QString &key) const {
|
||||
return constFind(key);
|
||||
}
|
||||
const_iterator constFind(const QString &key) const;
|
||||
iterator insert(const QString &key, const QJsonValue &value);
|
||||
|
||||
// STL compatibility
|
||||
typedef QJsonValue mapped_type;
|
||||
typedef QString key_type;
|
||||
typedef int size_type;
|
||||
|
||||
inline bool empty() const {
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class QJsonPrivate::Data;
|
||||
friend class QJsonValue;
|
||||
friend class QJsonDocument;
|
||||
friend class QJsonValueRef;
|
||||
|
||||
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
|
||||
|
||||
QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object);
|
||||
void detach(uint reserve = 0);
|
||||
void compact();
|
||||
|
||||
QString keyAt(int i) const;
|
||||
QJsonValue valueAt(int i) const;
|
||||
void setValueAt(int i, const QJsonValue &val);
|
||||
|
||||
QJsonPrivate::Data *d;
|
||||
QJsonPrivate::Object *o;
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSONOBJECT_H
|
|
@ -1,984 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcoreapplication.h"
|
||||
#include "qdebug.h"
|
||||
#include "qjsonparser_p.h"
|
||||
#include "qjson_p.h"
|
||||
|
||||
//#define PARSER_DEBUG
|
||||
#ifdef PARSER_DEBUG
|
||||
static int indent = 0;
|
||||
#define BEGIN qDebug() << QByteArray(4*indent++, ' ').constData() << "pos=" << current
|
||||
#define END --indent
|
||||
#define DEBUG qDebug() << QByteArray(4*indent, ' ').constData()
|
||||
#else
|
||||
#define BEGIN if (1) ; else qDebug()
|
||||
#define END do {} while (0)
|
||||
#define DEBUG if (1) ; else qDebug()
|
||||
#endif
|
||||
|
||||
static const int nestingLimit = 1024;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// error strings for the JSON parser
|
||||
#define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred")
|
||||
#define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object")
|
||||
#define JSONERR_MISS_NSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing name separator")
|
||||
#define JSONERR_UNTERM_AR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated array")
|
||||
#define JSONERR_MISS_VSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing value separator")
|
||||
#define JSONERR_ILLEGAL_VAL QT_TRANSLATE_NOOP("QJsonParseError", "illegal value")
|
||||
#define JSONERR_END_OF_NUM QT_TRANSLATE_NOOP("QJsonParseError", "invalid termination by number")
|
||||
#define JSONERR_ILLEGAL_NUM QT_TRANSLATE_NOOP("QJsonParseError", "illegal number")
|
||||
#define JSONERR_STR_ESC_SEQ QT_TRANSLATE_NOOP("QJsonParseError", "invalid escape sequence")
|
||||
#define JSONERR_STR_UTF8 QT_TRANSLATE_NOOP("QJsonParseError", "invalid UTF8 string")
|
||||
#define JSONERR_UTERM_STR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated string")
|
||||
#define JSONERR_MISS_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "object is missing after a comma")
|
||||
#define JSONERR_DEEP_NEST QT_TRANSLATE_NOOP("QJsonParseError", "too deeply nested document")
|
||||
#define JSONERR_DOC_LARGE QT_TRANSLATE_NOOP("QJsonParseError", "too large document")
|
||||
|
||||
/*!
|
||||
\class QJsonParseError
|
||||
\inmodule QtCore
|
||||
\ingroup json
|
||||
\reentrant
|
||||
\since 4.9
|
||||
|
||||
\brief The QJsonParseError class is used to report errors during JSON parsing.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QJsonParseError::ParseError
|
||||
|
||||
This enum describes the type of error that occurred during the parsing of a JSON document.
|
||||
|
||||
\value NoError No error occurred
|
||||
\value UnterminatedObject An object is not correctly terminated with a closing curly bracket
|
||||
\value MissingNameSeparator A comma separating different items is missing
|
||||
\value UnterminatedArray The array is not correctly terminated with a closing square bracket
|
||||
\value MissingValueSeparator A colon separating keys from values inside objects is missing
|
||||
\value IllegalValue The value is illegal
|
||||
\value TerminationByNumber The input stream ended while parsing a number
|
||||
\value IllegalNumber The number is not well formed
|
||||
\value IllegalEscapeSequence An illegal escape sequence occurred in the input
|
||||
\value IllegalUTF8String An illegal UTF8 sequence occurred in the input
|
||||
\value UnterminatedString A string wasn't terminated with a quote
|
||||
\value MissingObject An object was expected but couldn't be found
|
||||
\value DeepNesting The JSON document is too deeply nested for the parser to parse it
|
||||
\value DocumentTooLarge The JSON document is too large for the parser to parse it
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QJsonParseError::error
|
||||
|
||||
Contains the type of the parse error. Is equal to QJsonParseError::NoError if the document
|
||||
was parsed correctly.
|
||||
|
||||
\sa ParseError, errorString()
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\variable QJsonParseError::offset
|
||||
|
||||
Contains the offset in the input string where the parse error occurred.
|
||||
|
||||
\sa error, errorString()
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the human-readable message appropriate to the reported JSON parsing error.
|
||||
|
||||
\sa error
|
||||
*/
|
||||
QString QJsonParseError::errorString() const
|
||||
{
|
||||
const char *sz = "";
|
||||
switch (error) {
|
||||
case NoError:
|
||||
sz = JSONERR_OK;
|
||||
break;
|
||||
case UnterminatedObject:
|
||||
sz = JSONERR_UNTERM_OBJ;
|
||||
break;
|
||||
case MissingNameSeparator:
|
||||
sz = JSONERR_MISS_NSEP;
|
||||
break;
|
||||
case UnterminatedArray:
|
||||
sz = JSONERR_UNTERM_AR;
|
||||
break;
|
||||
case MissingValueSeparator:
|
||||
sz = JSONERR_MISS_VSEP;
|
||||
break;
|
||||
case IllegalValue:
|
||||
sz = JSONERR_ILLEGAL_VAL;
|
||||
break;
|
||||
case TerminationByNumber:
|
||||
sz = JSONERR_END_OF_NUM;
|
||||
break;
|
||||
case IllegalNumber:
|
||||
sz = JSONERR_ILLEGAL_NUM;
|
||||
break;
|
||||
case IllegalEscapeSequence:
|
||||
sz = JSONERR_STR_ESC_SEQ;
|
||||
break;
|
||||
case IllegalUTF8String:
|
||||
sz = JSONERR_STR_UTF8;
|
||||
break;
|
||||
case UnterminatedString:
|
||||
sz = JSONERR_UTERM_STR;
|
||||
break;
|
||||
case MissingObject:
|
||||
sz = JSONERR_MISS_OBJ;
|
||||
break;
|
||||
case DeepNesting:
|
||||
sz = JSONERR_DEEP_NEST;
|
||||
break;
|
||||
case DocumentTooLarge:
|
||||
sz = JSONERR_DOC_LARGE;
|
||||
break;
|
||||
}
|
||||
|
||||
return QCoreApplication::translate("QJsonParseError", sz);
|
||||
}
|
||||
|
||||
using namespace QJsonPrivate;
|
||||
|
||||
Parser::Parser(const char *json, int length)
|
||||
: head(json), json(json), data(0), dataLength(0), current(0), nestingLevel(0), lastError(QJsonParseError::NoError)
|
||||
{
|
||||
end = json + length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
begin-array = ws %x5B ws ; [ left square bracket
|
||||
|
||||
begin-object = ws %x7B ws ; { left curly bracket
|
||||
|
||||
end-array = ws %x5D ws ; ] right square bracket
|
||||
|
||||
end-object = ws %x7D ws ; } right curly bracket
|
||||
|
||||
name-separator = ws %x3A ws ; : colon
|
||||
|
||||
value-separator = ws %x2C ws ; , comma
|
||||
|
||||
Insignificant whitespace is allowed before or after any of the six
|
||||
structural characters.
|
||||
|
||||
ws = *(
|
||||
%x20 / ; WhiteSpace
|
||||
%x09 / ; Horizontal tab
|
||||
%x0A / ; Line feed or New line
|
||||
%x0D ; Carriage return
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
enum {
|
||||
WhiteSpace = 0x20,
|
||||
Tab = 0x09,
|
||||
LineFeed = 0x0a,
|
||||
Return = 0x0d,
|
||||
BeginArray = 0x5b,
|
||||
BeginObject = 0x7b,
|
||||
EndArray = 0x5d,
|
||||
EndObject = 0x7d,
|
||||
NameSeparator = 0x3a,
|
||||
ValueSeparator = 0x2c,
|
||||
Quote = 0x22
|
||||
};
|
||||
|
||||
void Parser::eatBOM()
|
||||
{
|
||||
// eat UTF-8 byte order mark
|
||||
uchar utf8bom[3] = { 0xef, 0xbb, 0xbf };
|
||||
if (end - json > 3 &&
|
||||
(uchar)json[0] == utf8bom[0] &&
|
||||
(uchar)json[1] == utf8bom[1] &&
|
||||
(uchar)json[2] == utf8bom[2]) {
|
||||
json += 3;
|
||||
}
|
||||
}
|
||||
|
||||
bool Parser::eatSpace()
|
||||
{
|
||||
while (json < end) {
|
||||
if (*json > WhiteSpace) {
|
||||
break;
|
||||
}
|
||||
if (*json != WhiteSpace &&
|
||||
*json != Tab &&
|
||||
*json != LineFeed &&
|
||||
*json != Return) {
|
||||
break;
|
||||
}
|
||||
++json;
|
||||
}
|
||||
return (json < end);
|
||||
}
|
||||
|
||||
char Parser::nextToken()
|
||||
{
|
||||
if (!eatSpace()) {
|
||||
return 0;
|
||||
}
|
||||
char token = *json++;
|
||||
switch (token) {
|
||||
case BeginArray:
|
||||
case BeginObject:
|
||||
case NameSeparator:
|
||||
case ValueSeparator:
|
||||
case EndArray:
|
||||
case EndObject:
|
||||
eatSpace();
|
||||
case Quote:
|
||||
break;
|
||||
default:
|
||||
token = 0;
|
||||
break;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/*
|
||||
JSON-text = object / array
|
||||
*/
|
||||
QJsonDocument Parser::parse(QJsonParseError *error)
|
||||
{
|
||||
#ifdef PARSER_DEBUG
|
||||
indent = 0;
|
||||
qDebug() << ">>>>> parser begin";
|
||||
#endif
|
||||
// allocate some space
|
||||
dataLength = qMax(end - json, (ptrdiff_t) 256);
|
||||
data = (char *)malloc(dataLength);
|
||||
|
||||
// fill in Header data
|
||||
QJsonPrivate::Header *h = (QJsonPrivate::Header *)data;
|
||||
h->tag = QJsonDocument::BinaryFormatTag;
|
||||
h->version = 1u;
|
||||
|
||||
current = sizeof(QJsonPrivate::Header);
|
||||
|
||||
eatBOM();
|
||||
char token = nextToken();
|
||||
|
||||
DEBUG << hex << (uint)token;
|
||||
if (token == BeginArray) {
|
||||
if (!parseArray()) {
|
||||
goto error;
|
||||
}
|
||||
} else if (token == BeginObject) {
|
||||
if (!parseObject()) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
goto error;
|
||||
}
|
||||
|
||||
END;
|
||||
{
|
||||
if (error) {
|
||||
error->offset = 0;
|
||||
error->error = QJsonParseError::NoError;
|
||||
}
|
||||
return QJsonDocument(new QJsonPrivate::Data(data, current));
|
||||
}
|
||||
|
||||
error:
|
||||
#ifdef PARSER_DEBUG
|
||||
qDebug() << ">>>>> parser error";
|
||||
#endif
|
||||
if (error) {
|
||||
error->offset = json - head;
|
||||
error->error = lastError;
|
||||
}
|
||||
free(data);
|
||||
return QJsonDocument();
|
||||
}
|
||||
|
||||
|
||||
void Parser::ParsedObject::insert(uint offset)
|
||||
{
|
||||
const QJsonPrivate::Entry *newEntry = reinterpret_cast<const QJsonPrivate::Entry *>(parser->data + objectPosition +
|
||||
offset);
|
||||
int min = 0;
|
||||
int n = offsets.size();
|
||||
while (n > 0) {
|
||||
int half = n >> 1;
|
||||
int middle = min + half;
|
||||
if (*entryAt(middle) >= *newEntry) {
|
||||
n = half;
|
||||
} else {
|
||||
min = middle + 1;
|
||||
n -= half + 1;
|
||||
}
|
||||
}
|
||||
if (min < offsets.size() && *entryAt(min) == *newEntry) {
|
||||
offsets[min] = offset;
|
||||
} else {
|
||||
offsets.insert(min, offset);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
object = begin-object [ member *( value-separator member ) ]
|
||||
end-object
|
||||
*/
|
||||
|
||||
bool Parser::parseObject()
|
||||
{
|
||||
if (++nestingLevel > nestingLimit) {
|
||||
lastError = QJsonParseError::DeepNesting;
|
||||
return false;
|
||||
}
|
||||
|
||||
int objectOffset = reserveSpace(sizeof(QJsonPrivate::Object));
|
||||
BEGIN << "parseObject pos=" << objectOffset << current << json;
|
||||
|
||||
ParsedObject parsedObject(this, objectOffset);
|
||||
|
||||
char token = nextToken();
|
||||
while (token == Quote) {
|
||||
int off = current - objectOffset;
|
||||
if (!parseMember(objectOffset)) {
|
||||
return false;
|
||||
}
|
||||
parsedObject.insert(off);
|
||||
token = nextToken();
|
||||
if (token != ValueSeparator) {
|
||||
break;
|
||||
}
|
||||
token = nextToken();
|
||||
if (token == EndObject) {
|
||||
lastError = QJsonParseError::MissingObject;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG << "end token=" << token;
|
||||
if (token != EndObject) {
|
||||
lastError = QJsonParseError::UnterminatedObject;
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG << "numEntries" << parsedObject.offsets.size();
|
||||
int table = objectOffset;
|
||||
// finalize the object
|
||||
if (parsedObject.offsets.size()) {
|
||||
int tableSize = parsedObject.offsets.size() * sizeof(uint);
|
||||
table = reserveSpace(tableSize);
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
memcpy(data + table, parsedObject.offsets.constData(), tableSize);
|
||||
#else
|
||||
offset *o = (offset *)(data + table);
|
||||
for (int i = 0; i < tableSize; ++i) {
|
||||
o[i] = parsedObject.offsets[i];
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
QJsonPrivate::Object *o = (QJsonPrivate::Object *)(data + objectOffset);
|
||||
o->tableOffset = table - objectOffset;
|
||||
o->size = current - objectOffset;
|
||||
o->is_object = true;
|
||||
o->length = parsedObject.offsets.size();
|
||||
|
||||
DEBUG << "current=" << current;
|
||||
END;
|
||||
|
||||
--nestingLevel;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
member = string name-separator value
|
||||
*/
|
||||
bool Parser::parseMember(int baseOffset)
|
||||
{
|
||||
int entryOffset = reserveSpace(sizeof(QJsonPrivate::Entry));
|
||||
BEGIN << "parseMember pos=" << entryOffset;
|
||||
|
||||
bool latin1;
|
||||
if (!parseString(&latin1)) {
|
||||
return false;
|
||||
}
|
||||
char token = nextToken();
|
||||
if (token != NameSeparator) {
|
||||
lastError = QJsonParseError::MissingNameSeparator;
|
||||
return false;
|
||||
}
|
||||
QJsonPrivate::Value val;
|
||||
if (!parseValue(&val, baseOffset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// finalize the entry
|
||||
QJsonPrivate::Entry *e = (QJsonPrivate::Entry *)(data + entryOffset);
|
||||
e->value = val;
|
||||
e->value.latinKey = latin1;
|
||||
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
array = begin-array [ value *( value-separator value ) ] end-array
|
||||
*/
|
||||
bool Parser::parseArray()
|
||||
{
|
||||
BEGIN << "parseArray";
|
||||
|
||||
if (++nestingLevel > nestingLimit) {
|
||||
lastError = QJsonParseError::DeepNesting;
|
||||
return false;
|
||||
}
|
||||
|
||||
int arrayOffset = reserveSpace(sizeof(QJsonPrivate::Array));
|
||||
|
||||
QVarLengthArray<QJsonPrivate::Value, 64> values;
|
||||
|
||||
if (!eatSpace()) {
|
||||
lastError = QJsonParseError::UnterminatedArray;
|
||||
return false;
|
||||
}
|
||||
if (*json == EndArray) {
|
||||
nextToken();
|
||||
} else {
|
||||
while (1) {
|
||||
QJsonPrivate::Value val;
|
||||
if (!parseValue(&val, arrayOffset)) {
|
||||
return false;
|
||||
}
|
||||
values.append(val);
|
||||
char token = nextToken();
|
||||
if (token == EndArray) {
|
||||
break;
|
||||
} else if (token != ValueSeparator) {
|
||||
if (!eatSpace()) {
|
||||
lastError = QJsonParseError::UnterminatedArray;
|
||||
} else {
|
||||
lastError = QJsonParseError::MissingValueSeparator;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG << "size =" << values.size();
|
||||
int table = arrayOffset;
|
||||
// finalize the object
|
||||
if (values.size()) {
|
||||
int tableSize = values.size() * sizeof(QJsonPrivate::Value);
|
||||
table = reserveSpace(tableSize);
|
||||
memcpy(data + table, values.constData(), tableSize);
|
||||
}
|
||||
|
||||
QJsonPrivate::Array *a = (QJsonPrivate::Array *)(data + arrayOffset);
|
||||
a->tableOffset = table - arrayOffset;
|
||||
a->size = current - arrayOffset;
|
||||
a->is_object = false;
|
||||
a->length = values.size();
|
||||
|
||||
DEBUG << "current=" << current;
|
||||
END;
|
||||
|
||||
--nestingLevel;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
value = false / null / true / object / array / number / string
|
||||
|
||||
*/
|
||||
|
||||
bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset)
|
||||
{
|
||||
BEGIN << "parse Value" << json;
|
||||
val->_dummy = 0;
|
||||
|
||||
switch (*json++) {
|
||||
case 'n':
|
||||
if (end - json < 4) {
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
}
|
||||
if (*json++ == 'u' &&
|
||||
*json++ == 'l' &&
|
||||
*json++ == 'l') {
|
||||
val->type = QJsonValue::Null;
|
||||
DEBUG << "value: null";
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
case 't':
|
||||
if (end - json < 4) {
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
}
|
||||
if (*json++ == 'r' &&
|
||||
*json++ == 'u' &&
|
||||
*json++ == 'e') {
|
||||
val->type = QJsonValue::Bool;
|
||||
val->value = true;
|
||||
DEBUG << "value: true";
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
case 'f':
|
||||
if (end - json < 5) {
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
}
|
||||
if (*json++ == 'a' &&
|
||||
*json++ == 'l' &&
|
||||
*json++ == 's' &&
|
||||
*json++ == 'e') {
|
||||
val->type = QJsonValue::Bool;
|
||||
val->value = false;
|
||||
DEBUG << "value: false";
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
lastError = QJsonParseError::IllegalValue;
|
||||
return false;
|
||||
case Quote: {
|
||||
val->type = QJsonValue::String;
|
||||
if (current - baseOffset >= Value::MaxSize) {
|
||||
lastError = QJsonParseError::DocumentTooLarge;
|
||||
return false;
|
||||
}
|
||||
val->value = current - baseOffset;
|
||||
bool latin1;
|
||||
if (!parseString(&latin1)) {
|
||||
return false;
|
||||
}
|
||||
val->latinOrIntValue = latin1;
|
||||
DEBUG << "value: string";
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
case BeginArray:
|
||||
val->type = QJsonValue::Array;
|
||||
if (current - baseOffset >= Value::MaxSize) {
|
||||
lastError = QJsonParseError::DocumentTooLarge;
|
||||
return false;
|
||||
}
|
||||
val->value = current - baseOffset;
|
||||
if (!parseArray()) {
|
||||
return false;
|
||||
}
|
||||
DEBUG << "value: array";
|
||||
END;
|
||||
return true;
|
||||
case BeginObject:
|
||||
val->type = QJsonValue::Object;
|
||||
if (current - baseOffset >= Value::MaxSize) {
|
||||
lastError = QJsonParseError::DocumentTooLarge;
|
||||
return false;
|
||||
}
|
||||
val->value = current - baseOffset;
|
||||
if (!parseObject()) {
|
||||
return false;
|
||||
}
|
||||
DEBUG << "value: object";
|
||||
END;
|
||||
return true;
|
||||
case EndArray:
|
||||
lastError = QJsonParseError::MissingObject;
|
||||
return false;
|
||||
default:
|
||||
--json;
|
||||
if (!parseNumber(val, baseOffset)) {
|
||||
return false;
|
||||
}
|
||||
DEBUG << "value: number";
|
||||
END;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
number = [ minus ] int [ frac ] [ exp ]
|
||||
decimal-point = %x2E ; .
|
||||
digit1-9 = %x31-39 ; 1-9
|
||||
e = %x65 / %x45 ; e E
|
||||
exp = e [ minus / plus ] 1*DIGIT
|
||||
frac = decimal-point 1*DIGIT
|
||||
int = zero / ( digit1-9 *DIGIT )
|
||||
minus = %x2D ; -
|
||||
plus = %x2B ; +
|
||||
zero = %x30 ; 0
|
||||
|
||||
*/
|
||||
|
||||
bool Parser::parseNumber(QJsonPrivate::Value *val, int baseOffset)
|
||||
{
|
||||
BEGIN << "parseNumber" << json;
|
||||
val->type = QJsonValue::Double;
|
||||
|
||||
const char *start = json;
|
||||
bool isInt = true;
|
||||
|
||||
// minus
|
||||
if (json < end && *json == '-') {
|
||||
++json;
|
||||
}
|
||||
|
||||
// int = zero / ( digit1-9 *DIGIT )
|
||||
if (json < end && *json == '0') {
|
||||
++json;
|
||||
} else {
|
||||
while (json < end && *json >= '0' && *json <= '9') {
|
||||
++json;
|
||||
}
|
||||
}
|
||||
|
||||
// frac = decimal-point 1*DIGIT
|
||||
if (json < end && *json == '.') {
|
||||
isInt = false;
|
||||
++json;
|
||||
while (json < end && *json >= '0' && *json <= '9') {
|
||||
++json;
|
||||
}
|
||||
}
|
||||
|
||||
// exp = e [ minus / plus ] 1*DIGIT
|
||||
if (json < end && (*json == 'e' || *json == 'E')) {
|
||||
isInt = false;
|
||||
++json;
|
||||
if (json < end && (*json == '-' || *json == '+')) {
|
||||
++json;
|
||||
}
|
||||
while (json < end && *json >= '0' && *json <= '9') {
|
||||
++json;
|
||||
}
|
||||
}
|
||||
|
||||
if (json >= end) {
|
||||
lastError = QJsonParseError::TerminationByNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray number(start, json - start);
|
||||
DEBUG << "numberstring" << number;
|
||||
|
||||
if (isInt) {
|
||||
bool ok;
|
||||
int n = number.toInt(&ok);
|
||||
if (ok && n < (1 << 25) && n > -(1 << 25)) {
|
||||
val->int_value = n;
|
||||
val->latinOrIntValue = true;
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ok;
|
||||
union {
|
||||
quint64 ui;
|
||||
double d;
|
||||
};
|
||||
d = number.toDouble(&ok);
|
||||
|
||||
if (!ok) {
|
||||
lastError = QJsonParseError::IllegalNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
int pos = reserveSpace(sizeof(double));
|
||||
*(quint64 *)(data + pos) = qToLittleEndian(ui);
|
||||
if (current - baseOffset >= Value::MaxSize) {
|
||||
lastError = QJsonParseError::DocumentTooLarge;
|
||||
return false;
|
||||
}
|
||||
val->value = pos - baseOffset;
|
||||
val->latinOrIntValue = false;
|
||||
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
string = quotation-mark *char quotation-mark
|
||||
|
||||
char = unescaped /
|
||||
escape (
|
||||
%x22 / ; " quotation mark U+0022
|
||||
%x5C / ; \ reverse solidus U+005C
|
||||
%x2F / ; / solidus U+002F
|
||||
%x62 / ; b backspace U+0008
|
||||
%x66 / ; f form feed U+000C
|
||||
%x6E / ; n line feed U+000A
|
||||
%x72 / ; r carriage return U+000D
|
||||
%x74 / ; t tab U+0009
|
||||
%x75 4HEXDIG ) ; uXXXX U+XXXX
|
||||
|
||||
escape = %x5C ; \
|
||||
|
||||
quotation-mark = %x22 ; "
|
||||
|
||||
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
||||
*/
|
||||
static inline bool addHexDigit(char digit, uint *result)
|
||||
{
|
||||
*result <<= 4;
|
||||
if (digit >= '0' && digit <= '9') {
|
||||
*result |= (digit - '0');
|
||||
} else if (digit >= 'a' && digit <= 'f') {
|
||||
*result |= (digit - 'a') + 10;
|
||||
} else if (digit >= 'A' && digit <= 'F') {
|
||||
*result |= (digit - 'A') + 10;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool scanEscapeSequence(const char *&json, const char *end, uint *ch)
|
||||
{
|
||||
++json;
|
||||
if (json >= end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG << "scan escape" << (char)*json;
|
||||
uint escaped = *json++;
|
||||
switch (escaped) {
|
||||
case '"':
|
||||
*ch = '"';
|
||||
break;
|
||||
case '\\':
|
||||
*ch = '\\';
|
||||
break;
|
||||
case '/':
|
||||
*ch = '/';
|
||||
break;
|
||||
case 'b':
|
||||
*ch = 0x8;
|
||||
break;
|
||||
case 'f':
|
||||
*ch = 0xc;
|
||||
break;
|
||||
case 'n':
|
||||
*ch = 0xa;
|
||||
break;
|
||||
case 'r':
|
||||
*ch = 0xd;
|
||||
break;
|
||||
case 't':
|
||||
*ch = 0x9;
|
||||
break;
|
||||
case 'u': {
|
||||
*ch = 0;
|
||||
if (json > end - 4) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (!addHexDigit(*json, ch)) {
|
||||
return false;
|
||||
}
|
||||
++json;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
// this is not as strict as one could be, but allows for more Json files
|
||||
// to be parsed correctly.
|
||||
*ch = escaped;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool scanUtf8Char(const char *&json, const char *end, uint *result)
|
||||
{
|
||||
int need;
|
||||
uint min_uc;
|
||||
uint uc;
|
||||
uchar ch = *json++;
|
||||
if (ch < 128) {
|
||||
*result = ch;
|
||||
return true;
|
||||
} else if ((ch & 0xe0) == 0xc0) {
|
||||
uc = ch & 0x1f;
|
||||
need = 1;
|
||||
min_uc = 0x80;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
uc = ch & 0x0f;
|
||||
need = 2;
|
||||
min_uc = 0x800;
|
||||
} else if ((ch & 0xf8) == 0xf0) {
|
||||
uc = ch & 0x07;
|
||||
need = 3;
|
||||
min_uc = 0x10000;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (json >= end - need) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < need; ++i) {
|
||||
ch = *json++;
|
||||
if ((ch & 0xc0) != 0x80) {
|
||||
return false;
|
||||
}
|
||||
uc = (uc << 6) | (ch & 0x3f);
|
||||
}
|
||||
|
||||
/* Qt 5 Beta 1
|
||||
if (uc < min_uc || QChar::isNonCharacter(uc) ||
|
||||
QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) {
|
||||
*/
|
||||
// Temporary for missing QChar methods. Does not check for non-characters
|
||||
// or past last valid code point.
|
||||
if (uc < min_uc ||
|
||||
QChar::isHighSurrogate(uc) || QChar::isLowSurrogate(uc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = uc;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::parseString(bool *latin1)
|
||||
{
|
||||
*latin1 = true;
|
||||
|
||||
const char *start = json;
|
||||
int outStart = current;
|
||||
|
||||
// try to write out a latin1 string
|
||||
|
||||
int stringPos = reserveSpace(2);
|
||||
BEGIN << "parse string stringPos=" << stringPos << json;
|
||||
while (json < end) {
|
||||
uint ch = 0;
|
||||
if (*json == '"') {
|
||||
break;
|
||||
} else if (*json == '\\') {
|
||||
if (!scanEscapeSequence(json, end, &ch)) {
|
||||
lastError = QJsonParseError::IllegalEscapeSequence;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!scanUtf8Char(json, end, &ch)) {
|
||||
lastError = QJsonParseError::IllegalUTF8String;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ch > 0xff) {
|
||||
*latin1 = false;
|
||||
break;
|
||||
}
|
||||
int pos = reserveSpace(1);
|
||||
DEBUG << " " << ch << (char)ch;
|
||||
data[pos] = (uchar)ch;
|
||||
}
|
||||
++json;
|
||||
DEBUG << "end of string";
|
||||
if (json >= end) {
|
||||
lastError = QJsonParseError::UnterminatedString;
|
||||
return false;
|
||||
}
|
||||
|
||||
// no unicode string, we are done
|
||||
if (*latin1) {
|
||||
// write string length
|
||||
*(QJsonPrivate::qle_ushort *)(data + stringPos) = ushort(current - outStart - sizeof(ushort));
|
||||
int pos = reserveSpace((4 - current) & 3);
|
||||
while (pos & 3) {
|
||||
data[pos++] = 0;
|
||||
}
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
|
||||
*latin1 = false;
|
||||
DEBUG << "not latin";
|
||||
|
||||
json = start;
|
||||
current = outStart + sizeof(int);
|
||||
|
||||
while (json < end) {
|
||||
uint ch = 0;
|
||||
if (*json == '"') {
|
||||
break;
|
||||
} else if (*json == '\\') {
|
||||
if (!scanEscapeSequence(json, end, &ch)) {
|
||||
lastError = QJsonParseError::IllegalEscapeSequence;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!scanUtf8Char(json, end, &ch)) {
|
||||
lastError = QJsonParseError::IllegalUTF8String;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (QChar::requiresSurrogates(ch)) {
|
||||
int pos = reserveSpace(4);
|
||||
*(QJsonPrivate::qle_ushort *)(data + pos) = QChar::highSurrogate(ch);
|
||||
*(QJsonPrivate::qle_ushort *)(data + pos + 2) = QChar::lowSurrogate(ch);
|
||||
} else {
|
||||
int pos = reserveSpace(2);
|
||||
*(QJsonPrivate::qle_ushort *)(data + pos) = (ushort)ch;
|
||||
}
|
||||
}
|
||||
++json;
|
||||
|
||||
if (json >= end) {
|
||||
lastError = QJsonParseError::UnterminatedString;
|
||||
return false;
|
||||
}
|
||||
|
||||
// write string length
|
||||
*(QJsonPrivate::qle_int *)(data + stringPos) = (current - outStart - sizeof(int)) / 2;
|
||||
int pos = reserveSpace((4 - current) & 3);
|
||||
while (pos & 3) {
|
||||
data[pos++] = 0;
|
||||
}
|
||||
END;
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -1,94 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONPARSER_P_H
|
||||
#define QJSONPARSER_P_H
|
||||
|
||||
#include "qjsondocument.h"
|
||||
#include "qvarlengtharray.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QJsonPrivate {
|
||||
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
Parser(const char *json, int length);
|
||||
|
||||
QJsonDocument parse(QJsonParseError *error);
|
||||
|
||||
class ParsedObject
|
||||
{
|
||||
public:
|
||||
ParsedObject(Parser *p, int pos) : parser(p), objectPosition(pos) {}
|
||||
void insert(uint offset);
|
||||
|
||||
Parser *parser;
|
||||
int objectPosition;
|
||||
QVarLengthArray<uint, 64> offsets;
|
||||
|
||||
inline QJsonPrivate::Entry *entryAt(int i) const {
|
||||
return reinterpret_cast<QJsonPrivate::Entry *>(parser->data + objectPosition + offsets[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
inline void eatBOM();
|
||||
inline bool eatSpace();
|
||||
inline char nextToken();
|
||||
|
||||
bool parseObject();
|
||||
bool parseArray();
|
||||
bool parseMember(int baseOffset);
|
||||
bool parseString(bool *latin1);
|
||||
bool parseValue(QJsonPrivate::Value *val, int baseOffset);
|
||||
bool parseNumber(QJsonPrivate::Value *val, int baseOffset);
|
||||
const char *head;
|
||||
const char *json;
|
||||
const char *end;
|
||||
|
||||
char *data;
|
||||
int dataLength;
|
||||
int current;
|
||||
int nestingLevel;
|
||||
QJsonParseError::ParseError lastError;
|
||||
|
||||
inline int reserveSpace(int space) {
|
||||
if (current + space >= dataLength) {
|
||||
dataLength = 2 * dataLength + space;
|
||||
data = (char *)realloc(data, dataLength);
|
||||
}
|
||||
int pos = current;
|
||||
current += space;
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -1,693 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qjsonobject.h"
|
||||
#include "qjsonvalue.h"
|
||||
#include "qjsonarray.h"
|
||||
#include "qvariant.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qdebug.h"
|
||||
#include "qjson_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QJsonValue
|
||||
\inmodule QtCore
|
||||
\ingroup json
|
||||
\reentrant
|
||||
\since 4.9
|
||||
|
||||
\brief The QJsonValue class encapsulates a value in JSON.
|
||||
|
||||
A value in JSON can be one of 6 basic types:
|
||||
|
||||
JSON is a format to store structured data. It has 6 basic data types:
|
||||
|
||||
\list
|
||||
\li bool QJsonValue::Bool
|
||||
\li double QJsonValue::Double
|
||||
\li string QJsonValue::String
|
||||
\li array QJsonValue::Array
|
||||
\li object QJsonValue::Object
|
||||
\li null QJsonValue::Null
|
||||
\endlist
|
||||
|
||||
A value can represent any of the above data types. In addition, QJsonValue has one special
|
||||
flag to represent undefined values. This can be queried with isUndefined().
|
||||
|
||||
The type of the value can be queried with type() or accessors like isBool(), isString(), and so on.
|
||||
Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on.
|
||||
|
||||
Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type
|
||||
conversions. This implies that converting to a type that is not stored in the value will return a default
|
||||
constructed return value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates a QJsonValue of type \a type.
|
||||
|
||||
The default is to create a Null value.
|
||||
*/
|
||||
QJsonValue::QJsonValue(Type type)
|
||||
: b(false), dbl(0), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(type)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QJsonValue::QJsonValue(QJsonPrivate::Data *data, QJsonPrivate::Base *privbase, const QJsonPrivate::Value &v)
|
||||
: b(false), dbl(0), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(static_cast<Type>(uint(v.type)))
|
||||
{
|
||||
switch (t) {
|
||||
case Undefined:
|
||||
case Null:
|
||||
break;
|
||||
case Bool:
|
||||
b = v.toBoolean();
|
||||
break;
|
||||
case Double:
|
||||
dbl = v.toDouble(privbase);
|
||||
break;
|
||||
case String: {
|
||||
stringData = new QString(v.toString(privbase));
|
||||
break;
|
||||
}
|
||||
case Array:
|
||||
case Object:
|
||||
d = data;
|
||||
base = v.base(privbase);
|
||||
break;
|
||||
}
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type Bool, with value \a a.
|
||||
*/
|
||||
QJsonValue::QJsonValue(bool a)
|
||||
: b(a), dbl(0), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(Bool)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type Double, with value \a n.
|
||||
*/
|
||||
QJsonValue::QJsonValue(double n)
|
||||
: b(false), dbl(n), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(Double)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Creates a value of type Double, with value \a n.
|
||||
*/
|
||||
QJsonValue::QJsonValue(int n)
|
||||
: b(false), dbl(n), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(Double)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Creates a value of type Double, with value \a n.
|
||||
NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992).
|
||||
If you pass in values outside this range expect a loss of precision to occur.
|
||||
*/
|
||||
QJsonValue::QJsonValue(qint64 n)
|
||||
: b(false), dbl(n), stringData(Q_NULLPTR), base(Q_NULLPTR), d(Q_NULLPTR), t(Double)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type String, with value \a s.
|
||||
*/
|
||||
QJsonValue::QJsonValue(const QString &s)
|
||||
: b(false), dbl(0), stringData(new QString(s)), base(Q_NULLPTR), d(Q_NULLPTR), t(String)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type String, with value \a s.
|
||||
*/
|
||||
QJsonValue::QJsonValue(QLatin1String s)
|
||||
: b(false), dbl(0), stringData(new QString(s)), base(Q_NULLPTR), d(Q_NULLPTR), t(String)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type Array, with value \a a.
|
||||
*/
|
||||
QJsonValue::QJsonValue(const QJsonArray &a)
|
||||
: b(false), dbl(0), stringData(Q_NULLPTR), base(a.a), d(a.d), t(Array)
|
||||
{
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a value of type Object, with value \a o.
|
||||
*/
|
||||
QJsonValue::QJsonValue(const QJsonObject &o)
|
||||
: b(false), dbl(0), stringData(Q_NULLPTR), base(o.o), d(o.d), t(Object)
|
||||
{
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Destroys the value.
|
||||
*/
|
||||
QJsonValue::~QJsonValue()
|
||||
{
|
||||
if (t == String) {
|
||||
delete stringData;
|
||||
}
|
||||
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a copy of \a other.
|
||||
*/
|
||||
QJsonValue::QJsonValue(const QJsonValue &other)
|
||||
: b(other.b), dbl(other.dbl), stringData(Q_NULLPTR), base(Q_NULLPTR), d(other.d), t(other.t)
|
||||
{
|
||||
if (d) {
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
if (t == String && other.stringData) {
|
||||
stringData = new QString(*other.stringData);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns the value stored in \a other to this object.
|
||||
*/
|
||||
QJsonValue &QJsonValue::operator =(const QJsonValue &other)
|
||||
{
|
||||
if (t == String) {
|
||||
delete stringData;
|
||||
stringData = Q_NULLPTR;
|
||||
}
|
||||
|
||||
t = other.t;
|
||||
b = other.b;
|
||||
dbl = other.dbl;
|
||||
|
||||
qAtomicAssign(d, other.d);
|
||||
|
||||
if (t == String && other.stringData) {
|
||||
stringData = new QString(*other.stringData);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isNull() const
|
||||
|
||||
Returns true if the value is null.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isBool() const
|
||||
|
||||
Returns true if the value contains a boolean.
|
||||
|
||||
\sa toBool()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isDouble() const
|
||||
|
||||
Returns true if the value contains a double.
|
||||
|
||||
\sa toDouble()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isString() const
|
||||
|
||||
Returns true if the value contains a string.
|
||||
|
||||
\sa toString()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isArray() const
|
||||
|
||||
Returns true if the value contains an array.
|
||||
|
||||
\sa toArray()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isObject() const
|
||||
|
||||
Returns true if the value contains an object.
|
||||
|
||||
\sa toObject()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QJsonValue::isUndefined() const
|
||||
|
||||
Returns true if the value is undefined. This can happen in certain
|
||||
error cases as e.g. accessing a non existing key in a QJsonObject.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Converts \a variant to a QJsonValue and returns it.
|
||||
|
||||
The conversion will convert QVariant types as follows:
|
||||
|
||||
\list
|
||||
\li QVariant::Bool to Bool
|
||||
\li QVariant::Int
|
||||
\li QVariant::Double
|
||||
\li QVariant::LongLong
|
||||
\li QVariant::ULongLong
|
||||
\li QVariant::UInt to Double
|
||||
\li QVariant::String to String
|
||||
\li QVariant::StringList
|
||||
\li QVariant::VariantList to Array
|
||||
\li QVariant::VariantMap to Object
|
||||
\endlist
|
||||
|
||||
For all other QVariant types a conversion to a QString will be attempted. If the returned string
|
||||
is empty, a Null QJsonValue will be stored, otherwise a String value using the returned QString.
|
||||
|
||||
\sa toVariant()
|
||||
*/
|
||||
QJsonValue QJsonValue::fromVariant(const QVariant &variant)
|
||||
{
|
||||
switch (variant.type()) {
|
||||
case QVariant::Bool:
|
||||
return QJsonValue(variant.toBool());
|
||||
case QVariant::Int:
|
||||
case QVariant::Double:
|
||||
case QVariant::LongLong:
|
||||
case QVariant::ULongLong:
|
||||
case QVariant::UInt:
|
||||
return QJsonValue(variant.toDouble());
|
||||
case QVariant::String:
|
||||
return QJsonValue(variant.toString());
|
||||
case QVariant::StringList:
|
||||
return QJsonValue(QJsonArray::fromStringList(variant.toStringList()));
|
||||
case QVariant::List:
|
||||
return QJsonValue(QJsonArray::fromVariantList(variant.toList()));
|
||||
case QVariant::Map:
|
||||
return QJsonValue(QJsonObject::fromVariantMap(variant.toMap()));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QByteArray a;
|
||||
{
|
||||
QDataStream s(&a, QIODevice::WriteOnly);
|
||||
s << variant;
|
||||
}
|
||||
if (a.isEmpty()) {
|
||||
return QJsonValue();
|
||||
}
|
||||
|
||||
QString result = QLatin1String("@(");
|
||||
result += QString::fromLatin1(a.constData(), a.size());
|
||||
result += QLatin1String(")@");
|
||||
return QJsonValue(result);
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to a QVariant.
|
||||
|
||||
The QJsonValue types will be converted as follows:
|
||||
|
||||
\value Null QVariant()
|
||||
\value Bool QVariant::Bool
|
||||
\value Double QVariant::Double
|
||||
\value String QVariant::String
|
||||
\value Array QVariantList
|
||||
\value Object QVariantMap
|
||||
\value Undefined QVariant()
|
||||
|
||||
\sa fromVariant()
|
||||
*/
|
||||
QVariant QJsonValue::toVariant() const
|
||||
{
|
||||
switch (t) {
|
||||
case Bool:
|
||||
return b;
|
||||
case Double:
|
||||
return dbl;
|
||||
case String: {
|
||||
QVariant variant = toString();
|
||||
QString string = variant.toString();
|
||||
if (string.startsWith(QLatin1String("@(")) && string.endsWith(")@")) {
|
||||
QByteArray a(string.toLatin1());
|
||||
a.remove(0, 2);
|
||||
a.chop(2);
|
||||
QDataStream stream(&a, QIODevice::ReadOnly);
|
||||
QVariant result;
|
||||
stream >> result;
|
||||
return result;
|
||||
}
|
||||
return variant;
|
||||
}
|
||||
case Array:
|
||||
return d ?
|
||||
QJsonArray(d, static_cast<QJsonPrivate::Array *>(base)).toVariantList() :
|
||||
QVariantList();
|
||||
case Object:
|
||||
return d ?
|
||||
QJsonObject(d, static_cast<QJsonPrivate::Object *>(base)).toVariantMap() :
|
||||
QVariantMap();
|
||||
case Null:
|
||||
case Undefined:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
\enum QJsonValue::Type
|
||||
|
||||
This enum describes the type of the JSON value.
|
||||
|
||||
\value Null A Null value
|
||||
\value Bool A boolean value. Use toBool() to convert to a bool.
|
||||
\value Double A double. Use toDouble() to convert to a double.
|
||||
\value String A string. Use toString() to convert to a QString.
|
||||
\value Array An array. Use toArray() to convert to a QJsonArray.
|
||||
\value Object An object. Use toObject() to convert to a QJsonObject.
|
||||
\value Undefined The value is undefined. This is usually returned as an
|
||||
error condition, when trying to read an out of bounds value
|
||||
in an array or a non existent key in an object.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the type of the value.
|
||||
|
||||
\sa QJsonValue::Type
|
||||
*/
|
||||
QJsonValue::Type QJsonValue::type() const
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to a bool and returns it.
|
||||
|
||||
If type() is not bool, the \a defaultValue will be returned.
|
||||
*/
|
||||
bool QJsonValue::toBool(bool defaultValue) const
|
||||
{
|
||||
if (t != Bool) {
|
||||
return defaultValue;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to an int and returns it.
|
||||
|
||||
If type() is not Double or the value is not a whole number,
|
||||
the \a defaultValue will be returned.
|
||||
*/
|
||||
int QJsonValue::toInt(int defaultValue) const
|
||||
{
|
||||
if (t == Double && int(dbl) == dbl) {
|
||||
return dbl;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to a double and returns it.
|
||||
|
||||
If type() is not Double, the \a defaultValue will be returned.
|
||||
*/
|
||||
double QJsonValue::toDouble(double defaultValue) const
|
||||
{
|
||||
if (t != Double) {
|
||||
return defaultValue;
|
||||
}
|
||||
return dbl;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to a QString and returns it.
|
||||
|
||||
If type() is not String, the \a defaultValue will be returned.
|
||||
*/
|
||||
QString QJsonValue::toString(const QString &defaultValue) const
|
||||
{
|
||||
if (t != String) {
|
||||
return defaultValue;
|
||||
}
|
||||
return *stringData;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to an array and returns it.
|
||||
|
||||
If type() is not Array, the \a defaultValue will be returned.
|
||||
*/
|
||||
QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
|
||||
{
|
||||
if (!d || t != Array) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Converts the value to an array and returns it.
|
||||
|
||||
If type() is not Array, a QJsonArray() will be returned.
|
||||
*/
|
||||
QJsonArray QJsonValue::toArray() const
|
||||
{
|
||||
return toArray(QJsonArray());
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the value to an object and returns it.
|
||||
|
||||
If type() is not Object, the \a defaultValue will be returned.
|
||||
*/
|
||||
QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
|
||||
{
|
||||
if (!d || t != Object) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base));
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Converts the value to an object and returns it.
|
||||
|
||||
If type() is not Object, the QJsonObject() will be returned.
|
||||
*/
|
||||
QJsonObject QJsonValue::toObject() const
|
||||
{
|
||||
return toObject(QJsonObject());
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the value is equal to \a other.
|
||||
*/
|
||||
bool QJsonValue::operator==(const QJsonValue &other) const
|
||||
{
|
||||
if (t != other.t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
case Undefined:
|
||||
case Null:
|
||||
break;
|
||||
case Bool:
|
||||
return b == other.b;
|
||||
case Double:
|
||||
return dbl == other.dbl;
|
||||
case String:
|
||||
return toString() == other.toString();
|
||||
case Array:
|
||||
if (base == other.base) {
|
||||
return true;
|
||||
}
|
||||
if (!base || !other.base) {
|
||||
return false;
|
||||
}
|
||||
return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base))
|
||||
== QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.base));
|
||||
case Object:
|
||||
if (base == other.base) {
|
||||
return true;
|
||||
}
|
||||
if (!base || !other.base) {
|
||||
return false;
|
||||
}
|
||||
return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base))
|
||||
== QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.base));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the value is not equal to \a other.
|
||||
*/
|
||||
bool QJsonValue::operator!=(const QJsonValue &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QJsonValue::detach()
|
||||
{
|
||||
if (!d) {
|
||||
return;
|
||||
}
|
||||
|
||||
qAtomicAssign(d, d->clone(base));
|
||||
base = static_cast<QJsonPrivate::Object *>(d->header->root());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\class QJsonValueRef
|
||||
\inmodule QtCore
|
||||
\reentrant
|
||||
\brief The QJsonValueRef class is a helper class for QJsonValue.
|
||||
|
||||
\internal
|
||||
|
||||
\ingroup json
|
||||
|
||||
When you get an object of type QJsonValueRef, if you can assign to it,
|
||||
the assignment will apply to the character in the string from
|
||||
which you got the reference. That is its whole purpose in life.
|
||||
|
||||
You can use it exactly in the same way as a reference to a QJsonValue.
|
||||
|
||||
The QJsonValueRef becomes invalid once modifications are made to the
|
||||
string: if you want to keep the character, copy it into a QJsonValue.
|
||||
|
||||
Most of the QJsonValue member functions also exist in QJsonValueRef.
|
||||
However, they are not explicitly documented here.
|
||||
*/
|
||||
|
||||
|
||||
QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
|
||||
{
|
||||
if (is_object) {
|
||||
o->setValueAt(index, val);
|
||||
} else {
|
||||
a->replace(index, val);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
|
||||
{
|
||||
if (is_object) {
|
||||
o->setValueAt(index, ref);
|
||||
} else {
|
||||
a->replace(index, ref);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QJsonArray QJsonValueRef::toArray() const
|
||||
{
|
||||
return toValue().toArray();
|
||||
}
|
||||
|
||||
QJsonObject QJsonValueRef::toObject() const
|
||||
{
|
||||
return toValue().toObject();
|
||||
}
|
||||
|
||||
QJsonValue QJsonValueRef::toValue() const
|
||||
{
|
||||
if (!is_object) {
|
||||
return a->at(index);
|
||||
}
|
||||
return o->valueAt(index);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const QJsonValue &o)
|
||||
{
|
||||
switch (o.t) {
|
||||
case QJsonValue::Undefined:
|
||||
dbg.nospace() << "QJsonValue(undefined)";
|
||||
break;
|
||||
case QJsonValue::Null:
|
||||
dbg.nospace() << "QJsonValue(null)";
|
||||
break;
|
||||
case QJsonValue::Bool:
|
||||
dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ")";
|
||||
break;
|
||||
case QJsonValue::Double:
|
||||
dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ")";
|
||||
break;
|
||||
case QJsonValue::String:
|
||||
dbg.nospace() << "QJsonValue(string, " << o.toString() << ")";
|
||||
break;
|
||||
case QJsonValue::Array:
|
||||
dbg.nospace() << "QJsonValue(array, ";
|
||||
dbg.nospace() << o.toArray();
|
||||
dbg.nospace() << ")";
|
||||
break;
|
||||
case QJsonValue::Object:
|
||||
dbg.nospace() << "QJsonValue(object, ";
|
||||
dbg.nospace() << o.toObject();
|
||||
dbg.nospace() << ")";
|
||||
break;
|
||||
}
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -1,235 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONVALUE_H
|
||||
#define QJSONVALUE_H
|
||||
|
||||
#include <QtCore/qobjectdefs.h>
|
||||
#include <QtCore/qstring.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QDebug;
|
||||
class QVariant;
|
||||
class QJsonArray;
|
||||
class QJsonObject;
|
||||
|
||||
namespace QJsonPrivate {
|
||||
class Data;
|
||||
class Base;
|
||||
class Object;
|
||||
class Header;
|
||||
class Array;
|
||||
class Value;
|
||||
class Entry;
|
||||
}
|
||||
|
||||
class Q_CORE_EXPORT QJsonValue
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
Null = 0x0,
|
||||
Bool = 0x1,
|
||||
Double = 0x2,
|
||||
String = 0x3,
|
||||
Array = 0x4,
|
||||
Object = 0x5,
|
||||
Undefined = 0x80
|
||||
};
|
||||
|
||||
QJsonValue(Type = Null);
|
||||
QJsonValue(bool b);
|
||||
QJsonValue(double n);
|
||||
QJsonValue(int n);
|
||||
QJsonValue(qint64 n);
|
||||
QJsonValue(const QString &s);
|
||||
QJsonValue(QLatin1String s);
|
||||
QJsonValue(const QJsonArray &a);
|
||||
QJsonValue(const QJsonObject &o);
|
||||
|
||||
~QJsonValue();
|
||||
|
||||
QJsonValue(const QJsonValue &other);
|
||||
QJsonValue &operator =(const QJsonValue &other);
|
||||
|
||||
static QJsonValue fromVariant(const QVariant &variant);
|
||||
QVariant toVariant() const;
|
||||
|
||||
Type type() const;
|
||||
inline bool isNull() const {
|
||||
return type() == Null;
|
||||
}
|
||||
inline bool isBool() const {
|
||||
return type() == Bool;
|
||||
}
|
||||
inline bool isDouble() const {
|
||||
return type() == Double;
|
||||
}
|
||||
inline bool isString() const {
|
||||
return type() == String;
|
||||
}
|
||||
inline bool isArray() const {
|
||||
return type() == Array;
|
||||
}
|
||||
inline bool isObject() const {
|
||||
return type() == Object;
|
||||
}
|
||||
inline bool isUndefined() const {
|
||||
return type() == Undefined;
|
||||
}
|
||||
|
||||
bool toBool(bool defaultValue = false) const;
|
||||
int toInt(int defaultValue = 0) const;
|
||||
double toDouble(double defaultValue = 0) const;
|
||||
QString toString(const QString &defaultValue = QString()) const;
|
||||
QJsonArray toArray() const;
|
||||
QJsonArray toArray(const QJsonArray &defaultValue) const;
|
||||
QJsonObject toObject() const;
|
||||
QJsonObject toObject(const QJsonObject &defaultValue) const;
|
||||
|
||||
bool operator==(const QJsonValue &other) const;
|
||||
bool operator!=(const QJsonValue &other) const;
|
||||
|
||||
private:
|
||||
// avoid implicit conversions from char * to bool
|
||||
inline QJsonValue(const void *) {}
|
||||
friend class QJsonPrivate::Value;
|
||||
friend class QJsonArray;
|
||||
friend class QJsonObject;
|
||||
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
|
||||
|
||||
QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value &v);
|
||||
|
||||
void detach();
|
||||
|
||||
bool b;
|
||||
double dbl;
|
||||
QString *stringData;
|
||||
QJsonPrivate::Base *base;
|
||||
QJsonPrivate::Data *d; // needed for Objects and Arrays
|
||||
Type t;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QJsonValueRef
|
||||
{
|
||||
public:
|
||||
QJsonValueRef(QJsonArray *array, int idx)
|
||||
: a(array), is_object(false), index(idx) {}
|
||||
QJsonValueRef(QJsonObject *object, int idx)
|
||||
: o(object), is_object(true), index(idx) {}
|
||||
|
||||
inline operator QJsonValue() const {
|
||||
return toValue();
|
||||
}
|
||||
QJsonValueRef &operator = (const QJsonValue &val);
|
||||
QJsonValueRef &operator = (const QJsonValueRef &val);
|
||||
|
||||
inline QJsonValue::Type type() const {
|
||||
return toValue().type();
|
||||
}
|
||||
inline bool isNull() const {
|
||||
return type() == QJsonValue::Null;
|
||||
}
|
||||
inline bool isBool() const {
|
||||
return type() == QJsonValue::Bool;
|
||||
}
|
||||
inline bool isDouble() const {
|
||||
return type() == QJsonValue::Double;
|
||||
}
|
||||
inline bool isString() const {
|
||||
return type() == QJsonValue::String;
|
||||
}
|
||||
inline bool isArray() const {
|
||||
return type() == QJsonValue::Array;
|
||||
}
|
||||
inline bool isObject() const {
|
||||
return type() == QJsonValue::Object;
|
||||
}
|
||||
inline bool isUndefined() const {
|
||||
return type() == QJsonValue::Undefined;
|
||||
}
|
||||
|
||||
inline bool toBool() const {
|
||||
return toValue().toBool();
|
||||
}
|
||||
inline int toInt() const {
|
||||
return toValue().toInt();
|
||||
}
|
||||
inline double toDouble() const {
|
||||
return toValue().toDouble();
|
||||
}
|
||||
inline QString toString() const {
|
||||
return toValue().toString();
|
||||
}
|
||||
QJsonArray toArray() const;
|
||||
QJsonObject toObject() const;
|
||||
|
||||
inline bool operator==(const QJsonValue &other) const {
|
||||
return toValue() == other;
|
||||
}
|
||||
inline bool operator!=(const QJsonValue &other) const {
|
||||
return toValue() != other;
|
||||
}
|
||||
|
||||
private:
|
||||
QJsonValue toValue() const;
|
||||
|
||||
union {
|
||||
QJsonArray *a;
|
||||
QJsonObject *o;
|
||||
};
|
||||
bool is_object;
|
||||
int index;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QJsonValueRefPtr {
|
||||
public:
|
||||
template<typename T1, typename T2>
|
||||
QJsonValueRefPtr(T1 a, T2 b)
|
||||
: m_ref(a, b) { }
|
||||
|
||||
QJsonValueRef* operator->() const { return &m_ref; };
|
||||
|
||||
private:
|
||||
mutable QJsonValueRef m_ref;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QJsonValuePtr {
|
||||
public:
|
||||
|
||||
QJsonValuePtr(QJsonValue val)
|
||||
: m_value(val) { }
|
||||
|
||||
const QJsonValue * operator->() const { return &m_value; };
|
||||
|
||||
private:
|
||||
const QJsonValue m_value;
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSONVALUE_H
|
|
@ -1,255 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qjsonwriter_p.h"
|
||||
#include "qjson_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace QJsonPrivate;
|
||||
|
||||
static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact);
|
||||
static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact);
|
||||
|
||||
static inline uchar hexdig(uint u)
|
||||
{
|
||||
return (u < 0xa ? '0' + u : 'a' + u - 0xa);
|
||||
}
|
||||
|
||||
static QByteArray escapedString(const QString &s)
|
||||
{
|
||||
const uchar replacement = '?';
|
||||
QByteArray ba(s.length(), Qt::Uninitialized);
|
||||
|
||||
uchar *cursor = (uchar *)ba.data();
|
||||
const uchar *ba_end = cursor + ba.length();
|
||||
|
||||
const QChar *ch = (const QChar *)s.constData();
|
||||
const QChar *end = ch + s.length();
|
||||
|
||||
int surrogate_high = -1;
|
||||
|
||||
while (ch < end) {
|
||||
if (cursor >= ba_end - 6) {
|
||||
// ensure we have enough space
|
||||
int pos = cursor - (const uchar *)ba.constData();
|
||||
ba.resize(ba.size() * 2);
|
||||
cursor = (uchar *)ba.data() + pos;
|
||||
ba_end = (const uchar *)ba.constData() + ba.length();
|
||||
}
|
||||
|
||||
uint u = ch->unicode();
|
||||
if (surrogate_high >= 0) {
|
||||
if (ch->isLowSurrogate()) {
|
||||
u = QChar::surrogateToUcs4(surrogate_high, u);
|
||||
surrogate_high = -1;
|
||||
} else {
|
||||
// high surrogate without low
|
||||
*cursor = replacement;
|
||||
++ch;
|
||||
surrogate_high = -1;
|
||||
continue;
|
||||
}
|
||||
} else if (ch->isLowSurrogate()) {
|
||||
// low surrogate without high
|
||||
*cursor = replacement;
|
||||
++ch;
|
||||
continue;
|
||||
} else if (ch->isHighSurrogate()) {
|
||||
surrogate_high = u;
|
||||
++ch;
|
||||
continue;
|
||||
}
|
||||
|
||||
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 (u < 0x0800) {
|
||||
*cursor++ = 0xc0 | ((uchar) (u >> 6));
|
||||
} else {
|
||||
/* Qt 5 Beta 1
|
||||
// is it one of the Unicode non-characters?
|
||||
if (QChar::isNonCharacter(u)) {
|
||||
*cursor++ = replacement;
|
||||
++ch;
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
if (QChar::requiresSurrogates(u)) {
|
||||
*cursor++ = 0xf0 | ((uchar) (u >> 18));
|
||||
*cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f);
|
||||
} else {
|
||||
*cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f);
|
||||
}
|
||||
*cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f);
|
||||
}
|
||||
*cursor++ = 0x80 | ((uchar) (u & 0x3f));
|
||||
}
|
||||
++ch;
|
||||
}
|
||||
|
||||
ba.resize(cursor - (const uchar *)ba.constData());
|
||||
return ba;
|
||||
}
|
||||
|
||||
static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value &v, QByteArray &json, int indent,
|
||||
bool compact)
|
||||
{
|
||||
QJsonValue::Type type = (QJsonValue::Type)(uint)v.type;
|
||||
switch (type) {
|
||||
case QJsonValue::Bool:
|
||||
json += v.toBoolean() ? "true" : "false";
|
||||
break;
|
||||
case QJsonValue::Double:
|
||||
json += QByteArray::number(v.toDouble(b), 'g', 17);
|
||||
break;
|
||||
case QJsonValue::String:
|
||||
json += '"';
|
||||
json += escapedString(v.toString(b));
|
||||
json += '"';
|
||||
break;
|
||||
case QJsonValue::Array:
|
||||
json += compact ? "[" : "[\n";
|
||||
arrayContentToJson(static_cast<QJsonPrivate::Array *>(v.base(b)), json, indent + (compact ? 0 : 1), compact);
|
||||
json += QByteArray(4 * indent, ' ');
|
||||
json += "]";
|
||||
break;
|
||||
case QJsonValue::Object:
|
||||
json += compact ? "{" : "{\n";
|
||||
objectContentToJson(static_cast<QJsonPrivate::Object *>(v.base(b)), json, indent + (compact ? 0 : 1), compact);
|
||||
json += QByteArray(4 * indent, ' ');
|
||||
json += "}";
|
||||
break;
|
||||
case QJsonValue::Null:
|
||||
default:
|
||||
json += "null";
|
||||
}
|
||||
}
|
||||
|
||||
static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact)
|
||||
{
|
||||
if (!a || !a->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray indentString(4 * indent, ' ');
|
||||
|
||||
uint i = 0;
|
||||
while (1) {
|
||||
json += indentString;
|
||||
valueToJson(a, a->at(i), json, indent, compact);
|
||||
|
||||
if (++i == a->length) {
|
||||
if (!compact) {
|
||||
json += '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
json += compact ? "," : ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact)
|
||||
{
|
||||
if (!o || !o->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray indentString(4 * indent, ' ');
|
||||
|
||||
uint i = 0;
|
||||
while (1) {
|
||||
QJsonPrivate::Entry *e = o->entryAt(i);
|
||||
json += indentString;
|
||||
json += '"';
|
||||
json += escapedString(e->key());
|
||||
json += "\": ";
|
||||
valueToJson(o, e->value, json, indent, compact);
|
||||
|
||||
if (++i == o->length) {
|
||||
if (!compact) {
|
||||
json += '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
json += compact ? "," : ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Writer::objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact)
|
||||
{
|
||||
json.reserve(json.size() + (o ? (int)o->size : 16));
|
||||
json += compact ? "{" : "{\n";
|
||||
objectContentToJson(o, json, indent + (compact ? 0 : 1), compact);
|
||||
json += QByteArray(4 * indent, ' ');
|
||||
json += compact ? "}" : "}\n";
|
||||
}
|
||||
|
||||
void Writer::arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact)
|
||||
{
|
||||
json.reserve(json.size() + (a ? (int)a->size : 16));
|
||||
json += compact ? "[" : "[\n";
|
||||
arrayContentToJson(a, json, indent + (compact ? 0 : 1), compact);
|
||||
json += QByteArray(4 * indent, ' ');
|
||||
json += compact ? "]" : "]\n";
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -1,45 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (c) 2012-2015 Barbara Geller
|
||||
** Copyright (c) 2012-2015 Ansel Sermersheim
|
||||
** Copyright (c) 2012-2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (c) 2008-2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2016 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONWRITER_P_H
|
||||
#define QJSONWRITER_P_H
|
||||
|
||||
#include "qjsonvalue.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QJsonPrivate {
|
||||
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
static void objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact = false);
|
||||
static void arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact = false);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
|
@ -31,9 +31,6 @@
|
|||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
# include "qeasingcurve.h"
|
||||
# include "qjsonvalue.h"
|
||||
# include "qjsonobject.h"
|
||||
# include "qjsonarray.h"
|
||||
# include "qjsondocument.h"
|
||||
# include "qbitarray.h"
|
||||
# include "qurl.h"
|
||||
|
@ -117,9 +114,6 @@ QT_BEGIN_NAMESPACE
|
|||
\value QPointF QPointF
|
||||
\value QRegExp QRegExp
|
||||
\value QEasingCurve QEasingCurve
|
||||
\value QJsonValue QJsonValue
|
||||
\value QJsonObject QJsonObject
|
||||
\value QJsonArray QJsonArray
|
||||
\value QJsonDocument QJsonDocument
|
||||
\value QVariantHash QVariantHash
|
||||
\value QVariantList QVariantList
|
||||
|
@ -244,9 +238,6 @@ static const struct MetaTypeTblData {
|
|||
QT_ADD_STATIC_METATYPE("QPointF", QMetaType::QPointF),
|
||||
QT_ADD_STATIC_METATYPE("QRegExp", QMetaType::QRegExp),
|
||||
QT_ADD_STATIC_METATYPE("QEasingCurve", QMetaType::QEasingCurve),
|
||||
QT_ADD_STATIC_METATYPE("QJsonValue", QMetaType:: QJsonValue),
|
||||
QT_ADD_STATIC_METATYPE("QJsonObject", QMetaType::QJsonObject),
|
||||
QT_ADD_STATIC_METATYPE("QJsonArray", QMetaType::QJsonArray),
|
||||
QT_ADD_STATIC_METATYPE("QJsonDocument", QMetaType::QJsonDocument),
|
||||
QT_ADD_STATIC_METATYPE("QVariantHash", QMetaType::QVariantHash),
|
||||
QT_ADD_STATIC_METATYPE("QVariantList", QMetaType::QVariantList),
|
||||
|
@ -621,9 +612,6 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
|
|||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
case QMetaType::QWidgetStar:
|
||||
case QMetaType::QJsonValue:
|
||||
case QMetaType::QJsonObject:
|
||||
case QMetaType::QJsonArray:
|
||||
case QMetaType::QJsonDocument:
|
||||
return false;
|
||||
case QMetaType::Long:
|
||||
|
@ -818,9 +806,6 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
|
|||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
case QMetaType::QWidgetStar:
|
||||
case QMetaType::QJsonValue:
|
||||
case QMetaType::QJsonObject:
|
||||
case QMetaType::QJsonArray:
|
||||
case QMetaType::QJsonDocument:
|
||||
return false;
|
||||
case QMetaType::Long: {
|
||||
|
@ -1094,12 +1079,6 @@ void *QMetaType::construct(int type, const void *copy)
|
|||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QEasingCurve:
|
||||
return new NS(QEasingCurve)(*static_cast<const NS(QEasingCurve)*>(copy));
|
||||
case QMetaType::QJsonValue:
|
||||
return new NS(QJsonValue)(*static_cast<const NS(QJsonValue)*>(copy));
|
||||
case QMetaType::QJsonObject:
|
||||
return new NS(QJsonObject)(*static_cast<const NS(QJsonObject)*>(copy));
|
||||
case QMetaType::QJsonArray:
|
||||
return new NS(QJsonArray)(*static_cast<const NS(QJsonArray)*>(copy));
|
||||
case QMetaType::QJsonDocument:
|
||||
return new NS(QJsonDocument)(*static_cast<const NS(QJsonDocument)*>(copy));
|
||||
#endif
|
||||
|
@ -1362,15 +1341,6 @@ void QMetaType::destroy(int type, void *data)
|
|||
case QMetaType::QEasingCurve:
|
||||
delete static_cast< NS(QEasingCurve)* >(data);
|
||||
break;
|
||||
case QMetaType::QJsonValue:
|
||||
delete static_cast< NS(QJsonValue)* >(data);
|
||||
break;
|
||||
case QMetaType::QJsonObject:
|
||||
delete static_cast< NS(QJsonObject)* >(data);
|
||||
break;
|
||||
case QMetaType::QJsonArray:
|
||||
delete static_cast< NS(QJsonArray)* >(data);
|
||||
break;
|
||||
case QMetaType::QJsonDocument:
|
||||
delete static_cast< NS(QJsonDocument)* >(data);
|
||||
break;
|
||||
|
|
|
@ -45,9 +45,8 @@ public:
|
|||
QByteArray = 11, QBitArray = 12, QDate = 13, QTime = 14,
|
||||
QDateTime = 15, QUrl = 16, QLocale = 17, QRect = 18, QRectF = 19,
|
||||
QSize = 20, QSizeF = 21, QLine = 22, QLineF = 23, QPoint = 24,
|
||||
QPointF = 25, QRegExp = 26, QEasingCurve = 27, QJsonValue = 28,
|
||||
QJsonObject = 29, QJsonArray = 30, QJsonDocument = 31,
|
||||
QVariantHash = 32, QVariantList = 33, QVariantMap = 34,
|
||||
QPointF = 25, QRegExp = 26, QEasingCurve = 27, QJsonDocument = 28,
|
||||
QVariantHash = 29, QVariantList = 30, QVariantMap = 31,
|
||||
LastCoreType = QVariantMap,
|
||||
|
||||
FirstGuiType = 64 /* QFont */,
|
||||
|
@ -262,9 +261,6 @@ class QPointF;
|
|||
#ifndef QT_NO_REGEXP
|
||||
class QRegExp;
|
||||
#endif
|
||||
class QJsonValue;
|
||||
class QJsonObject;
|
||||
class QJsonArray;
|
||||
class QJsonDocument;
|
||||
class QEasingCurve;
|
||||
class QWidget;
|
||||
|
@ -327,9 +323,6 @@ Q_DECLARE_BUILTIN_METATYPE(QPointF, QPointF)
|
|||
Q_DECLARE_BUILTIN_METATYPE(QRegExp, QRegExp)
|
||||
#endif
|
||||
Q_DECLARE_BUILTIN_METATYPE(QEasingCurve, QEasingCurve)
|
||||
Q_DECLARE_BUILTIN_METATYPE(QJsonValue, QJsonValue)
|
||||
Q_DECLARE_BUILTIN_METATYPE(QJsonObject, QJsonObject)
|
||||
Q_DECLARE_BUILTIN_METATYPE(QJsonArray, QJsonArray)
|
||||
Q_DECLARE_BUILTIN_METATYPE(QJsonDocument, QJsonDocument)
|
||||
// QVariantHash
|
||||
// QVariantList
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
# include "qeasingcurve.h"
|
||||
# include "qjsonvalue.h"
|
||||
# include "qjsonobject.h"
|
||||
# include "qjsonarray.h"
|
||||
# include "qjsondocument.h"
|
||||
# include "qsize.h"
|
||||
# include "qpoint.h"
|
||||
|
@ -133,15 +130,6 @@ static void construct(QVariant::Private *x, const void *copy)
|
|||
case QVariant::EasingCurve:
|
||||
v_construct<QEasingCurve>(x, copy);
|
||||
break;
|
||||
case QVariant::JsonValue:
|
||||
v_construct<QJsonValue>(x, copy);
|
||||
break;
|
||||
case QVariant::JsonObject:
|
||||
v_construct<QJsonObject>(x, copy);
|
||||
break;
|
||||
case QVariant::JsonArray:
|
||||
v_construct<QJsonArray>(x, copy);
|
||||
break;
|
||||
case QVariant::JsonDocument:
|
||||
v_construct<QJsonDocument>(x, copy);
|
||||
break;
|
||||
|
@ -265,15 +253,6 @@ static void clear(QVariant::Private *d)
|
|||
case QVariant::EasingCurve:
|
||||
v_clear<QEasingCurve>(d);
|
||||
break;
|
||||
case QVariant::JsonValue:
|
||||
v_clear<QJsonValue>(d);
|
||||
break;
|
||||
case QVariant::JsonObject:
|
||||
v_clear<QJsonObject>(d);
|
||||
break;
|
||||
case QVariant::JsonArray:
|
||||
v_clear<QJsonArray>(d);
|
||||
break;
|
||||
case QVariant::JsonDocument:
|
||||
v_clear<QJsonDocument>(d);
|
||||
break;
|
||||
|
@ -335,12 +314,8 @@ static bool isNull(const QVariant::Private *d)
|
|||
return v_cast<QPoint>(d)->isNull();
|
||||
case QVariant::PointF:
|
||||
return v_cast<QPointF>(d)->isNull();
|
||||
case QVariant::JsonValue:
|
||||
return v_cast<QJsonValue>(d)->isNull();
|
||||
case QVariant::JsonDocument:
|
||||
return v_cast<QJsonDocument>(d)->isNull();
|
||||
case QVariant::JsonObject:
|
||||
case QVariant::JsonArray:
|
||||
case QVariant::EasingCurve:
|
||||
case QVariant::Url:
|
||||
#endif
|
||||
|
@ -464,12 +439,6 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
|
|||
#ifndef QT_BOOTSTRAPPED
|
||||
case QVariant::EasingCurve:
|
||||
return *v_cast<QEasingCurve>(a) == *v_cast<QEasingCurve>(b);
|
||||
case QVariant::JsonValue:
|
||||
return *v_cast<QJsonValue>(a) == *v_cast<QJsonValue>(b);
|
||||
case QVariant::JsonObject:
|
||||
return *v_cast<QJsonObject>(a) == *v_cast<QJsonObject>(b);
|
||||
case QVariant::JsonArray:
|
||||
return *v_cast<QJsonArray>(a) == *v_cast<QJsonArray>(b);
|
||||
case QVariant::JsonDocument:
|
||||
return *v_cast<QJsonDocument>(a) == *v_cast<QJsonDocument>(b);
|
||||
#endif
|
||||
|
@ -534,10 +503,6 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
|
|||
return qRound64(d->data.f);
|
||||
case QVariant::Double:
|
||||
return qRound64(d->data.d);
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QJsonValue:
|
||||
return v_cast<QJsonValue>(d)->toDouble(0.0);
|
||||
#endif
|
||||
}
|
||||
Q_ASSERT(false);
|
||||
return 0;
|
||||
|
@ -574,12 +539,6 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
|
|||
return v_cast<QByteArray>(d)->toLongLong(ok);
|
||||
case QVariant::Bool:
|
||||
return qlonglong(d->data.b);
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QVariant::JsonValue:
|
||||
if (!v_cast<QJsonValue>(d)->isDouble())
|
||||
break;
|
||||
return qlonglong(v_cast<QJsonValue>(d)->toDouble(0.0));
|
||||
#endif
|
||||
case QVariant::Double:
|
||||
case QVariant::Int:
|
||||
case QMetaType::Char:
|
||||
|
@ -613,12 +572,6 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
|
|||
return v_cast<QByteArray>(d)->toULongLong(ok);
|
||||
case QVariant::Bool:
|
||||
return qulonglong(d->data.b);
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QVariant::JsonValue:
|
||||
if (!v_cast<QJsonValue>(d)->isDouble())
|
||||
break;
|
||||
return qulonglong(v_cast<QJsonValue>(d)->toDouble(0.0));
|
||||
#endif
|
||||
case QVariant::Double:
|
||||
case QVariant::Int:
|
||||
case QMetaType::Char:
|
||||
|
@ -716,12 +669,6 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
|
|||
case QVariant::Url:
|
||||
*str = v_cast<QUrl>(d)->toString();
|
||||
return true;
|
||||
case QMetaType::QJsonValue:
|
||||
if (v_cast<QJsonValue>(d)->isString()) {
|
||||
*str = v_cast<QJsonValue>(d)->toString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
|
@ -946,13 +893,6 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
|
|||
case QMetaType::ULong:
|
||||
*static_cast<bool *>(result) = qMetaTypeUNumber(d) != Q_UINT64_C(0);
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QJsonValue:
|
||||
if (!v_cast<QJsonValue>(d)->isBool())
|
||||
return false;
|
||||
*static_cast<bool *>(result) = v_cast<QJsonValue>(d)->toBool(false);
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -986,13 +926,6 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
|
|||
case QMetaType::ULong:
|
||||
*static_cast<double *>(result) = double(qMetaTypeUNumber(d));
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QJsonValue:
|
||||
if (!v_cast<QJsonValue>(d)->isDouble())
|
||||
return false;
|
||||
*static_cast<double *>(result) = v_cast<QJsonValue>(d)->toDouble(0.0);
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -1026,13 +959,6 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
|
|||
case QMetaType::ULong:
|
||||
*static_cast<float *>(result) = float(qMetaTypeUNumber(d));
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QJsonValue:
|
||||
if (!v_cast<QJsonValue>(d)->isDouble())
|
||||
return false;
|
||||
*static_cast<float *>(result) = v_cast<QJsonValue>(d)->toDouble(0.0);
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -1047,48 +973,18 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
|
|||
} else if (d->type == QVariant::List) {
|
||||
*static_cast<QVariantList *>(result) = *static_cast<QList<QVariant> *>(d->data.shared->ptr);
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
} else if (d->type == QMetaType::QJsonValue) {
|
||||
if (!v_cast<QJsonValue>(d)->isArray())
|
||||
return false;
|
||||
*static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList();
|
||||
return true;
|
||||
} else if (d->type == QMetaType::QJsonArray) {
|
||||
*static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
case QVariant::Map:
|
||||
if (d->type == QVariant::Map) {
|
||||
*static_cast<QVariantMap *>(result) = *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr);
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
} else if (d->type == QMetaType::QJsonValue) {
|
||||
if (!v_cast<QJsonValue>(d)->isObject())
|
||||
return false;
|
||||
*static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap();
|
||||
return true;
|
||||
} else if (d->type == QMetaType::QJsonObject) {
|
||||
*static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
case QVariant::Hash:
|
||||
if (d->type == QVariant::Hash) {
|
||||
*static_cast<QVariantHash *>(result) = *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr);
|
||||
return true;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
} else if (d->type == QMetaType::QJsonValue) {
|
||||
if (!v_cast<QJsonValue>(d)->isObject())
|
||||
return false;
|
||||
*static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash();
|
||||
return true;
|
||||
} else if (d->type == QMetaType::QJsonObject) {
|
||||
*static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
|
@ -1187,15 +1083,6 @@ static void streamDebug(QDebug dbg, const QVariant &v)
|
|||
case QVariant::EasingCurve:
|
||||
dbg.nospace() << v.toEasingCurve();
|
||||
break;
|
||||
case QVariant::JsonValue:
|
||||
dbg.nospace() << v.toJsonValue();
|
||||
break;
|
||||
case QVariant::JsonObject:
|
||||
dbg.nospace() << v.toJsonObject();
|
||||
break;
|
||||
case QVariant::JsonArray:
|
||||
dbg.nospace() << v.toJsonArray();
|
||||
break;
|
||||
case QVariant::JsonDocument:
|
||||
dbg.nospace() << v.toJsonDocument();
|
||||
break;
|
||||
|
@ -1368,9 +1255,6 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
|
|||
\value DateTime a QDateTime
|
||||
\value Double a double
|
||||
\value EasingCurve a QEasingCurve
|
||||
\value QJsonValue QJsonValue
|
||||
\value QJsonObject QJsonObject
|
||||
\value QJsonArray QJsonArray
|
||||
\value QJsonDocument QJsonDocument
|
||||
\value Font a QFont
|
||||
\value Hash a QVariantHash
|
||||
|
@ -1586,27 +1470,6 @@ QVariant::QVariant(const char *val)
|
|||
Constructs a new variant with a date/time value, \a val.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
\fn QVariant::QVariant(const QJsonValue &val)
|
||||
|
||||
Constructs a new variant with a json value, \a val.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
\fn QVariant::QVariant(const QJsonObject &val)
|
||||
|
||||
Constructs a new variant with a json object value, \a val.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
\fn QVariant::QVariant(const QJsonArray &val)
|
||||
|
||||
Constructs a new variant with a json array value, \a val.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
\fn QVariant::QVariant(const QJsonDocument &val)
|
||||
|
@ -1812,9 +1675,6 @@ QVariant::QVariant(const QDateTime &val)
|
|||
#ifndef QT_BOOTSTRAPPED
|
||||
QVariant::QVariant(const QEasingCurve &val)
|
||||
{ d.is_null = false; d.type = EasingCurve; v_construct<QEasingCurve>(&d, val); }
|
||||
QVariant::QVariant(const QJsonValue &jsonValue) { d.is_null = false; d.type = JsonValue; v_construct<QJsonValue>(&d, jsonValue); }
|
||||
QVariant::QVariant(const QJsonObject &jsonObject) { d.is_null = false; d.type = JsonObject; v_construct<QJsonObject>(&d, jsonObject); }
|
||||
QVariant::QVariant(const QJsonArray &jsonArray) { d.is_null = false; d.type = JsonArray; v_construct<QJsonArray>(&d, jsonArray); }
|
||||
QVariant::QVariant(const QJsonDocument &jsonDocument) { d.is_null = false; d.type = JsonDocument; v_construct<QJsonDocument>(&d, jsonDocument); }
|
||||
#endif
|
||||
QVariant::QVariant(const QList<QVariant> &list)
|
||||
|
@ -2251,45 +2111,6 @@ QEasingCurve QVariant::toEasingCurve() const
|
|||
return qVariantToHelper<QEasingCurve>(d, EasingCurve, handler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
|
||||
Returns the variant as a QJsonValue if the variant has userType() \l
|
||||
QJsonValue; otherwise returns a default constructed QJsonValue.
|
||||
|
||||
\sa canConvert(), convert()
|
||||
*/
|
||||
QJsonValue QVariant::toJsonValue() const
|
||||
{
|
||||
return qVariantToHelper<QJsonValue>(d, JsonValue, handler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
|
||||
Returns the variant as a QJsonObject if the variant has userType() \l
|
||||
QJsonObject; otherwise returns a default constructed QJsonObject.
|
||||
|
||||
\sa canConvert(), convert()
|
||||
*/
|
||||
QJsonObject QVariant::toJsonObject() const
|
||||
{
|
||||
return qVariantToHelper<QJsonObject>(d, JsonObject, handler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
|
||||
Returns the variant as a QJsonArray if the variant has userType() \l
|
||||
QJsonArray; otherwise returns a default constructed QJsonArray.
|
||||
|
||||
\sa canConvert(), convert()
|
||||
*/
|
||||
QJsonArray QVariant::toJsonArray() const
|
||||
{
|
||||
return qVariantToHelper<QJsonArray>(d, JsonArray, handler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.9
|
||||
|
||||
|
@ -2972,44 +2793,6 @@ bool QVariant::canConvert(Type t) const
|
|||
/* RegExp */
|
||||
/* Hash */
|
||||
/* EasingCurve */
|
||||
} else if (d.type == QVariant::JsonValue) {
|
||||
switch (int(t)) {
|
||||
case QVariant::String:
|
||||
case QVariant::Bool:
|
||||
case QVariant::Int:
|
||||
case QVariant::UInt:
|
||||
case QVariant::Double:
|
||||
case QVariant::Float:
|
||||
case QMetaType::ULong:
|
||||
case QMetaType::Long:
|
||||
case QVariant::LongLong:
|
||||
case QVariant::ULongLong:
|
||||
case QMetaType::UShort:
|
||||
case QMetaType::UChar:
|
||||
case QMetaType::Char:
|
||||
case QMetaType::Short:
|
||||
case QVariant::List:
|
||||
case QVariant::Map:
|
||||
case QVariant::Hash:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (d.type == QVariant::JsonObject) {
|
||||
switch (t) {
|
||||
case QVariant::Map:
|
||||
case QVariant::Hash:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if (d.type == QVariant::JsonArray) {
|
||||
switch (t) {
|
||||
case QVariant::List:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
/* JsonDocument */
|
||||
} else if (t == QVariant::Font) {
|
||||
switch (d.type) {
|
||||
|
|
|
@ -36,9 +36,6 @@ class QDate;
|
|||
class QDateTime;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
class QEasingCurve;
|
||||
class QJsonValue;
|
||||
class QJsonObject;
|
||||
class QJsonArray;
|
||||
class QJsonDocument;
|
||||
#endif
|
||||
class QLine;
|
||||
|
@ -105,9 +102,6 @@ class Q_CORE_EXPORT QVariant
|
|||
RegExp = QMetaType::QRegExp,
|
||||
Hash = QMetaType::QVariantHash,
|
||||
EasingCurve = QMetaType::QEasingCurve,
|
||||
JsonValue = QMetaType::QJsonValue,
|
||||
JsonObject = QMetaType::QJsonObject,
|
||||
JsonArray = QMetaType::QJsonArray,
|
||||
JsonDocument = QMetaType::QJsonDocument,
|
||||
LastCoreType = QMetaType::LastCoreType,
|
||||
|
||||
|
@ -191,9 +185,6 @@ class Q_CORE_EXPORT QVariant
|
|||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
QVariant(const QEasingCurve &easing);
|
||||
QVariant(const QJsonValue &jsonValue);
|
||||
QVariant(const QJsonObject &jsonObject);
|
||||
QVariant(const QJsonArray &jsonArray);
|
||||
QVariant(const QJsonDocument &jsonDocument);
|
||||
#endif
|
||||
|
||||
|
@ -258,9 +249,6 @@ class Q_CORE_EXPORT QVariant
|
|||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
QEasingCurve toEasingCurve() const;
|
||||
QJsonValue toJsonValue() const;
|
||||
QJsonObject toJsonObject() const;
|
||||
QJsonArray toJsonArray() const;
|
||||
QJsonDocument toJsonDocument() const;
|
||||
#endif
|
||||
|
||||
|
|
408
src/core/tools/qjsondocument.cpp
Normal file
408
src/core/tools/qjsondocument.cpp
Normal file
|
@ -0,0 +1,408 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qjsondocument.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qvariant.h"
|
||||
#include "qscopedpointer.h"
|
||||
#include "qcoreapplication.h"
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QJsonDocumentPrivate {
|
||||
public:
|
||||
QJsonDocumentPrivate() : ref(1) { }
|
||||
|
||||
QVariantMap jsonToMap(const QByteArray &jsondata);
|
||||
QByteArray mapToJson(const QVariantMap &jsonmap);
|
||||
|
||||
QAtomicInt ref;
|
||||
QByteArray json;
|
||||
QVariantMap map;
|
||||
QString error;
|
||||
};
|
||||
|
||||
QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
||||
{
|
||||
QVariantMap result;
|
||||
|
||||
if (jsondata.isEmpty()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data is empty");
|
||||
return result;
|
||||
}
|
||||
|
||||
json_error_t jerror;
|
||||
json_t *jroot = json_loads(jsondata.constData(), 0, &jerror);
|
||||
|
||||
if (!jroot) {
|
||||
error = jerror.text;
|
||||
return result;
|
||||
}
|
||||
|
||||
switch(json_typeof(jroot)) {
|
||||
case JSON_OBJECT: {
|
||||
const char *jkey;
|
||||
json_t *jobject;
|
||||
json_object_foreach(jroot, jkey, jobject) {
|
||||
switch(json_typeof(jobject)) {
|
||||
case JSON_OBJECT: {
|
||||
result.insert(jkey, jsonToMap(json_dumps(jobject, 0)));
|
||||
break;
|
||||
}
|
||||
case JSON_ARRAY: {
|
||||
QVariantList listvalue;
|
||||
for (size_t i = 0; i < json_array_size(jobject); i++) {
|
||||
json_t *jarray = json_array_get(jobject, i);
|
||||
switch(json_typeof(jarray)) {
|
||||
case JSON_OBJECT: {
|
||||
listvalue.append(jsonToMap(json_dumps(jarray, 0)));
|
||||
break;
|
||||
}
|
||||
case JSON_STRING: {
|
||||
listvalue.append(QVariant(json_string_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_INTEGER: {
|
||||
listvalue.append(QVariant(json_integer_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
listvalue.append(QVariant(json_real_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_TRUE: {
|
||||
listvalue.append(QVariant(true));
|
||||
break;
|
||||
}
|
||||
case JSON_FALSE: {
|
||||
listvalue.append(QVariant(false));
|
||||
break;
|
||||
}
|
||||
case JSON_NULL: {
|
||||
listvalue.append(QVariant());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown JSON type in array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.insert(jkey, listvalue);
|
||||
break;
|
||||
}
|
||||
case JSON_STRING: {
|
||||
result.insert(jkey, QVariant(json_string_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_INTEGER: {
|
||||
result.insert(jkey, QVariant(json_integer_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
result.insert(jkey, QVariant(json_real_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_TRUE: {
|
||||
result.insert(jkey, QVariant(true));
|
||||
break;
|
||||
}
|
||||
case JSON_FALSE: {
|
||||
result.insert(jkey, QVariant(false));
|
||||
break;
|
||||
}
|
||||
case JSON_NULL: {
|
||||
result.insert(jkey, QVariant());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown JSON type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Rootless array/values are not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
json_decref(jroot);
|
||||
|
||||
// qDebug() << "converted" << jsondata << "to" << result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray QJsonDocumentPrivate::mapToJson(const QVariantMap &jsonmap)
|
||||
{
|
||||
QByteArray result;
|
||||
|
||||
if (jsonmap.isEmpty()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data map is empty");
|
||||
return result;
|
||||
}
|
||||
|
||||
static const size_t jflags = JSON_SORT_KEYS | JSON_INDENT(4);
|
||||
json_t *jroot = json_object();
|
||||
|
||||
foreach(const QString &key, jsonmap.keys()) {
|
||||
const QVariant value = jsonmap.value(key);
|
||||
const QByteArray bytearraykey = key.toUtf8();
|
||||
switch(value.type()) {
|
||||
case QVariant::Invalid: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_null());
|
||||
break;
|
||||
}
|
||||
case QVariant::Bool: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), value.toBool() ? json_true() : json_false());
|
||||
break;
|
||||
}
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toLongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toULongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::Float:
|
||||
case QVariant::Double: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_real(value.toReal()));
|
||||
break;
|
||||
}
|
||||
case QVariant::Char:
|
||||
case QVariant::ByteArray:
|
||||
case QVariant::String: {
|
||||
const QByteArray bytearrayvalue = value.toByteArray();
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_string(bytearrayvalue.constData()));
|
||||
break;
|
||||
}
|
||||
case QVariant::List: // TODO: this works only for QString-convertable types
|
||||
case QVariant::StringList: {
|
||||
json_t *jarray = json_array();
|
||||
foreach(const QString &listvalue, value.toStringList()) {
|
||||
const QByteArray bytearrayvalue = listvalue.toUtf8();
|
||||
json_array_append_new(jarray, json_stringn_nocheck(bytearrayvalue.constData(), bytearrayvalue.size()));
|
||||
}
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), jarray);
|
||||
break;
|
||||
}
|
||||
case QVariant::Hash:
|
||||
case QVariant::Map: {
|
||||
result += mapToJson(value.toMap());
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown JSON type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result += json_dumps(jroot, jflags);
|
||||
json_decref(jroot);
|
||||
|
||||
// qDebug() << "converted" << jsonmap << "to" << result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument()
|
||||
: d_ptr(Q_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
QJsonDocument::~QJsonDocument()
|
||||
{
|
||||
Q_D(QJsonDocument);
|
||||
if (d && !d->ref.deref()) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument::QJsonDocument(const QJsonDocument &other)
|
||||
{
|
||||
qAtomicAssign(d_ptr, other.d_ptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
Assigns the \a other document to this QJsonDocument.
|
||||
Returns a reference to this object.
|
||||
*/
|
||||
QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
|
||||
{
|
||||
qAtomicAssign(d_ptr, other.d_ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a QJsonDocument from the QVariant \a variant.
|
||||
|
||||
If the \a variant contains any other type than a QVariant::Invalid,
|
||||
QVariant::Bool, QVariant::Int, QVariant::LongLong, QVariant::UInt,
|
||||
QVariant::ULongLong, QVariant::Float, QVariant::Double, QVariant::Char,
|
||||
QVariant::ByteArray, QVariant::String, QVariant::List,
|
||||
QVariant::StringList, QVariant::Hash or QVariant::Map the returned document
|
||||
is null.
|
||||
|
||||
\sa toVariant()
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
|
||||
{
|
||||
QScopedPointer<QJsonDocumentPrivate> d(new QJsonDocumentPrivate());
|
||||
d->map = variant.toMap();
|
||||
d->json = d->mapToJson(d->map);
|
||||
|
||||
QJsonDocument jd;
|
||||
if (Q_UNLIKELY(!d->error.isEmpty())) {
|
||||
d->json.clear();
|
||||
d->map.clear();
|
||||
}
|
||||
|
||||
jd.d_ptr = d.take();
|
||||
|
||||
// qDebug() << "QJsonDocument::fromVariant" << jd.errorString();
|
||||
|
||||
return jd;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QVariant representing the Json document.
|
||||
|
||||
The returned variant will be a QVariantList if the document is
|
||||
a array and a QVariantMap if the document is a object.
|
||||
|
||||
\sa fromVariant()
|
||||
*/
|
||||
QVariant QJsonDocument::toVariant() const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
if (!d) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return d->map;
|
||||
}
|
||||
|
||||
/*!
|
||||
Parses a UTF-8 encoded JSON document and creates a QJsonDocument
|
||||
from it.
|
||||
|
||||
\a json contains the json document to be parsed.
|
||||
|
||||
\sa toJson(), errorString()
|
||||
*/
|
||||
QJsonDocument QJsonDocument::fromJson(const QByteArray &json)
|
||||
{
|
||||
QScopedPointer<QJsonDocumentPrivate> d(new QJsonDocumentPrivate());
|
||||
d->json = json;
|
||||
d->map = d->jsonToMap(json);
|
||||
|
||||
if (Q_UNLIKELY(!d->error.isEmpty())) {
|
||||
d->json.clear();
|
||||
d->map.clear();
|
||||
}
|
||||
|
||||
QJsonDocument jd;
|
||||
jd.d_ptr = d.take();
|
||||
|
||||
// qDebug() << "QJsonDocument::fromJson" << jd.errorString();
|
||||
|
||||
return jd;
|
||||
}
|
||||
|
||||
QByteArray QJsonDocument::toJson() const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
if (!d) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return d->json;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the \a other document is equal to this document.
|
||||
*/
|
||||
bool QJsonDocument::operator==(const QJsonDocument &other) const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
if (d == other.d_ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!d || !other.d_ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (d->json == other.d_ptr->json && d->map == other.d_ptr->map);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QJsonDocument::operator!=(const QJsonDocument &other) const
|
||||
|
||||
returns \c true if \a other is not equal to this document
|
||||
*/
|
||||
|
||||
/*!
|
||||
returns true if this document is null.
|
||||
|
||||
Null documents are documents created through the default constructor.
|
||||
|
||||
Documents created from UTF-8 encoded text are validated during parsing. If
|
||||
validation fails, the returned document will be null.
|
||||
*/
|
||||
bool QJsonDocument::isNull() const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
return (!d || (d->json.isEmpty() && d->map.isEmpty()));
|
||||
}
|
||||
|
||||
QString QJsonDocument::errorString() const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
if (!d) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return d->error;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const QJsonDocument &jd)
|
||||
{
|
||||
if (jd.isNull()) {
|
||||
dbg << "QJsonDocument()";
|
||||
return dbg;
|
||||
}
|
||||
dbg.nospace() << "QJsonDocument("
|
||||
<< jd.toJson().constData()
|
||||
<< ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
64
src/core/tools/qjsondocument.h
Normal file
64
src/core/tools/qjsondocument.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Ivailo Monev
|
||||
**
|
||||
** This file is part of the QtCore module of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QJSONDOCUMENT_H
|
||||
#define QJSONDOCUMENT_H
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QJsonDocumentPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QJsonDocument
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QJsonDocument)
|
||||
public:
|
||||
QJsonDocument();
|
||||
~QJsonDocument();
|
||||
|
||||
QJsonDocument(const QJsonDocument &other);
|
||||
QJsonDocument &operator =(const QJsonDocument &other);
|
||||
|
||||
static QJsonDocument fromVariant(const QVariant &variant);
|
||||
QVariant toVariant() const;
|
||||
|
||||
static QJsonDocument fromJson(const QByteArray &json);
|
||||
QByteArray toJson() const;
|
||||
|
||||
bool isNull() const;
|
||||
QString errorString() const;
|
||||
|
||||
bool operator==(const QJsonDocument &other) const;
|
||||
bool operator!=(const QJsonDocument &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
|
||||
|
||||
QJsonDocumentPrivate *d_ptr;
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QJSONDOCUMENT_H
|
|
@ -371,14 +371,7 @@ static const struct ClassTblData {
|
|||
{ QLatin1String("QItemSelection"), QLatin1String("QtGui/qitemselectionmodel.h") },
|
||||
{ QLatin1String("QItemSelectionModel"), QLatin1String("QtGui/qitemselectionmodel.h") },
|
||||
{ QLatin1String("QItemSelectionRange"), QLatin1String("QtGui/qitemselectionmodel.h") },
|
||||
{ QLatin1String("QJsonArray"), QLatin1String("QtCore/qjsonarray.h") },
|
||||
{ QLatin1String("QJsonDocument"), QLatin1String("QtCore/qjsondocument.h") },
|
||||
{ QLatin1String("QJsonObject"), QLatin1String("QtCore/qjsonobject.h") },
|
||||
{ QLatin1String("QJsonParseError"), QLatin1String("QtCore/qjsondocument.h") },
|
||||
{ QLatin1String("QJsonValue"), QLatin1String("QtCore/qjsonvalue.h") },
|
||||
{ QLatin1String("QJsonValuePtr"), QLatin1String("QtCore/qjsonvalue.h") },
|
||||
{ QLatin1String("QJsonValueRef"), QLatin1String("QtCore/qjsonvalue.h") },
|
||||
{ QLatin1String("QJsonValueRefPtr"), QLatin1String("QtCore/qjsonvalue.h") },
|
||||
{ QLatin1String("QKeyEvent"), QLatin1String("QtGui/qevent.h") },
|
||||
{ QLatin1String("QKeySequence"), QLatin1String("QtGui/qkeysequence.h") },
|
||||
{ QLatin1String("QLCDNumber"), QLatin1String("QtGui/qlcdnumber.h") },
|
||||
|
|
3
tests/auto/qjsondocument/CMakeLists.txt
Normal file
3
tests/auto/qjsondocument/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
katie_test(tst_qjsondocument
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tst_qjsondocument.cpp
|
||||
)
|
5
tests/auto/qjsondocument/invalidjson.json
Normal file
5
tests/auto/qjsondocument/invalidjson.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"Qt/GUIEffects": [
|
||||
"none"
|
||||
],
|
||||
}
|
35
tests/auto/qjsondocument/qjsondocument.json
Normal file
35
tests/auto/qjsondocument/qjsondocument.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"Qt/GUIEffects": [
|
||||
"none"
|
||||
],
|
||||
"Qt/Palette/active": [
|
||||
],
|
||||
"Qt/Palette/disabled": [
|
||||
],
|
||||
"Qt/Palette/inactive": [
|
||||
],
|
||||
"Qt/cursorFlashTime": 1000,
|
||||
"Qt/doubleClickInterval": 400,
|
||||
"Qt/embedFonts": true,
|
||||
"Qt/font": "Sans Serif,9,-1,5,50,0,0,0,0",
|
||||
"Qt/fontPath": [
|
||||
],
|
||||
"Qt/globalStrut/height": 0,
|
||||
"Qt/globalStrut/width": 0,
|
||||
"Qt/resolveSymlinks": false,
|
||||
"Qt/style": "Cleanlooks",
|
||||
"Qt/useRtlExtensions": false,
|
||||
"Qt/wheelScrollLines": 3,
|
||||
|
||||
"MixedArray": [
|
||||
1,
|
||||
"a"
|
||||
],
|
||||
|
||||
"NestedObject": {
|
||||
"MixedArray": [
|
||||
2,
|
||||
"b"
|
||||
]
|
||||
}
|
||||
}
|
147
tests/auto/qjsondocument/tst_qjsondocument.cpp
Normal file
147
tests/auto/qjsondocument/tst_qjsondocument.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 Ivailo Monev
|
||||
**
|
||||
** This file is part of the test suite of the Katie Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtCore/QtCore>
|
||||
|
||||
//TESTED_CLASS=QJsonDocument
|
||||
//TESTED_FILES=qjsondocument.cpp,qjsondocument.h
|
||||
|
||||
static QString testinvalidfile = QString::fromLatin1(SRCDIR "/invalidjson.json");
|
||||
static QString testjsonfile = QString::fromLatin1(SRCDIR "/qjsondocument.json");
|
||||
static QVariantMap testjsondata;
|
||||
|
||||
class tst_QJsonDocument : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
private slots:
|
||||
void read();
|
||||
void write();
|
||||
void error();
|
||||
};
|
||||
|
||||
void tst_QJsonDocument::init()
|
||||
{
|
||||
testjsondata.insert("Qt/GUIEffects", QStringList() << "none");
|
||||
testjsondata.insert("Qt/doubleClickInterval", 400);
|
||||
testjsondata.insert("Qt/embedFonts", true);
|
||||
testjsondata.insert("Qt/style", "Cleanlooks");
|
||||
|
||||
testjsondata.insert("MixedArray", QVariantList() << 1 << "a");
|
||||
QVariantMap NestedObject;
|
||||
NestedObject.insert("MixedArray", QVariantList() << 2 << "b");
|
||||
testjsondata.insert("NestedObject", NestedObject);
|
||||
}
|
||||
|
||||
void tst_QJsonDocument::cleanup()
|
||||
{
|
||||
testjsondata.clear();
|
||||
}
|
||||
|
||||
void tst_QJsonDocument::read()
|
||||
{
|
||||
QJsonDocument jsondoc = QJsonDocument::fromVariant(testjsondata);
|
||||
QVERIFY(jsondoc.errorString().isEmpty());
|
||||
QVariantMap jsonmap = jsondoc.toVariant().toMap();
|
||||
|
||||
QStringList GUIEffects = jsonmap.value("Qt/GUIEffects").toStringList();
|
||||
QCOMPARE(GUIEffects, QStringList() << "none");
|
||||
|
||||
int doubleClickInterval = jsonmap.value("Qt/doubleClickInterval").toInt();
|
||||
QCOMPARE(doubleClickInterval, 400);
|
||||
|
||||
bool embedFonts = jsonmap.value("Qt/embedFonts").toBool();
|
||||
QCOMPARE(embedFonts, true);
|
||||
|
||||
QString style = jsonmap.value("Qt/style").toString();
|
||||
QCOMPARE(style, QLatin1String("Cleanlooks"));
|
||||
|
||||
QVariantList MixedArray = jsonmap.value("MixedArray").toList();
|
||||
QCOMPARE(MixedArray, QVariantList() << 1 << "a");
|
||||
|
||||
QVariantList NestedObject = jsonmap.value("NestedObject").toMap().value("MixedArray").toList();
|
||||
QCOMPARE(NestedObject, QVariantList() << 2 << "b");
|
||||
|
||||
QFile jsonfile(testjsonfile);
|
||||
QVERIFY(jsonfile.open(QIODevice::ReadOnly));
|
||||
|
||||
jsondoc = QJsonDocument::fromJson(jsonfile.readAll());
|
||||
QVERIFY(jsondoc.errorString().isEmpty());
|
||||
jsonmap = jsondoc.toVariant().toMap();
|
||||
|
||||
GUIEffects = jsonmap.value("Qt/GUIEffects").toStringList();
|
||||
QCOMPARE(GUIEffects, QStringList() << "none");
|
||||
|
||||
doubleClickInterval = jsonmap.value("Qt/doubleClickInterval").toInt();
|
||||
QCOMPARE(doubleClickInterval, 400);
|
||||
|
||||
embedFonts = jsonmap.value("Qt/embedFonts").toBool();
|
||||
QCOMPARE(embedFonts, true);
|
||||
|
||||
style = jsonmap.value("Qt/style").toString();
|
||||
QCOMPARE(style, QLatin1String("Cleanlooks"));
|
||||
|
||||
MixedArray = jsonmap.value("MixedArray").toList();
|
||||
QCOMPARE(MixedArray, QVariantList() << 1 << "a");
|
||||
|
||||
NestedObject = jsonmap.value("NestedObject").toMap().value("MixedArray").toList();
|
||||
QCOMPARE(NestedObject, QVariantList() << 2 << "b");
|
||||
|
||||
// TODO: test other types too
|
||||
}
|
||||
|
||||
void tst_QJsonDocument::write()
|
||||
{
|
||||
QJsonDocument jsondoc = QJsonDocument::fromVariant(testjsondata);
|
||||
// TODO: compare to desired output
|
||||
QVERIFY(!jsondoc.toJson().isEmpty());
|
||||
|
||||
QFile jsonfile(testjsonfile);
|
||||
QVERIFY(jsonfile.open(QIODevice::ReadOnly));
|
||||
QByteArray jsoncontent = jsonfile.readAll();
|
||||
jsondoc = QJsonDocument::fromJson(jsoncontent);
|
||||
QCOMPARE(jsoncontent, jsondoc.toJson());
|
||||
}
|
||||
|
||||
void tst_QJsonDocument::error()
|
||||
{
|
||||
QFile jsonfile(testinvalidfile);
|
||||
QVERIFY(jsonfile.open(QIODevice::ReadOnly));
|
||||
QJsonDocument jsondoc = QJsonDocument::fromJson(jsonfile.readAll());
|
||||
// not testing for specific string on purpose
|
||||
QVERIFY(!jsondoc.errorString().isEmpty());
|
||||
QVERIFY(jsondoc.isNull());
|
||||
|
||||
jsondoc = QJsonDocument::fromVariant(QVariantMap());
|
||||
QCOMPARE(jsondoc.errorString(), QLatin1String("Data map is empty"));
|
||||
QVERIFY(jsondoc.isNull());
|
||||
|
||||
// TODO: indermediate error test
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QJsonDocument)
|
||||
|
||||
#include "moc_tst_qjsondocument.cpp"
|
2547
translations/qt.pot
2547
translations/qt.pot
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-05 06:17+0200\n"
|
||||
"POT-Creation-Date: 2021-02-11 01:35+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,11 +17,11 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/tools/qtconfig/previewframe.cpp:75
|
||||
#: src/tools/qtconfig/previewframe.cpp:63
|
||||
msgid "Desktop settings will only take effect after an application restart."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:68
|
||||
#: src/tools/qtconfig/mainwindow.cpp:56
|
||||
msgctxt "MainWindow"
|
||||
msgid ""
|
||||
"<p><b><font size+=2>Appearance</font></b></p><hr><p>Use this tab to "
|
||||
|
@ -36,7 +36,7 @@ msgid ""
|
|||
"Window shows what the selected Style and colors look like."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:84
|
||||
#: src/tools/qtconfig/mainwindow.cpp:72
|
||||
msgctxt "MainWindow"
|
||||
msgid ""
|
||||
"<p><b><font size+=2>Fonts</font></b></p><hr><p>Use this tab to select the "
|
||||
|
@ -54,7 +54,7 @@ msgid ""
|
|||
"text)."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:103
|
||||
#: src/tools/qtconfig/mainwindow.cpp:91
|
||||
msgctxt "MainWindow"
|
||||
msgid ""
|
||||
"<p><b><font size+=2>Interface</font></b></p><hr><p>Use this tab to customize "
|
||||
|
@ -69,7 +69,7 @@ msgid ""
|
|||
"disable the Global Strut feature."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:118
|
||||
#: src/tools/qtconfig/mainwindow.cpp:106
|
||||
msgctxt "MainWindow"
|
||||
msgid ""
|
||||
"<p><b><font size+=2>Printer</font></b></p><hr><p>Use this tab to configure "
|
||||
|
@ -82,755 +82,755 @@ msgid ""
|
|||
"the X server font path is used."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:201
|
||||
#: src/tools/qtconfig/mainwindow.cpp:189
|
||||
msgid "Desktop Settings (Default)"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:207
|
||||
#: src/tools/qtconfig/mainwindow.cpp:195
|
||||
msgid "Choose style and palette based on your desktop settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:222
|
||||
#: src/tools/qtconfig/mainwindow.cpp:210
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:368
|
||||
#: src/tools/qtconfig/mainwindow.cpp:356
|
||||
msgid "No changes to be saved."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:372
|
||||
#: src/tools/qtconfig/mainwindow.cpp:360
|
||||
msgid "Saving changes..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:457
|
||||
#: src/tools/qtconfig/mainwindow.cpp:445
|
||||
msgid "Saved changes."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:723
|
||||
#: src/tools/qtconfig/mainwindow.cpp:711
|
||||
msgid "Select a Directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:738
|
||||
#: src/tools/qtconfig/mainwindow.cpp:726
|
||||
msgid ""
|
||||
"<h3>%1</h3><br/>Version %2<br/><br/>Copyright (C) 2015 The Qt Company Ltd."
|
||||
"<br/><br/>Copyright (C) 2016 Ivailo Monev"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:743 src/tools/qtconfig/mainwindow.cpp:744
|
||||
#: src/tools/qtconfig/mainwindow.cpp:751
|
||||
#: src/tools/qtconfig/mainwindow.cpp:731 src/tools/qtconfig/mainwindow.cpp:732
|
||||
#: src/tools/qtconfig/mainwindow.cpp:739
|
||||
msgid "Katie Configuration"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:770
|
||||
#: src/tools/qtconfig/mainwindow.cpp:758
|
||||
msgid "Save Changes"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/mainwindow.cpp:771
|
||||
#: src/tools/qtconfig/mainwindow.cpp:759
|
||||
msgid "Save changes to settings?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:46
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:52
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:34
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:40
|
||||
msgid "Choose a color"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:47
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:35
|
||||
msgid "Choose a color for the selected central color role."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:53
|
||||
#: src/tools/qtconfig/paletteeditoradvanced.cpp:41
|
||||
msgid "Choose a color for the selected effect color role."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:63
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:51
|
||||
msgctxt "QtDBusViewer"
|
||||
msgid "Katie D-Bus Viewer"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:70
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:58
|
||||
msgid "Session Bus"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:71
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:59
|
||||
msgid "System Bus"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:73
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:188
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:61
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:176
|
||||
msgid "&File"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:74
|
||||
#: src/tools/designer/qdesigner_actions.cpp:177
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:62
|
||||
#: src/tools/designer/qdesigner_actions.cpp:165
|
||||
msgid "&Quit"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:77
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:205
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:65
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:193
|
||||
msgid "&Help"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:78
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:66
|
||||
msgid "&About"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:82
|
||||
#: src/tools/qdbusviewer/qdbusviewermain.cpp:70
|
||||
msgid "About &Katie"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:75
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:63
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:86
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:74
|
||||
msgid "&Refresh"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:202
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:190
|
||||
msgid "Arguments"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:203
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:191
|
||||
msgid "Please enter the value of the property %1 (type %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:211
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:199
|
||||
msgid "Unable to marshall"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:212
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:200
|
||||
msgid "Value conversion failed, unable to set property"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:249
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:237
|
||||
msgid "Unable to find method"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:250
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:238
|
||||
msgid "Unable to find method %1 on path %2 in interface %3"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:272
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:260
|
||||
msgid "Please enter parameters for the method \"%1\""
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:322
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:310
|
||||
msgid "&Connect"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:327
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:315
|
||||
msgid "&Call"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:332
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:320
|
||||
msgid "&Set value"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:334
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:322
|
||||
msgid "&Get value"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:367
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:355
|
||||
msgid "Unable to connect to service %1, path %2, interface %3, signal %4"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:489
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:490
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:477
|
||||
#: src/tools/qdbusviewer/qdbusviewer.cpp:478
|
||||
msgid "D-Bus Viewer"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/versiondialog.cpp:158
|
||||
#: src/tools/designer/versiondialog.cpp:146
|
||||
msgid "<h3>%1</h3><br/><br/>Version %2"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/versiondialog.cpp:159
|
||||
#: src/tools/designer/mainwindow.cpp:127
|
||||
#: src/tools/designer/versiondialog.cpp:147
|
||||
#: src/tools/designer/mainwindow.cpp:115
|
||||
msgid "Katie Designer"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/versiondialog.cpp:160
|
||||
#: src/tools/designer/versiondialog.cpp:148
|
||||
msgid ""
|
||||
"<br/>Katie Designer is a graphical user interface designer for Qt "
|
||||
"applications.<br/>"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/versiondialog.cpp:162
|
||||
#: src/tools/designer/versiondialog.cpp:150
|
||||
msgid ""
|
||||
"%1<br/>Copyright (C) 2015 The Qt Company Ltd.<br/>Copyright (C) 2016 Ivailo "
|
||||
"Monev"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:143
|
||||
#: src/tools/designer/appfontdialog.cpp:131
|
||||
msgctxt "AppFontManager"
|
||||
msgid "'%1' is not a file."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:147
|
||||
#: src/tools/designer/appfontdialog.cpp:135
|
||||
msgctxt "AppFontManager"
|
||||
msgid "The font file '%1' does not have read permissions."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:155
|
||||
#: src/tools/designer/appfontdialog.cpp:143
|
||||
msgctxt "AppFontManager"
|
||||
msgid "The font file '%1' is already loaded."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:162
|
||||
#: src/tools/designer/appfontdialog.cpp:150
|
||||
msgctxt "AppFontManager"
|
||||
msgid "The font file '%1' could not be loaded."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:179
|
||||
#: src/tools/designer/appfontdialog.cpp:167
|
||||
msgctxt "AppFontManager"
|
||||
msgid "'%1' is not a valid font id."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:190
|
||||
#: src/tools/designer/appfontdialog.cpp:178
|
||||
msgctxt "AppFontManager"
|
||||
msgid "There is no loaded font matching the id '%1'."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:205
|
||||
#: src/tools/designer/appfontdialog.cpp:193
|
||||
msgctxt "AppFontManager"
|
||||
msgid "The font '%1' (%2) could not be unloaded."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:231
|
||||
#: src/tools/designer/appfontdialog.cpp:219
|
||||
msgid "Fonts"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:289
|
||||
#: src/tools/designer/appfontdialog.cpp:277
|
||||
msgid "Add font files"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:294
|
||||
#: src/tools/designer/appfontdialog.cpp:282
|
||||
msgid "Remove current font file"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:298
|
||||
#: src/tools/designer/appfontdialog.cpp:286
|
||||
msgid "Remove all font files"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:317
|
||||
#: src/tools/designer/appfontdialog.cpp:305
|
||||
msgid "Add Font Files"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:318
|
||||
#: src/tools/designer/appfontdialog.cpp:306
|
||||
msgid "Font files (*.ttf)"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:331
|
||||
#: src/tools/designer/appfontdialog.cpp:319
|
||||
msgid "Error Adding Fonts"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:355
|
||||
#: src/tools/designer/appfontdialog.cpp:343
|
||||
msgid "Error Removing Fonts"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:377
|
||||
#: src/tools/designer/appfontdialog.cpp:365
|
||||
msgid "Remove Fonts"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:377
|
||||
#: src/tools/designer/appfontdialog.cpp:365
|
||||
msgid "Would you like to remove all fonts?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/appfontdialog.cpp:410
|
||||
#: src/tools/designer/appfontdialog.cpp:398
|
||||
msgid "Additional Fonts"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:209
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:197
|
||||
msgid "%1 - %2[*]"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:219
|
||||
#: src/tools/designer/qdesigner_actions.cpp:824
|
||||
#: src/tools/designer/qdesigner_actions.cpp:864
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:207
|
||||
#: src/tools/designer/qdesigner_actions.cpp:812
|
||||
#: src/tools/designer/qdesigner_actions.cpp:852
|
||||
msgid "Save Form?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:220
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:208
|
||||
msgid "Do you want to save the changes to this document before closing?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:222
|
||||
#: src/tools/designer/qdesigner_formwindow.cpp:210
|
||||
msgid "If you don't save, your changes will be lost."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:65
|
||||
#: src/tools/designer/newform.cpp:53
|
||||
msgid "Show this Dialog on Startup"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:66
|
||||
#: src/tools/designer/newform.cpp:54
|
||||
msgctxt "NewForm"
|
||||
msgid "C&reate"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:67
|
||||
#: src/tools/designer/newform.cpp:55
|
||||
msgctxt "NewForm"
|
||||
msgid "Recent"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:70
|
||||
#: src/tools/designer/newform.cpp:58
|
||||
msgid "New Form"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:99
|
||||
#: src/tools/designer/newform.cpp:87
|
||||
msgctxt "NewForm"
|
||||
msgid "&Close"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:102
|
||||
#: src/tools/designer/newform.cpp:90
|
||||
msgctxt "NewForm"
|
||||
msgid "&Open..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:106
|
||||
#: src/tools/designer/qdesigner_actions.cpp:481
|
||||
#: src/tools/designer/newform.cpp:94
|
||||
#: src/tools/designer/qdesigner_actions.cpp:469
|
||||
msgid "&Recent Forms"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:170
|
||||
#: src/tools/designer/qdesigner_actions.cpp:742
|
||||
#: src/tools/designer/newform.cpp:158
|
||||
#: src/tools/designer/qdesigner_actions.cpp:730
|
||||
msgid "Read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:193
|
||||
#: src/tools/designer/newform.cpp:181
|
||||
msgid "A temporary form file could not be created in %1."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/newform.cpp:199
|
||||
#: src/tools/designer/newform.cpp:187
|
||||
msgid "The temporary form file %1 could not be written."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:117
|
||||
#: src/tools/designer/qdesigner_actions.cpp:105
|
||||
msgid "Saved %1."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:143
|
||||
#: src/tools/designer/qdesigner_actions.cpp:131
|
||||
msgid ""
|
||||
"%1 already exists.\n"
|
||||
"Do you want to replace it?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:167
|
||||
#: src/tools/designer/qdesigner_actions.cpp:155
|
||||
msgid "Edit Widgets"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:168
|
||||
#: src/tools/designer/qdesigner_actions.cpp:156
|
||||
msgid "&New..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:169
|
||||
#: src/tools/designer/qdesigner_actions.cpp:157
|
||||
msgid "&Open..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:170
|
||||
#: src/tools/designer/qdesigner_actions.cpp:158
|
||||
msgid "&Save"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:171
|
||||
#: src/tools/designer/qdesigner_actions.cpp:159
|
||||
msgid "Save &As..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:172
|
||||
#: src/tools/designer/qdesigner_actions.cpp:160
|
||||
msgid "Save A&ll"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:173
|
||||
#: src/tools/designer/qdesigner_actions.cpp:161
|
||||
msgid "Save As &Template..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:174
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1023
|
||||
#: src/tools/designer/qdesigner_actions.cpp:162
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1011
|
||||
msgid "&Close"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:175
|
||||
#: src/tools/designer/qdesigner_actions.cpp:163
|
||||
msgid "Save &Image..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:176
|
||||
#: src/tools/designer/qdesigner_actions.cpp:164
|
||||
msgid "&Print..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:179
|
||||
#: src/tools/designer/qdesigner_actions.cpp:167
|
||||
msgid "View &Code..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:180
|
||||
#: src/tools/designer/qdesigner_actions.cpp:168
|
||||
msgid "&Minimize"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:182
|
||||
#: src/tools/designer/qdesigner_actions.cpp:170
|
||||
msgid "Bring All to Front"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:184
|
||||
#: src/tools/designer/qdesigner_actions.cpp:172
|
||||
msgid "Preferences..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:185
|
||||
#: src/tools/designer/qdesigner_actions.cpp:173
|
||||
msgid "Additional Fonts..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:257
|
||||
#: src/tools/designer/qdesigner_actions.cpp:245
|
||||
msgid "CTRL+SHIFT+S"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:378
|
||||
#: src/tools/designer/qdesigner_actions.cpp:366
|
||||
msgid "CTRL+R"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:396
|
||||
#: src/tools/designer/qdesigner_actions.cpp:384
|
||||
msgid "CTRL+M"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:427
|
||||
#: src/tools/designer/qdesigner_actions.cpp:415
|
||||
msgid "About Plugins"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:433
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1004
|
||||
#: src/tools/designer/qdesigner_actions.cpp:421
|
||||
#: src/tools/designer/qdesigner_actions.cpp:992
|
||||
msgid "About Katie Designer"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:439
|
||||
#: src/tools/designer/qdesigner_actions.cpp:427
|
||||
msgid "About Katie"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:475
|
||||
#: src/tools/designer/qdesigner_actions.cpp:463
|
||||
msgid "Clear &Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:558
|
||||
#: src/tools/designer/qdesigner_actions.cpp:755
|
||||
#: src/tools/designer/qdesigner_actions.cpp:546
|
||||
#: src/tools/designer/qdesigner_actions.cpp:743
|
||||
msgid "Open Form"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:559
|
||||
#: src/tools/designer/qdesigner_actions.cpp:596
|
||||
#: src/tools/designer/qdesigner_actions.cpp:756
|
||||
#: src/tools/designer/qdesigner_actions.cpp:547
|
||||
#: src/tools/designer/qdesigner_actions.cpp:584
|
||||
#: src/tools/designer/qdesigner_actions.cpp:744
|
||||
msgid "Designer UI files (*.%1);;All Files (*)"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:596
|
||||
#: src/tools/designer/qdesigner_actions.cpp:844
|
||||
#: src/tools/designer/qdesigner_actions.cpp:584
|
||||
#: src/tools/designer/qdesigner_actions.cpp:832
|
||||
msgid "Save Form As"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:683
|
||||
#: src/tools/designer/qdesigner_actions.cpp:671
|
||||
msgid "Designer"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:683
|
||||
#: src/tools/designer/qdesigner_actions.cpp:671
|
||||
msgid "Feature not implemented yet!"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:698
|
||||
#: src/tools/designer/qdesigner_actions.cpp:686
|
||||
msgid "Code generation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:743
|
||||
#: src/tools/designer/qdesigner_actions.cpp:731
|
||||
msgid ""
|
||||
"%1\n"
|
||||
"Do you want to update the file location or generate a new form?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:746
|
||||
#: src/tools/designer/qdesigner_actions.cpp:734
|
||||
msgid "&Update"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:747
|
||||
#: src/tools/designer/qdesigner_actions.cpp:735
|
||||
msgid "&New Form"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:825
|
||||
#: src/tools/designer/qdesigner_actions.cpp:813
|
||||
msgid "Could not open file"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:829
|
||||
#: src/tools/designer/qdesigner_actions.cpp:817
|
||||
msgid ""
|
||||
"The file %1 could not be opened.\n"
|
||||
"Reason: %2\n"
|
||||
"Would you like to retry or select a different file?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:835
|
||||
#: src/tools/designer/qdesigner_actions.cpp:823
|
||||
msgid "Select New File"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:865
|
||||
#: src/tools/designer/qdesigner_actions.cpp:853
|
||||
msgid "Could not write file"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:868
|
||||
#: src/tools/designer/qdesigner_actions.cpp:856
|
||||
msgid ""
|
||||
"It was not possible to write the entire file %1 to disk.\n"
|
||||
"Reason:%2\n"
|
||||
"Would you like to retry?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1021
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1009
|
||||
msgid "&Close Preview"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1062
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1085
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1050
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1073
|
||||
msgid "The backup file %1 could not be written."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1192
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1180
|
||||
msgid "The backup directory %1 could not be created."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1198
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1186
|
||||
msgid "The temporary backup directory %1 could not be created."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1228
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1216
|
||||
msgid "Preview failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1252
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1240
|
||||
msgid "Image files (*.%1)"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1261
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1278
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1249
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1266
|
||||
msgid "Save Image"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1274
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1262
|
||||
msgid "Saved image %1."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1279
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1267
|
||||
msgid "The file %1 could not be written."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1292
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1280
|
||||
msgid "Please close all forms to enable the loading of additional fonts."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1343
|
||||
#: src/tools/designer/qdesigner_actions.cpp:1331
|
||||
msgid "Printed %1."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:64
|
||||
#: src/tools/designer/saveformastemplate.cpp:52
|
||||
msgid "Add path..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:87
|
||||
#: src/tools/designer/saveformastemplate.cpp:75
|
||||
msgid "Template Exists"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:88
|
||||
#: src/tools/designer/saveformastemplate.cpp:76
|
||||
msgid ""
|
||||
"A template with the name %1 already exists.\n"
|
||||
"Do you want overwrite the template?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:91
|
||||
#: src/tools/designer/saveformastemplate.cpp:79
|
||||
msgid "Overwrite Template"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:98
|
||||
#: src/tools/designer/saveformastemplate.cpp:86
|
||||
msgid "Open Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:99
|
||||
#: src/tools/designer/saveformastemplate.cpp:87
|
||||
msgid "There was an error opening template %1 for writing. Reason: %2"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:112
|
||||
#: src/tools/designer/saveformastemplate.cpp:100
|
||||
msgid "Write Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:113
|
||||
#: src/tools/designer/saveformastemplate.cpp:101
|
||||
msgid "There was an error writing the template %1 to disk. Reason: %2"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/saveformastemplate.cpp:140
|
||||
#: src/tools/designer/saveformastemplate.cpp:128
|
||||
msgid "Pick a directory to save templates in"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:111
|
||||
#: src/tools/designer/mainwindow.cpp:99
|
||||
msgid "Main"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:117 src/tools/designer/mainwindow.cpp:247
|
||||
#: src/tools/designer/mainwindow.cpp:105 src/tools/designer/mainwindow.cpp:235
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:118 src/tools/designer/mainwindow.cpp:251
|
||||
#: src/tools/designer/mainwindow.cpp:106 src/tools/designer/mainwindow.cpp:239
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:119 src/tools/designer/mainwindow.cpp:255
|
||||
#: src/tools/designer/mainwindow.cpp:107 src/tools/designer/mainwindow.cpp:243
|
||||
msgid "Tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:120 src/tools/designer/mainwindow.cpp:259
|
||||
#: src/tools/designer/mainwindow.cpp:108 src/tools/designer/mainwindow.cpp:247
|
||||
msgid "Form"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:216
|
||||
#: src/tools/designer/mainwindow.cpp:204
|
||||
msgid "Configure Toolbars..."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:231
|
||||
#: src/tools/designer/mainwindow.cpp:219
|
||||
msgid "Window"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:232
|
||||
#: src/tools/designer/mainwindow.cpp:220
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:239
|
||||
#: src/tools/designer/mainwindow.cpp:227
|
||||
msgid "Style"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:241
|
||||
#: src/tools/designer/mainwindow.cpp:229
|
||||
msgid "Dock views"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/mainwindow.cpp:263
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:228
|
||||
#: src/tools/designer/mainwindow.cpp:251
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:216
|
||||
msgid "Toolbars"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:179
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:167
|
||||
msgid "Property Editor"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:233
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:221
|
||||
msgid "Action Editor"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:275
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:263
|
||||
msgid "Object Inspector"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:310
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:298
|
||||
msgid "Resource Browser"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:344
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:332
|
||||
msgid "Signal/Slot Editor"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:385
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:394
|
||||
#: src/tools/designer/qdesigner_toolwindow.cpp:373
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:382
|
||||
msgid "Widget Box"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:190
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:178
|
||||
msgid "&Edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:194
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:182
|
||||
msgid "F&orm"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:195
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:183
|
||||
msgid "Preview in"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:199
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:187
|
||||
msgid "&View"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:201
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:189
|
||||
msgid "&Settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:203
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:191
|
||||
msgid "&Window"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:683
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:671
|
||||
msgid "Save Forms?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:684
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:672
|
||||
msgid ""
|
||||
"There are %1 forms with unsaved changes. Do you want to review these changes "
|
||||
"before quitting?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:687
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:675
|
||||
msgid "If you do not review your documents, all your changes will be lost."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:688
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:676
|
||||
msgid "Discard Changes"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:690
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:678
|
||||
msgid "Review Changes"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:785
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:773
|
||||
msgid "Backup Information"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:786
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:774
|
||||
msgid ""
|
||||
"The last session of Designer was not terminated correctly. Backup files were "
|
||||
"left behind. Do you want to load them?"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:896
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:884
|
||||
msgid "The file <b>%1</b> could not be opened."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:942
|
||||
#: src/tools/designer/qdesigner_workbench.cpp:930
|
||||
msgid "The file <b>%1</b> is not a valid Designer UI file."
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:77
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:65
|
||||
msgid "Docked Window"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:78
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:66
|
||||
msgid "Multiple Top-Level Windows"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:83
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:71
|
||||
msgid "Toolwindow Font"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:128
|
||||
#: src/tools/designer/qdesigner_appearanceoptions.cpp:116
|
||||
msgctxt "QDesignerAppearanceOptionsPage"
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qdesigner.cpp:121
|
||||
#: src/tools/designer/qdesigner.cpp:109
|
||||
msgctxt "QDesigner"
|
||||
msgid "%1 - warning"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qttoolbardialog/qttoolbardialog.cpp:1234
|
||||
#: src/tools/designer/qttoolbardialog/qttoolbardialog.cpp:1222
|
||||
msgid "Custom Toolbar"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/qttoolbardialog/qttoolbardialog.cpp:1777
|
||||
#: src/tools/designer/qttoolbardialog/qttoolbardialog.cpp:1765
|
||||
msgid "< S E P A R A T O R >"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:54
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:42
|
||||
msgid "Font"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:59
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:47
|
||||
msgid "&Family"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:63
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:51
|
||||
msgid "&Style"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:67
|
||||
#: src/tools/designer/fontpanel/fontpanel.cpp:55
|
||||
msgid "&Point size"
|
||||
msgstr ""
|
||||
|
|
Loading…
Add table
Reference in a new issue