From 5006b17c708d6324f3fce444afe9bd0fb6de2bec Mon Sep 17 00:00:00 2001 From: tianduanrui Date: Sun, 19 Apr 2020 19:51:21 +0800 Subject: [PATCH] =?UTF-8?q?QQtDictionary=E5=88=9D=E6=AD=A5=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0toCbor=E5=92=8CfromCbor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/qqtdictionary.cpp | 208 +++++++++++++++++++++++++++++ src/core/qqtdictionary.h | 4 + src/core/qqtordereddictionary.cpp | 209 ++++++++++++++++++++++++++++++ src/core/qqtordereddictionary.h | 3 + 4 files changed, 424 insertions(+) diff --git a/src/core/qqtdictionary.cpp b/src/core/qqtdictionary.cpp index 12734853..c7f86100 100644 --- a/src/core/qqtdictionary.cpp +++ b/src/core/qqtdictionary.cpp @@ -31,6 +31,10 @@ #include +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +#include +#endif + #include using namespace std; @@ -59,6 +63,13 @@ void fromCSV ( const QByteArray& csv, QQtDictionary& dict, const QString& textEncoding ); #endif +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray toCbor ( const QQtDictionary& dict ); +void fromCbor ( const QByteArray& cbor, QQtDictionary& dict ); +void parseCborNodeToDictionary ( const QCborValue& node, QQtDictionary& object ); +void packDictionaryToCborNode ( const QQtDictionary& node, QCborValue& object ); +#endif + QByteArray toJson ( const QQtDictionary& dict, int indent = 0 ); void fromJson ( const QByteArray& json, QQtDictionary& dict ); void parseJsonValue ( const QJsonValue& value, QQtDictionary& parent ); @@ -610,6 +621,18 @@ void QQtDictionary::fromCSV ( const QByteArray& csv, } #endif +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray QQtDictionary::toCbor() const +{ + return ::toCbor ( *this ); +} + +void QQtDictionary::fromCbor ( const QByteArray& cbor ) +{ + ::fromCbor ( cbor, *this ); +} +#endif + bool QQtDictionary::operator == ( const QQtDictionary& other ) const { if ( m_type == other.getType() && @@ -1918,3 +1941,188 @@ void parseOrderedDictionary ( QQtDictionary& node, const QQtOrderedDictionary& o } } + +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray toCbor ( const QQtDictionary& dict ) +{ + QCborValue root; + packDictionaryToCborNode ( dict, root ); + + return root.toCbor(); +} + +void fromCbor ( const QByteArray& cbor, QQtDictionary& dict ) +{ + QCborValue root; + QCborParserError error; + root.fromCbor ( cbor, &error ); + if ( error.error != QCborError::NoError ) + { + pline() << ( int ) ( error.error ) << error.errorString() << error.offset; + return; + } + + parseCborNodeToDictionary ( root, dict ); +} + +void parseCborNodeToDictionary ( const QCborValue& node, QQtDictionary& object ) +{ + switch ( node.type() ) + { + case QCborValue::Integer: + { + object = node.toInteger(); + } + break; + case QCborValue::SimpleType: + case QCborValue::False: + case QCborValue::True: + case QCborValue::Undefined: + { + if ( node.type() == QCborValue::False || node.type() == QCborValue::True ) + { + object = node.toBool(); + break; + } + object = node.toInteger(); + } + break; + case QCborValue::Double: + object = node.toDouble(); + break; + case QCborValue::ByteArray: + object = node.toByteArray(); + break; + case QCborValue::String: + object = node.toString(); + break; + case QCborValue::DateTime: + object = node.toDateTime(); + break; + case QCborValue::Url: + object = node.toUrl(); + break; + case QCborValue::RegularExpression: + object = node.toRegularExpression(); + break; + case QCborValue::Uuid: + object = node.toUuid(); + break; + case QCborValue::Array: + { + QCborArray array = node.toArray(); + if ( array.size() <= 0 ) + { + object = QQtDictionary ( QQtDictionary::DictList ); + break; + } + for ( int i = 0; i < array.size(); i++ ) + { + parseCborNodeToDictionary ( array[i], object[i] ); + } + } + break; + case QCborValue::Map: + { + QCborMap map = node.toMap(); + if ( map.size() <= 0 ) + { + object = QQtDictionary ( QQtDictionary::DictMap ); + break; + } + for ( QCborMap::Iterator itor = map.begin(); + itor != map.end(); itor++ ) + { + const QCborValue& qkey = itor.key(); + QCborValueRef qvalue = itor.value(); + //强制转换为String,如果不是String,如此强制转换可能出现特别的数据。 + QString key = qkey.toString(); + parseCborNodeToDictionary ( qvalue, object[key] ); + } + } + break; + case QCborValue::Tag: + { + //此处没有判定tag,而是全部转换为String。 + node.tag(); + pline() << ( quint64 ) node.tag(); + //其实可以按照tag类型划分成已知的Value类型,但是我看基本上全都是String,所以此处全都转换成String。 + QString value = node.taggedValue().toString(); + object = value; + } + break; + case QCborValue::Invalid: + pline() << "invalid Cbor."; + default: + break; + } +} + +void packDictionaryToCborNode ( const QQtDictionary& node, QCborValue& result ) +{ + switch ( node.getType() ) + { + case QQtDictionary::DictValue: + { + //null, bool, double, string + p3line() << node.getValue().type(); + if ( node.getValue() == QVariant ( QJsonValue() ) ) + { + result = QCborValue(); + } + else if ( node.getValue().type() == QVariant::Bool ) + { + result = QCborValue ( node.getValue().toBool() ); + } + else if ( node.getValue().type() == QVariant::Double ) + { + result = QCborValue ( node.getValue().toDouble() ); + } + else if ( node.getValue().type() == QVariant::String ) + { + result = QCborValue ( node.getValue().toString() ); + } + else + { + result = QCborValue::fromVariant ( node.getValue() ); + } + break; + } + case QQtDictionary::DictList: + { + //"name":[a, b, ...] + QCborArray array; + for ( int i = 0; i < node.getList().size(); i++ ) + { + QList& l = node.getList(); + QCborValue value; + packDictionaryToCborNode ( l[i], value ); + //array.append ( value ); + array.push_back ( value ); + } + result = array; + break; + } + case QQtDictionary::DictMap: + { + //"name": {"a":"b", "a2":"b2", "a3":["b31", "b32"], "a4":{"a41":"b41", "a42":"b42"}, ...} + QCborMap object; + for ( QMap::Iterator itor = node.getMap().begin(); itor != node.getMap().end(); itor++ ) + { + //QMap& m = node.getMap(); + const QString& key = itor.key(); + const QQtDictionary& srcvalue = itor.value(); + QCborValue value; + packDictionaryToCborNode ( srcvalue, value ); + object.insert ( key, value ); + } + result = object; + break; + } + case QQtDictionary::DictMax: + default: + break; + } +} + +#endif diff --git a/src/core/qqtdictionary.h b/src/core/qqtdictionary.h index 186f37b0..c4c99b6f 100644 --- a/src/core/qqtdictionary.h +++ b/src/core/qqtdictionary.h @@ -43,6 +43,7 @@ typedef QMutableListIterator QQtDictionaryMutableListIterator; * fromINI toINI 支持ini * fromProperties toProperties 支持Properties 这是一种Java配置文件的格式,仅仅有键值对、注释 * fromCSV toCSV 支持csv 逗号分隔值格式文本。 + * fromCbor toCbor 支持Cbor 二进制、树型、流式数据结构。 * from函数默认行为为合并,如果用户希望新替,请手动调用clear(); * * QVariant 不能直接获取到真实数据,改变必须使用临时变量,而且,接口设计也不够灵活,存入和取出都不太方便。 @@ -223,6 +224,9 @@ public: const QString& textEncoding = QString ( "UTF-8" ) ); + QByteArray toCbor() const; + void fromCbor ( const QByteArray& cbor ); + private: /*节点类型,指示性变量*/ EDictType m_type; diff --git a/src/core/qqtordereddictionary.cpp b/src/core/qqtordereddictionary.cpp index 2e9e01f1..22f6419d 100644 --- a/src/core/qqtordereddictionary.cpp +++ b/src/core/qqtordereddictionary.cpp @@ -46,6 +46,10 @@ #include +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +#include +#endif + #include using namespace std; @@ -75,6 +79,13 @@ void fromCSV ( const QByteArray& csv, QQtOrderedDictionary& dict, #endif +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray toCbor ( const QQtOrderedDictionary& dict ); +void fromCbor ( const QByteArray& cbor, QQtOrderedDictionary& dict ); +void parseCborNodeToDictionary ( const QCborValue& node, QQtOrderedDictionary& object ); +void packDictionaryToCborNode ( const QQtOrderedDictionary& node, QCborValue& object ); +#endif + #ifdef USE_JSONCPP QByteArray toJson ( const QQtOrderedDictionary& dict, int indent = 0 ); void fromJson ( const QByteArray& json, QQtOrderedDictionary& dict ); @@ -99,6 +110,7 @@ void packDictionaryToDomNode ( const QQtOrderedDictionary& node, QDomNode& resul void parseDictionary ( QQtOrderedDictionary& node, const QQtDictionary& obj ); + //#define LOCAL_DEBUG #ifdef LOCAL_DEBUG #define p3line() p2line() @@ -615,6 +627,18 @@ void QQtOrderedDictionary::fromCSV ( const QByteArray& csv, } #endif +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray QQtOrderedDictionary::toCbor() const +{ + return ::toCbor ( *this ); +} + +void QQtOrderedDictionary::fromCbor ( const QByteArray& cbor ) +{ + ::fromCbor ( cbor, *this ); +} +#endif + bool QQtOrderedDictionary::operator == ( const QQtOrderedDictionary& other ) const { if ( m_type == other.getType() && @@ -2350,3 +2374,188 @@ void parseDictionary ( QQtOrderedDictionary& node, const QQtDictionary& obj ) break; } } + +#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) +QByteArray toCbor ( const QQtOrderedDictionary& dict ) +{ + QCborValue root; + packDictionaryToCborNode ( dict, root ); + + return root.toCbor(); +} + +void fromCbor ( const QByteArray& cbor, QQtOrderedDictionary& dict ) +{ + QCborValue root; + QCborParserError error; + root.fromCbor ( cbor, &error ); + if ( error.error != QCborError::NoError ) + { + pline() << ( int ) ( error.error ) << error.errorString() << error.offset; + return; + } + + parseCborNodeToDictionary ( root, dict ); +} + +void parseCborNodeToDictionary ( const QCborValue& node, QQtOrderedDictionary& object ) +{ + switch ( node.type() ) + { + case QCborValue::Integer: + { + object = node.toInteger(); + } + break; + case QCborValue::SimpleType: + case QCborValue::False: + case QCborValue::True: + case QCborValue::Undefined: + { + if ( node.type() == QCborValue::False || node.type() == QCborValue::True ) + { + object = node.toBool(); + break; + } + object = node.toInteger(); + } + break; + case QCborValue::Double: + object = node.toDouble(); + break; + case QCborValue::ByteArray: + object = node.toByteArray(); + break; + case QCborValue::String: + object = node.toString(); + break; + case QCborValue::DateTime: + object = node.toDateTime(); + break; + case QCborValue::Url: + object = node.toUrl(); + break; + case QCborValue::RegularExpression: + object = node.toRegularExpression(); + break; + case QCborValue::Uuid: + object = node.toUuid(); + break; + case QCborValue::Array: + { + QCborArray array = node.toArray(); + if ( array.size() <= 0 ) + { + object = QQtOrderedDictionary ( QQtOrderedDictionary::DictList ); + break; + } + for ( int i = 0; i < array.size(); i++ ) + { + parseCborNodeToDictionary ( array[i], object[i] ); + } + } + break; + case QCborValue::Map: + { + QCborMap map = node.toMap(); + if ( map.size() <= 0 ) + { + object = QQtOrderedDictionary ( QQtOrderedDictionary::DictMap ); + break; + } + for ( QCborMap::Iterator itor = map.begin(); + itor != map.end(); itor++ ) + { + const QCborValue& qkey = itor.key(); + QCborValueRef qvalue = itor.value(); + //强制转换为String,如果不是String,如此强制转换可能出现特别的数据。 + QString key = qkey.toString(); + parseCborNodeToDictionary ( qvalue, object[key] ); + } + } + break; + case QCborValue::Tag: + { + //此处没有判定tag,而是全部转换为String。 + node.tag(); + pline() << ( quint64 ) node.tag(); + //其实可以按照tag类型划分成已知的Value类型,但是我看基本上全都是String,所以此处全都转换成String。 + QString value = node.taggedValue().toString(); + object = value; + } + break; + case QCborValue::Invalid: + pline() << "invalid Cbor."; + default: + break; + } +} + +void packDictionaryToCborNode ( const QQtOrderedDictionary& node, QCborValue& result ) +{ + switch ( node.getType() ) + { + case QQtOrderedDictionary::DictValue: + { + //null, bool, double, string + p3line() << node.getValue().type(); + if ( node.getValue() == QVariant ( QJsonValue() ) ) + { + result = QCborValue(); + } + else if ( node.getValue().type() == QVariant::Bool ) + { + result = QCborValue ( node.getValue().toBool() ); + } + else if ( node.getValue().type() == QVariant::Double ) + { + result = QCborValue ( node.getValue().toDouble() ); + } + else if ( node.getValue().type() == QVariant::String ) + { + result = QCborValue ( node.getValue().toString() ); + } + else + { + result = QCborValue::fromVariant ( node.getValue() ); + } + break; + } + case QQtOrderedDictionary::DictList: + { + //"name":[a, b, ...] + QCborArray array; + for ( int i = 0; i < node.getList().size(); i++ ) + { + QList& l = node.getList(); + QCborValue value; + packDictionaryToCborNode ( l[i], value ); + //array.append ( value ); + array.push_back ( value ); + } + result = array; + break; + } + case QQtOrderedDictionary::DictMap: + { + //"name": {"a":"b", "a2":"b2", "a3":["b31", "b32"], "a4":{"a41":"b41", "a42":"b42"}, ...} + QCborMap object; + for ( QOrderedMap::Iterator itor = node.getMap().begin(); itor != node.getMap().end(); itor++ ) + { + //QOrderedMap& m = node.getMap(); + const QString& key = itor.key(); + const QQtOrderedDictionary& srcvalue = itor.value(); + QCborValue value; + packDictionaryToCborNode ( srcvalue, value ); + object.insert ( key, value ); + } + result = object; + break; + } + case QQtOrderedDictionary::DictMax: + default: + break; + } +} + +#endif diff --git a/src/core/qqtordereddictionary.h b/src/core/qqtordereddictionary.h index 13c44ea3..28dad262 100644 --- a/src/core/qqtordereddictionary.h +++ b/src/core/qqtordereddictionary.h @@ -204,6 +204,9 @@ public: const QString& textEncoding = QString ( "UTF-8" ) ); + QByteArray toCbor() const; + void fromCbor ( const QByteArray& cbor ); + private: /*节点类型,指示性变量*/ EDictType m_type;