This is the binary distribution of racket-webview
This commit is contained in:
+69
-28
@@ -1,34 +1,75 @@
|
|||||||
# ---> C++
|
# This file is used to ignore files which are generated
|
||||||
# Prerequisites
|
# ----------------------------------------------------------------------------
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
*~
|
||||||
*.slo
|
*.autosave
|
||||||
*.lo
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
*.o
|
*.o
|
||||||
*.obj
|
*.obj
|
||||||
|
*.orig
|
||||||
# Precompiled Headers
|
*.rej
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.so.*
|
||||||
*.dll
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
# Fortran module files
|
*.qm
|
||||||
*.mod
|
.#*
|
||||||
*.smod
|
*.*#
|
||||||
|
core
|
||||||
# Compiled Static libraries
|
!core/
|
||||||
*.lai
|
tags
|
||||||
*.la
|
.DS_Store
|
||||||
*.a
|
.directory
|
||||||
*.lib
|
*.debug
|
||||||
|
Makefile*
|
||||||
# Executables
|
*.prl
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
CMakeLists.txt.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
build
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
|
project(rktwebview LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(QT_DEBUG_FIND_PACKAGE ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
||||||
|
|
||||||
|
add_library(rktwebview SHARED
|
||||||
|
rktwebview_global.h
|
||||||
|
rktwebview.h
|
||||||
|
rktwebview.cpp
|
||||||
|
shm.h shm.cpp
|
||||||
|
shmqueue.h shmqueue.cpp
|
||||||
|
rkt_protocol.h
|
||||||
|
rktwebview_types.h
|
||||||
|
json.cpp json.h
|
||||||
|
utils.h
|
||||||
|
utils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(rktwebview_prg
|
||||||
|
main.cpp
|
||||||
|
|
||||||
|
rktwebview_qt.cpp
|
||||||
|
rktwebview_qt.h
|
||||||
|
|
||||||
|
webviewqt.h webviewqt.cpp
|
||||||
|
webviewwindow.h webviewwindow.cpp
|
||||||
|
|
||||||
|
rktutils.h rktutils.cpp
|
||||||
|
command.h command.cpp
|
||||||
|
shm.h shm.cpp
|
||||||
|
shmqueue.h shmqueue.cpp
|
||||||
|
|
||||||
|
rkt_protocol.h
|
||||||
|
rktwebview_types.h
|
||||||
|
utils.cpp utils.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(rktwebview_test
|
||||||
|
rktwebview_test.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(rktwebview_prg PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||||
|
target_link_libraries(rktwebview_prg PRIVATE Qt${QT_VERSION_MAJOR}::WebEngineWidgets)
|
||||||
|
|
||||||
|
target_compile_definitions(rktwebview PRIVATE RKTWEBVIEW_LIBRARY)
|
||||||
|
|
||||||
|
target_link_Libraries(rktwebview_test PRIVATE rktwebview)
|
||||||
|
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#include "command.h"
|
||||||
|
|
||||||
|
|
||||||
|
Command::Command(int _cmd)
|
||||||
|
{
|
||||||
|
cmd = _cmd;
|
||||||
|
done = false;
|
||||||
|
js_result_ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Command *CommandEvent::cmd()
|
||||||
|
{
|
||||||
|
return _cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandEvent::CommandEvent(Command *c)
|
||||||
|
: QEvent(COMMAND_EVENT)
|
||||||
|
{
|
||||||
|
_cmd = c;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#ifndef COMMAND_H
|
||||||
|
#define COMMAND_H
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#define COMMAND_QUIT 1
|
||||||
|
#define COMMAND_CLOSE 2
|
||||||
|
#define COMMAND_CREATE 3
|
||||||
|
#define COMMAND_SET_URL 4
|
||||||
|
#define COMMAND_SET_HTML 5
|
||||||
|
#define COMMAND_RUN_JS 6
|
||||||
|
#define COMMAND_DEV_TOOLS 7
|
||||||
|
#define COMMAND_MOVE 8
|
||||||
|
#define COMMAND_RESIZE 9
|
||||||
|
#define COMMAND_CALL_JS 10
|
||||||
|
#define COMMAND_HIDE_WIN 11
|
||||||
|
#define COMMAND_SHOW_WIN 12
|
||||||
|
#define COMMAND_MAX_WIN 13
|
||||||
|
#define COMMAND_MIN_WIN 14
|
||||||
|
#define COMMAND_PRESENT_WIN 15
|
||||||
|
#define COMMAND_SHOW_NORMAL_WIN 16
|
||||||
|
#define COMMAND_WINDOW_STATUS 17
|
||||||
|
#define COMMAND_SET_TITLE 18
|
||||||
|
#define COMMAND_CHOOSE_DIR 19
|
||||||
|
#define COMMAND_FILE_OPEN 20
|
||||||
|
#define COMMAND_FILE_SAVE 21
|
||||||
|
#define COMMAND_SET_OU_TOKEN 22
|
||||||
|
#define COMMAND_NEW_CONTEXT 23
|
||||||
|
#define COMMAND_MESSAGE 24
|
||||||
|
|
||||||
|
class Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int cmd;
|
||||||
|
QVector<QVariant> args;
|
||||||
|
QVariant result;
|
||||||
|
bool done;
|
||||||
|
bool js_result_ok;
|
||||||
|
public:
|
||||||
|
Command(int _cmd);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CommandEvent : public QEvent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Command *_cmd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Command *cmd();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CommandEvent(Command *c);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const QEvent::Type COMMAND_EVENT = static_cast<QEvent::Type>(QEvent::User + 1);
|
||||||
|
|
||||||
|
#endif // COMMAND_H
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
ARCH=`uname -m`
|
||||||
|
|
||||||
|
LIB="lib/linux/$ARCH"
|
||||||
|
|
||||||
|
mkdir -p $LIB
|
||||||
|
rm -f $LIB/*.so*
|
||||||
|
cp build/Release/*.so $LIB
|
||||||
|
cp build/Release/rktwebview_prg $LIB
|
||||||
|
|
||||||
|
QT_PATH=`ldd build/Release/rktwebview_prg | grep Qt | awk '{print $3}' | head -1 | sed -e 's%[/]lib[/].*%%'`
|
||||||
|
echo "QT_PATH=$QT_PATH"
|
||||||
|
|
||||||
|
QT_PLUGINS="$QT_PATH/plugins"
|
||||||
|
PLUGINS="platforms position generic iconengines imageformats qmltooling tls xcbglintegrations"
|
||||||
|
|
||||||
|
EXTRA_LIBS_SO=`ldd build/Release/rktwebview_prg | grep Qt | awk '{ print $3 }'`
|
||||||
|
EXTRA_LIBS_PLATFORM_PLUGIN_XCB=`ldd $QT_PATH/plugins/platforms/libqxcb.so | grep Qt | awk '{print $3}'`
|
||||||
|
|
||||||
|
for pl in $PLUGINS
|
||||||
|
do
|
||||||
|
echo "Assembling libs for $pl"
|
||||||
|
LIBS=`ls $QT_PLUGINS/$pl | grep so`
|
||||||
|
for ll in $LIBS
|
||||||
|
do
|
||||||
|
l="$QT_PLUGINS/$pl/$ll"
|
||||||
|
ELS=`ldd $l | grep Qt | grep -v no\ version\ information | awk '{print $3}'`
|
||||||
|
EXTRA_LIBS_SO="$EXTRA_LIBS_SO $ELS"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
#echo $EXTRA_LIBS_SO | less
|
||||||
|
|
||||||
|
EXTRA_LIBS=`echo $EXTRA_LIBS_SO $EXTRA_LIBS_PLATFORM_PLUGIN_XCB | sort | uniq`
|
||||||
|
|
||||||
|
for l in $EXTRA_LIBS; do
|
||||||
|
version_so=`basename $l`
|
||||||
|
if [ ! -r "$LIB/$version_so" ]; then
|
||||||
|
echo "Copying $l..."
|
||||||
|
cp $l $LIB
|
||||||
|
so=`echo $version_so | sed -e 's/[.]so.*$//'`
|
||||||
|
lib_so=`echo -n $so; echo ".so"`
|
||||||
|
(cd $LIB; ln -s $version_so $lib_so)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
for p in $PLUGINS
|
||||||
|
do
|
||||||
|
echo "Plugin $p..."
|
||||||
|
(cd $QT_PLUGINS; tar cf - $p) | (cd $LIB; tar xf -)
|
||||||
|
done
|
||||||
|
|
||||||
|
RESOURCES="resources translations"
|
||||||
|
QT_RESOURCES="$QT_PATH"
|
||||||
|
|
||||||
|
for r in $RESOURCES
|
||||||
|
do
|
||||||
|
echo "Resource $r..."
|
||||||
|
(cd $QT_RESOURCES; tar cf - $r) | (cd $LIB; tar xf - )
|
||||||
|
done
|
||||||
|
|
||||||
|
cp $QT_PATH/libexec/QtWebEngineProcess $LIB
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,505 @@
|
|||||||
|
#include "json.h"
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
using std::deque;
|
||||||
|
using std::string;
|
||||||
|
using std::enable_if;
|
||||||
|
using std::initializer_list;
|
||||||
|
using std::is_same;
|
||||||
|
using std::is_convertible;
|
||||||
|
using std::is_integral;
|
||||||
|
using std::is_floating_point;
|
||||||
|
|
||||||
|
std::string json_escape(const string &str) {
|
||||||
|
string output;
|
||||||
|
for( unsigned i = 0; i < str.length(); ++i )
|
||||||
|
switch( str[i] ) {
|
||||||
|
case '\"': output += "\\\""; break;
|
||||||
|
case '\\': output += "\\\\"; break;
|
||||||
|
case '\b': output += "\\b"; break;
|
||||||
|
case '\f': output += "\\f"; break;
|
||||||
|
case '\n': output += "\\n"; break;
|
||||||
|
case '\r': output += "\\r"; break;
|
||||||
|
case '\t': output += "\\t"; break;
|
||||||
|
default : output += str[i]; break;
|
||||||
|
}
|
||||||
|
return std::move( output );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSON() : Internal(), Type( Class::Null ){}
|
||||||
|
|
||||||
|
JSON::JSON(std::initializer_list<JSON> list)
|
||||||
|
: JSON()
|
||||||
|
{
|
||||||
|
SetType( Class::Object );
|
||||||
|
for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i )
|
||||||
|
operator[]( i->toString() ) = *std::next( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSON(JSON &&other)
|
||||||
|
: Internal( other.Internal )
|
||||||
|
, Type( other.Type )
|
||||||
|
{ other.Type = Class::Null; other.Internal.Map = nullptr; }
|
||||||
|
|
||||||
|
JSON::JSON(const JSON &other) {
|
||||||
|
switch( other.Type ) {
|
||||||
|
case Class::Object:
|
||||||
|
Internal.Map =
|
||||||
|
new map<string,JSON>( other.Internal.Map->begin(),
|
||||||
|
other.Internal.Map->end() );
|
||||||
|
break;
|
||||||
|
case Class::Array:
|
||||||
|
Internal.List =
|
||||||
|
new deque<JSON>( other.Internal.List->begin(),
|
||||||
|
other.Internal.List->end() );
|
||||||
|
break;
|
||||||
|
case Class::String:
|
||||||
|
Internal.String =
|
||||||
|
new string( *other.Internal.String );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Internal = other.Internal;
|
||||||
|
}
|
||||||
|
Type = other.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON JSON::Make(Class type) {
|
||||||
|
JSON ret; ret.SetType( type );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::operator[](unsigned int index) {
|
||||||
|
SetType( Class::Array );
|
||||||
|
if( index >= Internal.List->size() ) Internal.List->resize( index + 1 );
|
||||||
|
return Internal.List->operator[]( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::at(const std::string &key) {
|
||||||
|
return operator[]( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
const JSON &JSON::at(const std::string &key) const {
|
||||||
|
return Internal.Map->at( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::at(unsigned int index) {
|
||||||
|
return operator[]( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
const JSON &JSON::at(unsigned int index) const {
|
||||||
|
return Internal.List->at( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
int JSON::length() const {
|
||||||
|
if( Type == Class::Array )
|
||||||
|
return Internal.List->size();
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JSON::hasKey(const std::string &key) const {
|
||||||
|
if( Type == Class::Object )
|
||||||
|
return Internal.Map->find( key ) != Internal.Map->end();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JSON::size() const {
|
||||||
|
if( Type == Class::Object )
|
||||||
|
return Internal.Map->size();
|
||||||
|
else if( Type == Class::Array )
|
||||||
|
return Internal.List->size();
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::Class JSON::JSONType() const { return Type; }
|
||||||
|
|
||||||
|
bool JSON::IsNull() const { return Type == Class::Null; }
|
||||||
|
|
||||||
|
string JSON::toString() const { bool b; return std::move( toString( b ) ); }
|
||||||
|
|
||||||
|
string JSON::toString(bool &ok) const {
|
||||||
|
ok = (Type == Class::String);
|
||||||
|
return ok ? std::move( json_escape( *Internal.String ) ): string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
double JSON::toFloat() const { bool b; return toFloat( b ); }
|
||||||
|
|
||||||
|
double JSON::toFloat(bool &ok) const {
|
||||||
|
ok = (Type == Class::Floating);
|
||||||
|
return ok ? Internal.Float : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long JSON::toInt() const { bool b; return toInt( b ); }
|
||||||
|
|
||||||
|
long JSON::toInt(bool &ok) const {
|
||||||
|
ok = (Type == Class::Integral);
|
||||||
|
return ok ? Internal.Int : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JSON::toBool() const { bool b; return toBool( b ); }
|
||||||
|
|
||||||
|
bool JSON::toBool(bool &ok) const {
|
||||||
|
ok = (Type == Class::Boolean);
|
||||||
|
return ok ? Internal.Bool : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSONWrapper<std::map<string, JSON> > JSON::ObjectRange() {
|
||||||
|
if( Type == Class::Object )
|
||||||
|
return JSONWrapper<std::map<std::string,JSON>>( Internal.Map );
|
||||||
|
return JSONWrapper<std::map<std::string,JSON>>( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSONWrapper<std::deque<JSON> > JSON::ArrayRange() {
|
||||||
|
if( Type == Class::Array )
|
||||||
|
return JSONWrapper<std::deque<JSON>>( Internal.List );
|
||||||
|
return JSONWrapper<std::deque<JSON>>( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSONConstWrapper<std::map<string, JSON> > JSON::ObjectRange() const {
|
||||||
|
if( Type == Class::Object )
|
||||||
|
return JSONConstWrapper<std::map<std::string,JSON>>( Internal.Map );
|
||||||
|
return JSONConstWrapper<std::map<std::string,JSON>>( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::JSONConstWrapper<std::deque<JSON> > JSON::ArrayRange() const {
|
||||||
|
if( Type == Class::Array )
|
||||||
|
return JSONConstWrapper<std::deque<JSON>>( Internal.List );
|
||||||
|
return JSONConstWrapper<std::deque<JSON>>( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
string JSON::dump(int depth, const std::string &tab) const {
|
||||||
|
std::string pad = "";
|
||||||
|
for( int i = 0; i < depth; ++i, pad += tab );
|
||||||
|
|
||||||
|
switch( Type ) {
|
||||||
|
case Class::Null:
|
||||||
|
return "null";
|
||||||
|
case Class::Object: {
|
||||||
|
std::string s = "{ ";
|
||||||
|
bool skip = true;
|
||||||
|
for( auto &p : *Internal.Map ) {
|
||||||
|
if( !skip ) s += ", ";
|
||||||
|
s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||||
|
skip = false;
|
||||||
|
}
|
||||||
|
s += ( " " + pad.erase( 0, 2 ) + "}" ) ;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
case Class::Array: {
|
||||||
|
std::string s = "[";
|
||||||
|
bool skip = true;
|
||||||
|
for( auto &p : *Internal.List ) {
|
||||||
|
if( !skip ) s += ", ";
|
||||||
|
s += p.dump( depth + 1, tab );
|
||||||
|
skip = false;
|
||||||
|
}
|
||||||
|
s += "]";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
case Class::String:
|
||||||
|
return "\"" + json_escape( *Internal.String ) + "\"";
|
||||||
|
case Class::Floating:
|
||||||
|
return std::to_string( Internal.Float );
|
||||||
|
case Class::Integral:
|
||||||
|
return std::to_string( Internal.Int );
|
||||||
|
case Class::Boolean:
|
||||||
|
return Internal.Bool ? "true" : "false";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void JSON::SetType(Class type) {
|
||||||
|
if( type == Type )
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClearInternal();
|
||||||
|
|
||||||
|
switch( type ) {
|
||||||
|
case Class::Null: Internal.Map = nullptr; break;
|
||||||
|
case Class::Object: Internal.Map = new std::map<std::string,JSON>(); break;
|
||||||
|
case Class::Array: Internal.List = new std::deque<JSON>(); break;
|
||||||
|
case Class::String: Internal.String = new std::string(); break;
|
||||||
|
case Class::Floating: Internal.Float = 0.0; break;
|
||||||
|
case Class::Integral: Internal.Int = 0; break;
|
||||||
|
case Class::Boolean: Internal.Bool = false; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JSON::ClearInternal() {
|
||||||
|
switch( Type ) {
|
||||||
|
case Class::Object: delete Internal.Map; break;
|
||||||
|
case Class::Array: delete Internal.List; break;
|
||||||
|
case Class::String: delete Internal.String; break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::operator[](const std::string &key) {
|
||||||
|
SetType( Class::Object ); return Internal.Map->operator[]( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::operator=(const JSON &other) {
|
||||||
|
|
||||||
|
if (&other == this) { return *this; }
|
||||||
|
|
||||||
|
ClearInternal();
|
||||||
|
switch( other.Type ) {
|
||||||
|
case Class::Object:
|
||||||
|
Internal.Map =
|
||||||
|
new map<string,JSON>( other.Internal.Map->begin(),
|
||||||
|
other.Internal.Map->end() );
|
||||||
|
break;
|
||||||
|
case Class::Array:
|
||||||
|
Internal.List =
|
||||||
|
new deque<JSON>( other.Internal.List->begin(),
|
||||||
|
other.Internal.List->end() );
|
||||||
|
break;
|
||||||
|
case Class::String:
|
||||||
|
Internal.String =
|
||||||
|
new string( *other.Internal.String );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Internal = other.Internal;
|
||||||
|
}
|
||||||
|
Type = other.Type;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON &JSON::operator=(JSON &&other) {
|
||||||
|
ClearInternal();
|
||||||
|
Internal = other.Internal;
|
||||||
|
Type = other.Type;
|
||||||
|
other.Internal.Map = nullptr;
|
||||||
|
other.Type = Class::Null;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON Array() {
|
||||||
|
return std::move( JSON::Make( JSON::Class::Array ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//JSON Object() { return std::move(JSON::Make(JSON::Class::Object)); }
|
||||||
|
|
||||||
|
JSON Object() {
|
||||||
|
return std::move( JSON::Make( JSON::Class::Object ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const JSON &json) {
|
||||||
|
os << json.dump();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private functions.
|
||||||
|
|
||||||
|
static JSON parse_next( const std::string &, size_t &, std::function<void(const std::string &err)> );
|
||||||
|
|
||||||
|
|
||||||
|
static void consume_ws( const std::string &str, size_t &offset ) {
|
||||||
|
while( isspace( str[offset] ) ) ++offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_object( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON Object = JSON::Make( JSON::Class::Object );
|
||||||
|
|
||||||
|
++offset;
|
||||||
|
consume_ws( str, offset );
|
||||||
|
if( str[offset] == '}' ) {
|
||||||
|
++offset; return std::move( Object );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( true ) {
|
||||||
|
JSON Key = parse_next( str, offset, on_error );
|
||||||
|
consume_ws( str, offset );
|
||||||
|
if( str[offset] != ':' ) {
|
||||||
|
on_error(std::string("Error: Object: Expected colon, found '") + str[offset] + "'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
consume_ws( str, ++offset );
|
||||||
|
JSON Value = parse_next( str, offset, on_error );
|
||||||
|
Object[Key.toString()] = Value;
|
||||||
|
|
||||||
|
consume_ws( str, offset );
|
||||||
|
if( str[offset] == ',' ) {
|
||||||
|
++offset; continue;
|
||||||
|
}
|
||||||
|
else if( str[offset] == '}' ) {
|
||||||
|
++offset; break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
on_error(std::string("ERROR: Object: Expected comma, found '") + str[offset] + "'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move( Object );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_array( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON Array = JSON::Make( JSON::Class::Array );
|
||||||
|
unsigned index = 0;
|
||||||
|
|
||||||
|
++offset;
|
||||||
|
consume_ws( str, offset );
|
||||||
|
if( str[offset] == ']' ) {
|
||||||
|
++offset; return std::move( Array );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( true ) {
|
||||||
|
Array[index++] = parse_next( str, offset, on_error );
|
||||||
|
consume_ws( str, offset );
|
||||||
|
|
||||||
|
if( str[offset] == ',' ) {
|
||||||
|
++offset; continue;
|
||||||
|
}
|
||||||
|
else if( str[offset] == ']' ) {
|
||||||
|
++offset; break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
on_error(std::string("ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'");
|
||||||
|
return std::move( JSON::Make( JSON::Class::Array ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move( Array );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_string( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON String;
|
||||||
|
string val;
|
||||||
|
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) {
|
||||||
|
if( c == '\\' ) {
|
||||||
|
switch( str[ ++offset ] ) {
|
||||||
|
case '\"': val += '\"'; break;
|
||||||
|
case '\\': val += '\\'; break;
|
||||||
|
case '/' : val += '/' ; break;
|
||||||
|
case 'b' : val += '\b'; break;
|
||||||
|
case 'f' : val += '\f'; break;
|
||||||
|
case 'n' : val += '\n'; break;
|
||||||
|
case 'r' : val += '\r'; break;
|
||||||
|
case 't' : val += '\t'; break;
|
||||||
|
case 'u' : {
|
||||||
|
val += "\\u" ;
|
||||||
|
for( unsigned i = 1; i <= 4; ++i ) {
|
||||||
|
c = str[offset+i];
|
||||||
|
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
|
||||||
|
val += c;
|
||||||
|
else {
|
||||||
|
on_error(std::string("ERROR: String: Expected hex character in unicode escape, found '") + c + "'");
|
||||||
|
return std::move( JSON::Make( JSON::Class::String ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += 4;
|
||||||
|
} break;
|
||||||
|
default : val += '\\'; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
val += c;
|
||||||
|
}
|
||||||
|
++offset;
|
||||||
|
String = val;
|
||||||
|
return std::move( String );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_number( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON Number;
|
||||||
|
string val, exp_str;
|
||||||
|
char c;
|
||||||
|
bool isDouble = false;
|
||||||
|
long exp = 0;
|
||||||
|
while( true ) {
|
||||||
|
c = str[offset++];
|
||||||
|
if( (c == '-') || (c >= '0' && c <= '9') )
|
||||||
|
val += c;
|
||||||
|
else if( c == '.' ) {
|
||||||
|
val += c;
|
||||||
|
isDouble = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( c == 'E' || c == 'e' ) {
|
||||||
|
c = str[ offset++ ];
|
||||||
|
if( c == '-' ){ ++offset; exp_str += '-';}
|
||||||
|
while( true ) {
|
||||||
|
c = str[ offset++ ];
|
||||||
|
if( c >= '0' && c <= '9' )
|
||||||
|
exp_str += c;
|
||||||
|
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||||
|
on_error(std::string("ERROR: Number: Expected a number for exponent, found '") + c + "'");
|
||||||
|
return std::move( JSON::Make( JSON::Class::Null ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exp = std::stol( exp_str );
|
||||||
|
}
|
||||||
|
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
|
||||||
|
on_error(std::string("ERROR: Number: unexpected character '") + c + "'");
|
||||||
|
return std::move( JSON::Make( JSON::Class::Null ) );
|
||||||
|
}
|
||||||
|
--offset;
|
||||||
|
|
||||||
|
if( isDouble )
|
||||||
|
Number = std::stod( val ) * std::pow( 10, exp );
|
||||||
|
else {
|
||||||
|
if( !exp_str.empty() )
|
||||||
|
Number = std::stol( val ) * std::pow( 10, exp );
|
||||||
|
else
|
||||||
|
Number = std::stol( val );
|
||||||
|
}
|
||||||
|
return std::move( Number );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_bool( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON Bool;
|
||||||
|
if( str.substr( offset, 4 ) == "true" )
|
||||||
|
Bool = true;
|
||||||
|
else if( str.substr( offset, 5 ) == "false" )
|
||||||
|
Bool = false;
|
||||||
|
else {
|
||||||
|
on_error(std::string("ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'");
|
||||||
|
return std::move( JSON::Make( JSON::Class::Null ) );
|
||||||
|
}
|
||||||
|
offset += (Bool.toBool() ? 4 : 5);
|
||||||
|
return std::move( Bool );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_null( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
JSON Null;
|
||||||
|
if( str.substr( offset, 4 ) != "null" ) {
|
||||||
|
on_error(std::string("ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'" );
|
||||||
|
return std::move( JSON::Make( JSON::Class::Null ) );
|
||||||
|
}
|
||||||
|
offset += 4;
|
||||||
|
return std::move( Null );
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON parse_next( const string &str, size_t &offset, std::function<void(const std::string &err)> on_error ) {
|
||||||
|
char value;
|
||||||
|
consume_ws( str, offset );
|
||||||
|
value = str[offset];
|
||||||
|
switch( value ) {
|
||||||
|
case '[' : return std::move( parse_array( str, offset, on_error ) );
|
||||||
|
case '{' : return std::move( parse_object( str, offset, on_error ) );
|
||||||
|
case '\"': return std::move( parse_string( str, offset, on_error ) );
|
||||||
|
case 't' :
|
||||||
|
case 'f' : return std::move( parse_bool( str, offset, on_error ) );
|
||||||
|
case 'n' : return std::move( parse_null( str, offset, on_error ) );
|
||||||
|
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
|
||||||
|
return std::move( parse_number( str, offset, on_error ) );
|
||||||
|
}
|
||||||
|
on_error(std::string("ERROR: Parse: Unknown starting character '") + value + "'");
|
||||||
|
return JSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON JSON::Load( const string &str, std::function<void(const std::string &err)> on_error) {
|
||||||
|
size_t offset = 0;
|
||||||
|
return std::move( parse_next( str, offset, on_error ) );
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
#ifndef JSON_H
|
||||||
|
#define JSON_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cctype>
|
||||||
|
#include <string>
|
||||||
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <ostream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
std::string json_escape( const std::string &str );
|
||||||
|
|
||||||
|
class JSON
|
||||||
|
{
|
||||||
|
union BackingData {
|
||||||
|
BackingData( double d ) : Float( d ){}
|
||||||
|
BackingData( long l ) : Int( l ){}
|
||||||
|
BackingData( bool b ) : Bool( b ){}
|
||||||
|
BackingData( std::string s ) : String( new std::string( s ) ){}
|
||||||
|
BackingData() : Int( 0 ){}
|
||||||
|
|
||||||
|
std::deque<JSON> *List;
|
||||||
|
std::map<std::string,JSON> *Map;
|
||||||
|
std::string *String;
|
||||||
|
double Float;
|
||||||
|
long Int;
|
||||||
|
bool Bool;
|
||||||
|
} Internal;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class Class {
|
||||||
|
Null,
|
||||||
|
Object,
|
||||||
|
Array,
|
||||||
|
String,
|
||||||
|
Floating,
|
||||||
|
Integral,
|
||||||
|
Boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
class JSONWrapper {
|
||||||
|
Container *object;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JSONWrapper( Container *val ) : object( val ) {}
|
||||||
|
JSONWrapper( std::nullptr_t ) : object( nullptr ) {}
|
||||||
|
|
||||||
|
typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); }
|
||||||
|
typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); }
|
||||||
|
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); }
|
||||||
|
typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
class JSONConstWrapper {
|
||||||
|
const Container *object;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JSONConstWrapper( const Container *val ) : object( val ) {}
|
||||||
|
JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {}
|
||||||
|
|
||||||
|
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
|
||||||
|
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
JSON();
|
||||||
|
JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){}
|
||||||
|
JSON( std::initializer_list<JSON> list );
|
||||||
|
JSON( JSON&& other );
|
||||||
|
JSON( const JSON &other );
|
||||||
|
|
||||||
|
JSON& operator=( const JSON &other );
|
||||||
|
JSON& operator=( JSON&& other );
|
||||||
|
|
||||||
|
// Template T constructors
|
||||||
|
template <typename T>
|
||||||
|
JSON( T b, typename std::enable_if<std::is_same<T,bool>::value>::type* = 0 );
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
JSON( T i, typename std::enable_if<std::is_integral<T>::value && !std::is_same<T,bool>::value>::type* = 0 );
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
JSON( T f, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0 );
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
JSON( T s, typename std::enable_if<std::is_convertible<T, std::string>::value>::type* = 0 );
|
||||||
|
|
||||||
|
~JSON() {
|
||||||
|
switch( Type ) {
|
||||||
|
case Class::Array:
|
||||||
|
delete Internal.List;
|
||||||
|
break;
|
||||||
|
case Class::Object:
|
||||||
|
delete Internal.Map;
|
||||||
|
break;
|
||||||
|
case Class::String:
|
||||||
|
delete Internal.String;
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSON Make( Class type );
|
||||||
|
static JSON Load( const std::string &, std::function<void(const std::string &err)> );
|
||||||
|
|
||||||
|
// Appending things.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void append( T arg ) {
|
||||||
|
SetType( Class::Array ); Internal.List->emplace_back( arg );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... U>
|
||||||
|
void append( T arg, U... args ) {
|
||||||
|
append( arg ); append( args... );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignments (template T).
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_same<T,bool>::value, JSON&>::type operator=( T b ) {
|
||||||
|
SetType( Class::Boolean ); Internal.Bool = b; return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value && !std::is_same<T,bool>::value, JSON&>::type operator=( T i ) {
|
||||||
|
SetType( Class::Integral ); Internal.Int = i; return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, JSON&>::type operator=( T f ) {
|
||||||
|
SetType( Class::Floating ); Internal.Float = f; return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_convertible<T, std::string>::value, JSON&>::type operator=( T s ) {
|
||||||
|
SetType( Class::String ); *Internal.String = std::string( s ); return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Indexing.
|
||||||
|
JSON& operator[]( const std::string &key );
|
||||||
|
JSON& operator[]( unsigned index );
|
||||||
|
|
||||||
|
JSON &at( const std::string &key );
|
||||||
|
const JSON &at( const std::string &key ) const;
|
||||||
|
JSON &at( unsigned index );
|
||||||
|
const JSON &at( unsigned index ) const;
|
||||||
|
|
||||||
|
int length() const;
|
||||||
|
int size() const;
|
||||||
|
|
||||||
|
bool hasKey( const std::string &key ) const;
|
||||||
|
|
||||||
|
Class JSONType() const;
|
||||||
|
|
||||||
|
/// Functions for getting primitives from the JSON object.
|
||||||
|
bool IsNull() const;
|
||||||
|
|
||||||
|
std::string toString() const;
|
||||||
|
std::string toString( bool &ok ) const;
|
||||||
|
|
||||||
|
double toFloat() const;
|
||||||
|
double toFloat( bool &ok ) const;
|
||||||
|
|
||||||
|
long toInt() const;
|
||||||
|
long toInt( bool &ok ) const;
|
||||||
|
|
||||||
|
bool toBool() const;
|
||||||
|
bool toBool( bool &ok ) const;
|
||||||
|
|
||||||
|
JSONWrapper<std::map<std::string,JSON>> ObjectRange();
|
||||||
|
JSONWrapper<std::deque<JSON>> ArrayRange();
|
||||||
|
JSONConstWrapper<std::map<std::string,JSON>> ObjectRange() const;
|
||||||
|
JSONConstWrapper<std::deque<JSON>> ArrayRange() const;
|
||||||
|
|
||||||
|
std::string dump( int depth = 1, const std::string &tab = std::string(" ")) const;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<( std::ostream&, const JSON & );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetType( Class type );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* beware: only call if YOU know that Internal is allocated. No checks performed here.
|
||||||
|
This function should be called in a constructed JSON just before you are going to
|
||||||
|
overwrite Internal...
|
||||||
|
*/
|
||||||
|
void ClearInternal();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Class Type = Class::Null;
|
||||||
|
};
|
||||||
|
|
||||||
|
JSON Array();
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
JSON Array( T... args ) {
|
||||||
|
JSON arr = JSON::Make( JSON::Class::Array );
|
||||||
|
arr.append( args... );
|
||||||
|
return std::move( arr );
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON Object();
|
||||||
|
|
||||||
|
std::ostream& operator<<( std::ostream &os, const JSON &json );
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_H
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,48 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "qtbase",
|
||||||
|
"repositories": ["qtbase", "qtactiveqt", "qtimageformats"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtdeclarative",
|
||||||
|
"repositories": ["qtdeclarative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtmultimedia",
|
||||||
|
"repositories": ["qtmultimedia"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtconnectivity",
|
||||||
|
"repositories": ["qtconnectivity"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtlocation",
|
||||||
|
"repositories": ["qtlocation"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtwebsockets",
|
||||||
|
"repositories": ["qtwebsockets"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtserialport",
|
||||||
|
"repositories": ["qtserialport"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qtwebengine",
|
||||||
|
"repositories": ["qtwebengine"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "designer",
|
||||||
|
"modules": ["Designer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linguist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "assistant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qt_help",
|
||||||
|
"modules": ["Help"]
|
||||||
|
}
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user