ledok
This commit is contained in:
parent
0cb71807e6
commit
2cfa0cc514
|
@ -0,0 +1,2 @@
|
|||
//#include "cu.h"
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
#ifndef CU_H
|
||||
#define CU_H
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
inline long long steady_milli() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
inline long long system_milli() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
inline long long steady_micro() {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
inline long long system_micro() {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
struct SharedData {
|
||||
T data;
|
||||
uint64_t cnt{1};
|
||||
};
|
||||
template <class T>
|
||||
class SharedPtr {
|
||||
public:
|
||||
SharedPtr(SharedData<T> *ptr = 0) : ptr{ptr} {}
|
||||
SharedPtr(const SharedPtr &other) : ptr{other.ptr} {
|
||||
if(ptr) ptr->cnt++;
|
||||
}
|
||||
~SharedPtr() {
|
||||
if(ptr==0) return;
|
||||
if(ptr->cnt > 1) ptr->cnt--;
|
||||
else delete ptr;
|
||||
}
|
||||
|
||||
bool isNull() {return ptr==0;}
|
||||
SharedPtr &operator=(const SharedPtr &other) {
|
||||
this->~SharedPtr();
|
||||
new (this) SharedPtr(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator*() {
|
||||
if(ptr==0) ptr = new SharedData<T>;
|
||||
return ptr->data;
|
||||
}
|
||||
T *operator->() {
|
||||
if(ptr==0) ptr = new SharedData<T>;
|
||||
return &ptr->data;
|
||||
}
|
||||
const T &operator*() const {
|
||||
return ptr->data;
|
||||
}
|
||||
const T *operator->() const {
|
||||
return &ptr->data;
|
||||
}
|
||||
SharedData<T> *ptr{0};
|
||||
};
|
||||
|
||||
|
||||
template <class V>
|
||||
class Vector : public SharedPtr<std::vector<V>> {
|
||||
public:
|
||||
using SharedPtr<std::vector<V>>::SharedPtr;
|
||||
|
||||
using iterator = std::_Vector_iterator<std::_Vector_val<std::_Simple_types<V>>>;
|
||||
using const_iterator = std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<V>>>;
|
||||
|
||||
Vector(std::initializer_list<V> _Ilist) {
|
||||
this->ptr = new SharedData<std::vector<V>>{_Ilist, 1};
|
||||
}
|
||||
|
||||
bool empty() const noexcept {
|
||||
return this->ptr ? this->ptr->data.empty() : true;
|
||||
}
|
||||
uint64_t size() const noexcept {
|
||||
return this->ptr ? this->ptr->data.size() : 0;
|
||||
}
|
||||
Vector &append(const V &val) {
|
||||
(**this).push_back(val);
|
||||
return *this;
|
||||
}
|
||||
V &operator[](const uint64_t pos) noexcept {
|
||||
return (**this)[pos];
|
||||
}
|
||||
const V &operator[](const uint64_t pos) const noexcept {
|
||||
return this->ptr ? this->ptr->data[pos] : V();
|
||||
}
|
||||
const const_iterator begin() const noexcept {
|
||||
return this->ptr ? this->ptr->data.begin() : const_iterator();
|
||||
}
|
||||
const const_iterator end() const noexcept {
|
||||
return this->ptr ? this->ptr->data.end() : const_iterator();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct NodeBase {
|
||||
NodeBase *next{this};
|
||||
NodeBase *prev{this};
|
||||
};
|
||||
template <class V>
|
||||
struct _Node : NodeBase {
|
||||
V value;
|
||||
~_Node() {
|
||||
if(next) delete (_Node<V>*) next;
|
||||
}
|
||||
};
|
||||
|
||||
template <class V>
|
||||
class LinkedMapIterator {
|
||||
public:
|
||||
LinkedMapIterator(_Node<V> *node) : node(node) {}
|
||||
bool operator==(const LinkedMapIterator& that) const {
|
||||
return node == that.node;
|
||||
}
|
||||
bool operator!=(const LinkedMapIterator& that) const {
|
||||
return node != that.node;
|
||||
}
|
||||
LinkedMapIterator& operator++() {
|
||||
node = (_Node<V>*) node->next;
|
||||
return *this;
|
||||
}
|
||||
LinkedMapIterator& operator--() {
|
||||
node = (_Node<V>*) node->prev;
|
||||
return *this;
|
||||
}
|
||||
V &operator*() const {
|
||||
return node->value;
|
||||
}
|
||||
V *operator->() const {
|
||||
return &node->value;
|
||||
}
|
||||
_Node<V> *node{0};
|
||||
};
|
||||
|
||||
template <class K, class V>
|
||||
struct LinkedMapPri : NodeBase {
|
||||
std::unordered_map<K, _Node<std::pair<K, V>>*> map;
|
||||
uint64_t cnt{1};
|
||||
~LinkedMapPri() {
|
||||
if(prev) prev->next = 0;
|
||||
if(next) delete (_Node<std::pair<K, V>>*) next;
|
||||
}
|
||||
};
|
||||
template <class K, class V>
|
||||
class LinkedMap {
|
||||
public:
|
||||
using Node = _Node<std::pair<K, V>>;
|
||||
|
||||
using iterator = LinkedMapIterator<std::pair<K, V>>;
|
||||
using const_iterator = LinkedMapIterator<std::pair<K, V>>;
|
||||
|
||||
LinkedMap() {}
|
||||
LinkedMap(std::initializer_list<std::pair<K, V>> pairs) : _pri{new LinkedMapPri<K, V>} {
|
||||
for(auto pair : pairs) insert(pair.first, pair.second);
|
||||
}
|
||||
LinkedMap(std::unordered_map<K, Node*> &&map) : _pri{new LinkedMapPri<K, V>{0, 0, map}} {
|
||||
_pri->next = _pri->prev = _pri;
|
||||
}
|
||||
LinkedMap(const LinkedMap &other) : _pri{other._pri} {
|
||||
if(_pri) _pri->cnt++;
|
||||
}
|
||||
~LinkedMap() {
|
||||
if(_pri==0) return;
|
||||
if(_pri->cnt > 1) _pri->cnt--;
|
||||
else delete _pri;
|
||||
}
|
||||
|
||||
LinkedMap &operator=(const LinkedMap &other) {
|
||||
this->~LinkedMap();
|
||||
new (this) LinkedMap(other);
|
||||
return *this;
|
||||
}
|
||||
const V operator[](const K &k) const {
|
||||
if(_pri==0) return V();
|
||||
auto it = _pri->map.find(k);
|
||||
if(it==_pri->map.end()) return V();
|
||||
return it->second->value.second;
|
||||
}
|
||||
LinkedMap &insert(const K &k, const V &v) {
|
||||
if(_pri==0) _pri = new LinkedMapPri<K, V>;
|
||||
auto pair = _pri->map.emplace(k, nullptr);
|
||||
if(pair.second) {
|
||||
auto node = new Node{_pri, _pri->prev, {k, v}};
|
||||
_pri->prev->next = node;
|
||||
_pri->prev = node;
|
||||
pair.first->second = node;
|
||||
} else pair.first->second->value.second = v;
|
||||
return *this;
|
||||
}
|
||||
void erase(const K& k) {
|
||||
if(_pri==0) return;
|
||||
auto it = _pri->map.find(k);
|
||||
if(it==_pri->map.end()) return;
|
||||
auto node = it->second;
|
||||
_pri->map.erase(it);
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
node->next = 0;
|
||||
node->prev = 0;
|
||||
delete node;
|
||||
}
|
||||
inline bool empty() const {
|
||||
return _pri==0 || _pri->map.empty();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator((Node*) (_pri ? _pri->next : 0));
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator((Node*) _pri);
|
||||
}
|
||||
LinkedMapPri<K, V> *_pri{0};
|
||||
};
|
||||
|
||||
#endif // CU_H
|
|
@ -62,17 +62,13 @@ public:
|
|||
inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) {
|
||||
parent->addLayout(this);
|
||||
};
|
||||
inline VBox(QStackedLayout *parent) : QBoxLayout(TopToBottom) {
|
||||
inline VBox(QStackedLayout *stack) : QBoxLayout(TopToBottom, new QWidget) {
|
||||
stack->addWidget(parentWidget());
|
||||
setContentsMargins(0,0,0,0);
|
||||
auto wgt = new QWidget;
|
||||
wgt->setLayout(this);
|
||||
parent->addWidget(wgt);
|
||||
};
|
||||
inline VBox(QSplitter *parent) : QBoxLayout(TopToBottom) {
|
||||
inline VBox(QSplitter *splitter) : QBoxLayout(TopToBottom, new QWidget) {
|
||||
splitter->addWidget(parentWidget());
|
||||
setContentsMargins(0,0,0,0);
|
||||
auto wgt = new QWidget;
|
||||
wgt->setLayout(this);
|
||||
parent->addWidget(wgt);
|
||||
};
|
||||
inline QLabel *addLabel(const QString &text) {
|
||||
auto lb = new QLabel(text);
|
||||
|
@ -86,17 +82,13 @@ public:
|
|||
inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) {
|
||||
parent->addLayout(this);
|
||||
};
|
||||
inline HBox(QStackedLayout *parent) : QBoxLayout(LeftToRight) {
|
||||
inline HBox(QStackedLayout *stack) : QBoxLayout(LeftToRight, new QWidget) {
|
||||
stack->addWidget(parentWidget());
|
||||
setContentsMargins(0,0,0,0);
|
||||
auto wgt = new QWidget;
|
||||
wgt->setLayout(this);
|
||||
parent->addWidget(wgt);
|
||||
};
|
||||
inline HBox(QSplitter *parent) : QBoxLayout(LeftToRight) {
|
||||
inline HBox(QSplitter *splitter) : QBoxLayout(LeftToRight, new QWidget) {
|
||||
splitter->addWidget(parentWidget());
|
||||
setContentsMargins(0,0,0,0);
|
||||
auto wgt = new QWidget;
|
||||
wgt->setLayout(this);
|
||||
parent->addWidget(wgt);
|
||||
};
|
||||
inline QLabel *addLabel(const QString &text) {
|
||||
auto lb = new QLabel(text);
|
||||
|
@ -110,11 +102,17 @@ public:
|
|||
inline Grid(QBoxLayout *parent) {
|
||||
parent->addLayout(this);
|
||||
};
|
||||
inline Grid(QStackedLayout *parent) {
|
||||
auto wgt = new QWidget;
|
||||
wgt->setLayout(this);
|
||||
parent->addWidget(wgt);
|
||||
inline Grid(QStackedLayout *stack) : QGridLayout(new QWidget) {
|
||||
stack->addWidget(parentWidget());
|
||||
};
|
||||
inline Grid(QSplitter *splitter) : QGridLayout(new QWidget) {
|
||||
splitter->addWidget(parentWidget());
|
||||
};
|
||||
inline QLabel *addLabel(const QString &text) {
|
||||
auto lb = new QLabel(text);
|
||||
addWidget(lb);
|
||||
return lb;
|
||||
}
|
||||
};
|
||||
|
||||
class ListWgt : public QListWidget {
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
#include "qjson.h"
|
||||
|
||||
inline QChar readOne(QTextStream &in) {
|
||||
QChar ch;
|
||||
in >> ch;
|
||||
return ch;
|
||||
}
|
||||
JValue JParser::readValue() {
|
||||
if(ch=='{') {
|
||||
JObj obj;
|
||||
while(true) {
|
||||
do skipSpace(); //ch有三种可能
|
||||
while(ch==',');
|
||||
if(ch=='}') return obj;
|
||||
QString key;
|
||||
if(ch == '"') key = readStr();
|
||||
else if(ch!='n' || in.read(3)!="ull") throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting double-quote to start field name or null";
|
||||
skipSpace();
|
||||
if(ch != ':') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting a colon to separate field name and value";
|
||||
skipSpace();
|
||||
obj.insert(key, readValue());
|
||||
skipSpace(); //ch有两种可能
|
||||
if(ch=='}') return obj;
|
||||
if(ch!=',') throw QString("Unexpected char ")+ch+"' (code "+ch+"): was expecting } to end Object or comma to separate Object entries";
|
||||
}
|
||||
}
|
||||
if(ch=='[') {
|
||||
JArray list;
|
||||
while(true) {
|
||||
do skipSpace(); //ch有三种可能
|
||||
while(ch==',');
|
||||
if(ch==']') return list;
|
||||
list->push_back(readValue());
|
||||
skipSpace(); //ch有两种可能
|
||||
if(ch==']') return list;
|
||||
if(ch!=',') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting ] to end Array or comma to separate Array entries";
|
||||
}
|
||||
}
|
||||
if(ch=='"') return readStr();
|
||||
if((ch>='0' && ch<='9') || ch=='-') {
|
||||
QString buf;
|
||||
buf += ch;
|
||||
bool isInt = true;
|
||||
while(0 != (ch = readOne(in))) {
|
||||
if((ch>'*' && ch<':' && ch!=',' && ch!='/') || ch=='e' || ch=='E') {
|
||||
buf.append(ch);
|
||||
if(isInt && ch=='.') isInt = false;
|
||||
} else {
|
||||
bk = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool ok;
|
||||
if(isInt) {
|
||||
auto num = buf.toLongLong(&ok);
|
||||
if(! ok) throw "Illegal number: "+buf;
|
||||
return num;
|
||||
} else {
|
||||
auto num = buf.toDouble(&ok);
|
||||
if(! ok) throw "Illegal number: "+buf;
|
||||
return num;
|
||||
}
|
||||
}
|
||||
if(ch=='n') {
|
||||
if(in.read(3)=="ull") return JValue();
|
||||
else throw "Unexpected char n: expected null";
|
||||
}
|
||||
if(ch=='t') {
|
||||
if(in.read(3)=="rue") return true;
|
||||
else throw "Unexpected char t: expected true";
|
||||
}
|
||||
if(ch=='f') {
|
||||
if(in.read(4)=="alse") return false;
|
||||
else throw "Unexpected char f: expected false";
|
||||
}
|
||||
throw QString("Unexpected char ")+ch+" (code "+ch+"): expected {}, [], \"string\", number, null, true or false";
|
||||
}
|
||||
QString JParser::readStr() {
|
||||
QString buf;
|
||||
while((ch = readOne(in)) != '"') {
|
||||
if(ch==0) throw "Unexpected end-of-input: was expecting closing quote for string";
|
||||
if(ch=='\\') {
|
||||
in>>ch;
|
||||
if(ch==0) throw "Unexpected end-of-input in char escape sequence";
|
||||
if(ch=='"' || ch=='\\' || ch=='/') buf.append(ch);
|
||||
else if(ch=='n') buf.append('\n');
|
||||
else if(ch=='r') buf.append('\r');
|
||||
else if(ch=='t') buf.append('\t');
|
||||
else if(ch=='f') buf.append('\f');
|
||||
else if(ch=='b') buf.append('\b');
|
||||
else if(ch=='u') {
|
||||
auto hex = in.read(4);
|
||||
if(hex.size()<4) throw "Unexpected end-of-input in char escape sequence";
|
||||
bool ok;
|
||||
buf.append(hex.toUShort(&ok, 16));
|
||||
if(! ok) throw "Illegal hex-digits in char escape sequence: \\u"+hex;
|
||||
} else throw QString("Unrecognized char-escape ")+ch+" (code "+ch+")";
|
||||
} else buf.append(ch);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
void JParser::skipSpace() {
|
||||
if(bk.unicode()) {
|
||||
bk = QChar::Null;
|
||||
if(! ch.isSpace()) return;
|
||||
}
|
||||
in.skipWhiteSpace();
|
||||
in >> ch;
|
||||
if(ch==0) throw "Unexpected end-of-input";
|
||||
}
|
||||
|
||||
void JOut::write(const JValue &value) {
|
||||
if(value.type==JValue::Null) out << "null";
|
||||
else if(value.type==JValue::Str) writeStr(value.toStr());
|
||||
else if(value.type==JValue::Obj) writeMap(value.toObj());
|
||||
else if(value.type==JValue::Array) writeList(value.toArray());
|
||||
else out << value.toStr();
|
||||
out.flush();
|
||||
}
|
||||
void JOut::writeStr(const QString &str) {
|
||||
out << '"';
|
||||
QChar ch;
|
||||
for(int i=0; i<str.length(); i++) {
|
||||
ch = str[i];
|
||||
if(ch=='"'||ch=='\\') out<<'\\'<<ch;
|
||||
else if(ch < ' ') {
|
||||
if(ch=='\n') out<<"\\n";
|
||||
else if(ch=='\r') out<<"\\r";
|
||||
else if(ch=='\t') out<<"\\t";
|
||||
else if(ch=='\f') out<<"\\f";
|
||||
else if(ch=='\b') out<<"\\b";
|
||||
else {
|
||||
out<<"\\u00";
|
||||
auto aa = QString::number(ch.unicode(), 16);
|
||||
if(aa.size()==1) out<<'0';
|
||||
out<<aa;
|
||||
}
|
||||
} else out << ch;
|
||||
}
|
||||
out << '"';
|
||||
}
|
||||
void JOut::writeMap(const JObj &map) {
|
||||
out << '{';
|
||||
if(! map.empty()) {
|
||||
if(indent.size()) {
|
||||
out << '\n';
|
||||
cnt++;
|
||||
for(int c=0; c<cnt; c++) out << indent;
|
||||
}
|
||||
bool addSep = false;
|
||||
for(const auto &pair : map) {
|
||||
if(addSep) {
|
||||
out << ',';
|
||||
if(indent.size()) {
|
||||
out << '\n';
|
||||
for(int c=0; c<cnt; c++) out << indent;
|
||||
}
|
||||
}
|
||||
else addSep = true;
|
||||
out << '"' << pair.first << "\":";
|
||||
if(indent.size()) out << ' ';
|
||||
write(pair.second);
|
||||
}
|
||||
if(indent.size()) {
|
||||
out << '\n';
|
||||
cnt--;
|
||||
for(int c=0; c<cnt; c++) out << indent;
|
||||
}
|
||||
}
|
||||
out << '}';
|
||||
}
|
||||
void JOut::writeList(const JArray &vals) {
|
||||
out << '[';
|
||||
auto iter = vals.begin();
|
||||
auto end = vals.end();
|
||||
if(iter!=end) write(*iter++);
|
||||
while(iter!=end) {
|
||||
out << ',';
|
||||
if(indent.size()) out << ' ';
|
||||
write(*iter++);
|
||||
}
|
||||
out << ']';
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
#ifndef QJSON_H
|
||||
#define QJSON_H
|
||||
|
||||
#include "cu.h"
|
||||
#include "QtCore/qhashfunctions.h"
|
||||
#include <QTextStream>
|
||||
|
||||
class JValue;
|
||||
using JObj = LinkedMap<QString, JValue>;
|
||||
using JArray = Vector<JValue>;
|
||||
|
||||
class JValue {
|
||||
public:
|
||||
int data[2]{0};
|
||||
enum Type {
|
||||
Null, Bool, Int, Long, Double, Obj, Array, Str
|
||||
};
|
||||
Type type{Null};
|
||||
|
||||
JValue(Type = Null) {}
|
||||
JValue(bool b) : type(Bool) {data[0] = b;}
|
||||
JValue(int n) : type(Int) {data[0] = n;}
|
||||
JValue(qint64 n) : type(Long) {*(qint64*) data = n;}
|
||||
JValue(double d) : type(Double) {*(double*) data = d;}
|
||||
JValue(const JObj &o) : type(Obj) {new (data) JObj(o);}
|
||||
JValue(const JArray &a) : type(Array) {new (data) JArray(a);}
|
||||
JValue(const QString &s) : type(Str) {*(SharedData<QString>**) data = new SharedData<QString>{s, 1};}
|
||||
JValue(const char *s) : JValue(QString::fromUtf8(s)) {}
|
||||
JValue(const JValue &other) {
|
||||
type = other.type;
|
||||
if(type==Obj) new (data) JObj(*(JObj*) other.data);
|
||||
else if(type==Array) new (data) JArray(*(JArray*) other.data);
|
||||
else {
|
||||
data[0] = other.data[0];
|
||||
data[1] = other.data[1];
|
||||
if(type==Str) (*(SharedData<QString>**) data)->cnt++;
|
||||
}
|
||||
}
|
||||
~JValue() {
|
||||
if(type < Obj) return;
|
||||
else if(type==Obj) ((JObj*) data)->~JObj();
|
||||
else if(type==Array) ((JArray*) data)->~JArray();
|
||||
else if(type==Str) {
|
||||
auto ptr = *(SharedData<QString>**) data;
|
||||
if(ptr->cnt > 1) ptr->cnt--;
|
||||
else delete ptr;
|
||||
}
|
||||
}
|
||||
|
||||
JValue &operator=(const JValue &other) {
|
||||
this->~JValue();
|
||||
new (this) JValue(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isNull() const {return type==Null;}
|
||||
bool isObj() const {return type==Obj;}
|
||||
bool isArray() const {return type==Array;}
|
||||
|
||||
bool toBool(bool def = false) const {
|
||||
return type==Null ? def : data[0] || data[1];
|
||||
}
|
||||
int toInt(int def = 0) const {
|
||||
if(type==Bool || type==Int) return data[0];
|
||||
if(type==Long) return *(qint64*) data;
|
||||
if(type==Double) return *(double*) data;
|
||||
return def;
|
||||
}
|
||||
qint64 toLong(qint64 def = 0) const {
|
||||
if(type==Bool || type==Int) return data[0];
|
||||
if(type==Long) return *(qint64*) data;
|
||||
if(type==Double) return *(double*) data;
|
||||
return def;
|
||||
}
|
||||
double toDouble(double def = 0) const {
|
||||
if(type==Bool || type==Int) return data[0];
|
||||
if(type==Long) return *(qint64*) data;
|
||||
if(type==Double) return *(double*) data;
|
||||
return def;
|
||||
}
|
||||
QString toStr(const QString &def = "") const {
|
||||
if(type==Bool) return data[0] ? "true" : "false";
|
||||
if(type==Int) return QString::number(data[0]);
|
||||
if(type==Long) return QString::number(*(qint64*) data);
|
||||
if(type==Double) return QString::number(*(double*) data);
|
||||
if(type==Str) return (*(SharedData<QString>**) data)->data;
|
||||
return def;
|
||||
}
|
||||
JObj toObj() const {
|
||||
if(type==Obj) return *(JObj*) data;
|
||||
return JObj();
|
||||
}
|
||||
JArray toArray() const {
|
||||
if(type==Array) return *(JArray*) data;
|
||||
return JArray();
|
||||
}
|
||||
private:
|
||||
JValue(const void *) = delete; // avoid implicit conversions from char * to bool
|
||||
};
|
||||
|
||||
class JParser {
|
||||
public:
|
||||
JParser(QTextStream &in) : in(in) {}
|
||||
|
||||
inline JValue read() {
|
||||
skipSpace();
|
||||
return readValue();
|
||||
}
|
||||
protected:
|
||||
JValue readValue();
|
||||
QString readStr();
|
||||
void skipSpace();
|
||||
|
||||
QTextStream ∈
|
||||
QChar ch{0}, bk{0};
|
||||
};
|
||||
|
||||
inline JValue JFrom(const QByteArray &json, QString *err = 0) {
|
||||
QTextStream in(json);
|
||||
try {
|
||||
return JParser(in).read();
|
||||
} catch (QString anerr) {
|
||||
if(err) *err = anerr;
|
||||
} catch (const char *anerr) {
|
||||
if(err) *err = anerr;
|
||||
} catch (...) {
|
||||
if(err) *err = "unknow error";
|
||||
}
|
||||
return JValue();
|
||||
}
|
||||
inline JValue JFrom(QIODevice *device, QString *err = 0) {
|
||||
QTextStream in(device);
|
||||
try {
|
||||
return JParser(in).read();
|
||||
} catch (QString anerr) {
|
||||
if(err) *err = anerr;
|
||||
} catch (const char *anerr) {
|
||||
if(err) *err = anerr;
|
||||
} catch (...) {
|
||||
if(err) *err = "unknow error";
|
||||
}
|
||||
return JValue();
|
||||
}
|
||||
|
||||
class JOut {
|
||||
public:
|
||||
JOut(QTextStream &out, QString indent = "") : out(out), indent(indent) {}
|
||||
|
||||
void write(const JValue &obj);
|
||||
void writeStr(const QString &str);
|
||||
void writeMap(const JObj &map);
|
||||
void writeList(const JArray &objs);
|
||||
protected:
|
||||
QTextStream &out;
|
||||
QString indent;
|
||||
int cnt{0};
|
||||
};
|
||||
|
||||
inline QString JToStr(const JValue &obj, QString indent = "") {
|
||||
QString json;
|
||||
QTextStream out(&json);
|
||||
JOut(out, indent).write(obj);
|
||||
return json;
|
||||
}
|
||||
inline QByteArray JToBytes(const JValue &obj, QString indent = "") {
|
||||
QByteArray json;
|
||||
QTextStream out(&json);
|
||||
JOut(out, indent).write(obj);
|
||||
return json;
|
||||
}
|
||||
inline QTextStream::Status JWrite(const JValue &obj, QIODevice *device, QString indent = "") {
|
||||
QTextStream out(device);
|
||||
JOut(out, indent).write(obj);
|
||||
return out.status();
|
||||
}
|
||||
|
||||
#endif // QJSON_H
|
|
@ -5,16 +5,16 @@
|
|||
|
||||
const char *const FormBoundary = "----GangphonQtBoundary_.oOo._";
|
||||
|
||||
QNetworkAccessManager &netAccess() {
|
||||
QNetworkAccessManager *netAccess() {
|
||||
static QNetworkAccessManager access;
|
||||
return access;
|
||||
return &access;
|
||||
};
|
||||
|
||||
QString errStr(QNetworkReply *reply) {
|
||||
reply->deleteLater();
|
||||
auto error = reply->error();
|
||||
if(error != QNetworkReply::NoError) {
|
||||
if(error==QNetworkReply::OperationCanceledError) return QString(QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(QNetworkReply::TimeoutError))+" ("+QString::number(QNetworkReply::TimeoutError)+") "+QCoreApplication::translate("Net","Connection Timeout");
|
||||
if(error==QNetworkReply::OperationCanceledError) return "TimeoutError ("+QString::number(QNetworkReply::TimeoutError)+") "+QCoreApplication::translate("Net","Connection Timeout");
|
||||
auto errStr = reply->errorString();
|
||||
if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) return QString(QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error))+" ("+QString::number(error)+") "+errStr;
|
||||
}
|
||||
|
|
|
@ -8,19 +8,38 @@
|
|||
|
||||
extern const char *const FormBoundary;
|
||||
|
||||
QNetworkAccessManager &netAccess();
|
||||
QNetworkAccessManager *netAccess();
|
||||
|
||||
class NetReq : public QNetworkRequest {
|
||||
public:
|
||||
#if(QT_VERSION_MAJOR > 5)
|
||||
using QNetworkRequest::QNetworkRequest;
|
||||
explicit NetReq(const QString &url) : QNetworkRequest{url} {};
|
||||
explicit NetReq(QNetworkAccessManager *access) : mAccess(access) {};
|
||||
#else
|
||||
NetReq() {init();};
|
||||
explicit NetReq(const QString &url) : QNetworkRequest{url} {init();};
|
||||
explicit NetReq(QNetworkAccessManager *access) : mAccess(access) {init();};
|
||||
explicit NetReq(const QUrl &url) : QNetworkRequest{url} {init();};
|
||||
NetReq(const QNetworkRequest &other) : QNetworkRequest{other} {init();};
|
||||
|
||||
inline void init() {
|
||||
#if(QT_VERSION_MAJOR < 6)
|
||||
setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
}
|
||||
#endif
|
||||
using QNetworkRequest::url;
|
||||
inline NetReq &url(const QUrl &url) {
|
||||
setUrl(url);
|
||||
return *this;
|
||||
}
|
||||
inline NetReq &access(QNetworkAccessManager *access) {
|
||||
mAccess = access;
|
||||
return *this;
|
||||
}
|
||||
inline NetReq &header(const QByteArray &headerName, const QByteArray &value) {
|
||||
setRawHeader(headerName, value);
|
||||
return *this;
|
||||
}
|
||||
inline NetReq &header(KnownHeaders header, const QVariant &value) {
|
||||
setHeader(header, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline NetReq &type(const QByteArray &value) {
|
||||
|
@ -37,14 +56,16 @@ public:
|
|||
}
|
||||
|
||||
inline QNetworkReply *get() {
|
||||
return netAccess().get(*this);
|
||||
if(mAccess==0) mAccess = netAccess();
|
||||
return mAccess->get(*this);
|
||||
}
|
||||
inline QNetworkReply *post(const QByteArray &data) {
|
||||
return netAccess().post(*this, data);
|
||||
if(mAccess==0) mAccess = netAccess();
|
||||
return mAccess->post(*this, data);
|
||||
}
|
||||
inline QNetworkReply *post(const QJsonDocument &json) {
|
||||
setRawHeader("Content-Type", "application/json");
|
||||
return netAccess().post(*this, json.toJson(QJsonDocument::Compact));
|
||||
return post(json.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
inline QNetworkReply *post(const QJsonObject &json) {
|
||||
return post(QJsonDocument{json});
|
||||
|
@ -53,13 +74,20 @@ public:
|
|||
return post(QJsonDocument{json});
|
||||
}
|
||||
inline QNetworkReply *post(QHttpMultiPart *multiPart) {
|
||||
return netAccess().post(*this, multiPart);
|
||||
if(mAccess==0) mAccess = netAccess();
|
||||
return mAccess->post(*this, multiPart);
|
||||
}
|
||||
QNetworkAccessManager *mAccess{0};
|
||||
};
|
||||
|
||||
QString errStr(QNetworkReply *);
|
||||
QString errStrWithData(QNetworkReply *, QJsonDocument * = 0);
|
||||
|
||||
inline int waitFinished(QNetworkReply *reply, bool excludeUser = false) {
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
return excludeUser ? loop.exec(QEventLoop::ExcludeUserInputEvents) : loop.exec();
|
||||
}
|
||||
inline void abortSilence(QNetworkReply *reply) {
|
||||
reply->blockSignals(true);
|
||||
reply->abort();
|
||||
|
|
|
@ -143,7 +143,7 @@ void SendProgThread::run() {
|
|||
return;
|
||||
}
|
||||
while(remain > 0) {
|
||||
auto readed = file->read(qMin(4096LL, remain));
|
||||
auto readed = file->read(qMin(4*4096LL, remain));
|
||||
if(readed.isEmpty()) {
|
||||
emit emErr(tr("Read file failed")+" "+file->errorString());
|
||||
tcp.close();
|
||||
|
|
|
@ -124,21 +124,10 @@ QBrush Tools::getBrush(const QColor& color) {
|
|||
}
|
||||
|
||||
int Tools::color2Int(const QColor& color) {
|
||||
int res = 0;
|
||||
res |= (color.red() & 0xFF) << 24;
|
||||
res |= (color.green() & 0xFF) << 16;
|
||||
res |= (color.blue() & 0xFF) << 8;
|
||||
res |= (color.alpha() & 0xFF);
|
||||
return res;
|
||||
return color.red() << 24 | color.green() << 16 | color.blue() << 8 | color.alpha();
|
||||
}
|
||||
|
||||
QColor Tools::int2Color(int value) {
|
||||
QColor res;
|
||||
res.setRed ((value >> 24) & 0xFF);
|
||||
res.setGreen((value >> 16) & 0xFF);
|
||||
res.setBlue ((value >> 8) & 0xFF);
|
||||
res.setAlpha((value ) & 0xFF);
|
||||
return res;
|
||||
return QColor((value >> 24) & 0xff, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
|
||||
}
|
||||
|
||||
QString Tools::selectStr(bool f, const QString &s0, const QString &s1) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user