Sandboxie/SandboxiePlus/MiscHelpers/Common/Xml.cpp

290 lines
7.2 KiB
C++

#include "stdafx.h"
#include "Xml.h"
QString CXml::Serialize(const QVariant &Variant, bool bLazy)
{
QString String;
QXmlStreamWriter xml(&String);
Serialize(Variant, xml, bLazy);
return String;
}
QVariant CXml::Parse(const QString& String, bool bLazy)
{
QXmlStreamReader xml(String);
return Parse(xml, bLazy);
}
void CXml::Serialize(const QVariant& Variant, QFile* pFile)
{
QXmlStreamWriter xml(pFile);
Serialize(Variant, xml);
}
QVariant CXml::Parse(QFile* pFile)
{
QXmlStreamReader xml(pFile);
return Parse(xml);
}
void CXml::Write(const QVariant& Variant, const QString& FileName)
{
QFile File(FileName + ".tmp");
File.open(QFile::WriteOnly);
Serialize(Variant, &File);
QFile::rename(FileName, FileName + ".bak");
File.rename(FileName);
File.remove(FileName + ".bak");
}
QVariant CXml::Read(const QString& FileName)
{
QFile File(FileName);
File.open(QFile::ReadOnly);
return Parse(&File);
}
void CXml::Serialize(const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy)
{
#ifdef _DEBUG
xml.setAutoFormatting(true);
#endif
xml.writeStartDocument();
Serialize("Variant", Variant, xml, bLazy);
xml.writeEndDocument();
}
QVariant CXml::Parse(QXmlStreamReader &xml, bool bLazy)
{
QVariant Variant;
QString Temp;
Parse(Temp, Variant, xml, bLazy);
return Variant;
}
void CXml::Serialize(const QString& Name, const QVariant& Variant, QXmlStreamWriter &xml, bool bLazy)
{
xml.writeStartElement(Name);
xml.writeAttribute("Type", GetTypeStr(Variant.type()));
switch(Variant.type())
{
case QVariant::Map:
{
QVariantMap Map = Variant.toMap();
for(QVariantMap::iterator I = Map.begin(); I != Map.end(); ++I)
Serialize(I.key(), I.value(), xml, bLazy);
break;
}
case QVariant::Hash:
{
QVariantHash Hash = Variant.toHash();
for(QVariantHash::iterator I = Hash.begin(); I != Hash.end(); ++I)
Serialize(I.key(), I.value(), xml, bLazy);
break;
}
case QVariant::List:
{
QVariantList List = Variant.toList();
for(QVariantList::iterator I = List.begin(); I != List.end(); ++I)
Serialize("Variant", *I, xml, bLazy);
break;
}
case QVariant::StringList:
{
QStringList List = Variant.toStringList();
for(QStringList::iterator I = List.begin(); I != List.end(); ++I)
Serialize("Variant", *I, xml, bLazy);
break;
}
case QVariant::ByteArray:
if(!bLazy)
{
xml.writeCharacters (Variant.toByteArray().toBase64());
break;
}
default:
ASSERT(Variant.canConvert(QVariant::String));
xml.writeCharacters(Variant.toString().toUtf8().toPercentEncoding(" :;/|,'+()"));
//xml.writeCharacters (Variant.toString().replace("\\","\\\\").replace("\r","\\r").replace("\n","\\n"));
break;
case QVariant::Invalid:
break;
}
xml.writeEndElement();
}
bool CXml::Parse(QString &Name, QVariant &Variant, QXmlStreamReader &xml, bool bLazy)
{
bool bOpen = false;
QVariant::Type eType = QVariant::Invalid;
QString Text;
while (!xml.atEnd())
{
xml.readNext();
if (xml.error())
break;
if (xml.isEndDocument())
continue;
if (xml.isStartElement())
{
bOpen = true;
Name = xml.name().toString();
eType = GetType(xml.attributes().value("Type").toString());
QString Temp;
QVariant Item;
switch(eType)
{
case QVariant::Map:
{
QVariantMap Map;
while(Parse(Temp, Item, xml, bLazy))
Map.insert(Temp, Item);
Variant = Map;
return true;
}
case QVariant::Hash:
{
QVariantHash Hash;
while(Parse(Temp, Item, xml, bLazy))
Hash.insert(Temp, Item);
Variant = Hash;
return true;
}
case QVariant::List:
{
QVariantList List;
while(Parse(Temp, Item, xml, bLazy))
List.append(Item);
Variant = List;
return true;
}
case QVariant::StringList:
{
QStringList List;
while(Parse(Temp, Item, xml, bLazy))
List.append(Item.toString());
Variant = List;
return true;
}
}
}
else if (xml.isCharacters())
{
if(bOpen)
Text.append(xml.text().toString());
}
else if (xml.isEndElement())
{
if(bOpen)
{
if(eType == QVariant::ByteArray && !bLazy)
Variant.setValue(QByteArray::fromBase64(Text.toLatin1()));
else
{
/*bool bEsc = false;
for(int i = 0; i < Text.size(); i++)
{
if(bEsc) // ESC sequence handling
{
switch(Text.at(i).unicode())
{
case L'\\': Text.replace(--i,2,"\\"); break;
case L'r': Text.replace(--i,2,"\r"); break;
case L'n': Text.replace(--i,2,"\n"); break;
default: Text.replace(--i,2,"?"); break;
}
bEsc = false;
}
else if(Text.at(i) == L'\\')
bEsc = true;
}*/
Variant = QString::fromUtf8(QByteArray::fromPercentEncoding(Text.toLatin1()));
if(eType) // type is optional
{
ASSERT(Variant.canConvert(eType));
Variant.convert(eType);
}
}
return true;
}
return false;
}
}
//ASSERT(0); // incomplete XML
return false;
}
/* SQVariants provides a lookup list of all known QVariant types for to/from string conversion
*
* Note: All commented out types don't have native to string conversion
* If there is a need to use them a manual conversion must be implemented in CXml
*/
struct SQVariants{
SQVariants()
{
Map.insert("Invalid" , QVariant::Invalid);
Map.insert("Bool" , QVariant::Bool);
Map.insert("Int" , QVariant::Int);
Map.insert("UInt" , QVariant::UInt);
Map.insert("LongLong" , QVariant::LongLong);
Map.insert("ULongLong" , QVariant::ULongLong);
Map.insert("Double" , QVariant::Double);
Map.insert("Char" , QVariant::Char);
Map.insert("Map" , QVariant::Map); // container type
Map.insert("List" , QVariant::List); // container type
Map.insert("String" , QVariant::String);
Map.insert("StringList" , QVariant::StringList); // container type
Map.insert("ByteArray" , QVariant::ByteArray);
//Map.insert("BitArray" , QVariant::BitArray);
Map.insert("Date" , QVariant::Date);
Map.insert("Time" , QVariant::Time);
Map.insert("DateTime" , QVariant::DateTime);
Map.insert("Url" , QVariant::Url);
/*Map.insert("Locale" , 18);
Map.insert("Rect" , 19);
Map.insert("RectF" , 20);
Map.insert("Size" , 21);
Map.insert("SizeF" , 22);
Map.insert("Line" , 23);
Map.insert("LineF" , 24);
Map.insert("Point" , 25);
Map.insert("PointF" , 26);
Map.insert("RegExp" , 27);*/
Map.insert("Hash" , QVariant::Hash); // conainter type
/*Map.insert("Font" , 64);
Map.insert("Pixmap" , 65);
Map.insert("Brush" , 66);
Map.insert("Color" , 67);
Map.insert("Palette" , 68);
Map.insert("Icon" , 69);
Map.insert("Image" , 70);
Map.insert("Polygon" , 71);
Map.insert("Region" , 72);
Map.insert("Bitmap" , 73);
Map.insert("Cursor" , 74);
Map.insert("SizePolicy" , 75);
Map.insert("KeySequence", 76);
Map.insert("Pen" , 77);
Map.insert("TextLength" , 78);
Map.insert("TextFormat" , 79);
Map.insert("Matrix" , 80);
Map.insert("Transform" , 81);
Map.insert("Matrix4x4" , 82);
Map.insert("Vector2D" , 83);
Map.insert("Vector3D" , 84);
Map.insert("Vector4D" , 85);
Map.insert("Quaternion" , 86);*/
}
QMap<QString,int> Map;
} SQVariants;
QString CXml::GetTypeStr(int Type) {return SQVariants.Map.key(Type, "Invalid");}
QVariant::Type CXml::GetType(QString Type) {return (QVariant::Type)SQVariants.Map.value(Type, 0);}