PIValueTreeConversions text, options
PIVariant fixes
This commit is contained in:
@@ -23,6 +23,40 @@
|
||||
#include "piiostring.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
const char _attribute_[] = "_attribute_";
|
||||
|
||||
PIString unmask(const PIString & str) {
|
||||
PIString ret;
|
||||
for (int i = 0; i < str.size_s(); ++i) {
|
||||
if (str[i] == '\\') {
|
||||
if (i < str.size_s() - 1) {
|
||||
++i;
|
||||
ret += str[i];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ret += str[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PIString mask(const PIString & str) {
|
||||
PIString ret = str;
|
||||
if (ret.isEmpty()) return ret;
|
||||
int start = 0;
|
||||
if (ret[0].isSpace()) {
|
||||
ret.insert(0, '\\');
|
||||
start = 1;
|
||||
}
|
||||
for (int i = start; i < ret.size_s(); ++i) {
|
||||
if (ret[i] == '\\') {
|
||||
ret.insert(i, '\\');
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIValueTree PIValueTreeConversions::fromPropertyStorage(const PIPropertyStorage & ps) {
|
||||
PIValueTree ret;
|
||||
@@ -88,6 +122,25 @@ PIValueTree PIValueTreeConversions::fromJSON(const PIJSON & json) {
|
||||
}
|
||||
|
||||
|
||||
PIValueTree prepareFromText(const PIValueTree & root) {
|
||||
PIValueTree ret;
|
||||
ret.setName(root.name());
|
||||
ret.setComment(root.comment());
|
||||
if (root.contains(_attribute_)) {
|
||||
for (const auto & a: root.child(_attribute_).children())
|
||||
ret.attributes()[a.name()] = a.value().toString();
|
||||
}
|
||||
PIVariant value = PIVariant::fromType(ret.attribute("type", PIVariant::typeName<PIString>()).toString());
|
||||
value.setValueFromString(root.value().toString());
|
||||
ret.setValue(value);
|
||||
for (const auto & c: root.children()) {
|
||||
if (c.name() != _attribute_)
|
||||
ret[c.name()] = prepareFromText(c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
PIValueTree ret;
|
||||
if (!device) return ret;
|
||||
@@ -96,7 +149,7 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
PIIOTextStream ts(device);
|
||||
PIString line, comm;
|
||||
PIVariant value;
|
||||
PIChar type;
|
||||
PIString type;
|
||||
PIStringList prefix, path;
|
||||
while (!ts.isEnd()) {
|
||||
PIString l = ts.readLine().trim();
|
||||
@@ -115,7 +168,7 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
line.clear();
|
||||
continue;
|
||||
}
|
||||
type = 's';
|
||||
type = PIVariant::typeName<PIString>();
|
||||
comm.clear();
|
||||
int ind = line.find('#');
|
||||
if (ind >= 0) {
|
||||
@@ -126,7 +179,18 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
else if (comm[0].isAlpha() && comm[1].isSpace()) typed = true;
|
||||
}
|
||||
if (typed) {
|
||||
type = comm.takeLeft(1)[0];
|
||||
switch (comm.takeLeft(1)[0].toAscii()) {
|
||||
case 'b': type = PIVariant::typeName<bool>(); break;
|
||||
case 'n': type = PIVariant::typeName<int>(); break;
|
||||
case 'f': type = PIVariant::typeName<double>(); break;
|
||||
case 'l': type = PIVariant::typeName<PIStringList>(); break;
|
||||
case 'c': type = PIVariant::typeName<PIVariantTypes::Color>(); break;
|
||||
case 'p':
|
||||
case 'v': type = PIVariant::typeName<PIPointd>(); break;
|
||||
case 'r':
|
||||
case 'a': type = PIVariant::typeName<PIRectd>(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
comm.trim();
|
||||
line.cutRight(1).trim();
|
||||
@@ -134,7 +198,7 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
ind = line.find('=');
|
||||
if ((ind > 0) && (line[0] != '#')) {
|
||||
path = prefix;
|
||||
path << line.takeLeft(ind).trim().split('.');
|
||||
path << line.takeLeft(ind).split('.').trim();
|
||||
line.cutLeft(1).trim();
|
||||
if (path.front() == "include") {
|
||||
/*name = line.mid(ind + 1).trimmed();
|
||||
@@ -151,39 +215,31 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
|
||||
}
|
||||
}
|
||||
//piCout << path << line << comm;
|
||||
switch (type.toAscii()) {
|
||||
case 'b': value = line.toBool(); break;
|
||||
case 'n': value = line.toInt(); break;
|
||||
case 'f': value = line.toDouble(); break;
|
||||
case 'l': value = line.split("%|%"); break;
|
||||
case 'c': value = PIVariantTypes::Color(line.toUInt()); break;
|
||||
case 'p':
|
||||
case 'v': value = PIVariant(line).toPoint(); break;
|
||||
case 'r':
|
||||
case 'a': value = PIVariant(line).toRect(); break;
|
||||
default: value = line;
|
||||
}
|
||||
PIValueTree & leaf(ret[path]);
|
||||
value.setValueFromString(line);
|
||||
leaf.setComment(comm);
|
||||
leaf.setValue(value);
|
||||
leaf.setValue(unmask(line));
|
||||
if (!path.contains(_attribute_))
|
||||
if (!leaf.contains({_attribute_, "type"}))
|
||||
leaf[_attribute_].addChild({"type", type});
|
||||
line.clear();
|
||||
}
|
||||
return ret;
|
||||
return prepareFromText(ret);
|
||||
//return ret;
|
||||
}
|
||||
|
||||
|
||||
PIJSON toJSONTree(const PIValueTree & root) {
|
||||
PIJSON toJSONTree(const PIValueTree & root, PIValueTreeConversions::Options options) {
|
||||
PIJSON ret = PIJSON::newObject();
|
||||
if (root.name().isNotEmpty())
|
||||
ret["name"] = root.name();
|
||||
if (root.comment().isNotEmpty())
|
||||
if (root.comment().isNotEmpty() && options[PIValueTreeConversions::WithComment])
|
||||
ret["comment"] = root.comment();
|
||||
if (root.value().isValid()) {
|
||||
ret["type"] = root.value().typeName();
|
||||
if (options[PIValueTreeConversions::WithType])
|
||||
ret["type"] = root.value().typeName();
|
||||
ret["value"] = root.value().toString();
|
||||
}
|
||||
if (root.attributes().isNotEmpty()) {
|
||||
if (root.attributes().isNotEmpty() && options[PIValueTreeConversions::WithAttributes]) {
|
||||
PIJSON j;
|
||||
for (const auto & a: root.attributes())
|
||||
j[a.first] = a.second.toString();
|
||||
@@ -192,22 +248,79 @@ PIJSON toJSONTree(const PIValueTree & root) {
|
||||
if (root.hasChildren()) {
|
||||
PIJSON j;
|
||||
for (const auto & c: root.children())
|
||||
j << toJSONTree(c);
|
||||
j << toJSONTree(c, options);
|
||||
ret["children"] = j;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIJSON PIValueTreeConversions::toJSON(const PIValueTree & root) {
|
||||
PIJSON PIValueTreeConversions::toJSON(const PIValueTree & root, Options options) {
|
||||
PIJSON ret = PIJSON::newArray();
|
||||
for (const auto & c: root.children())
|
||||
ret << toJSONTree(c);
|
||||
ret << toJSONTree(c, options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIValueTreeConversions::toText(const PIValueTree & root) {
|
||||
PIString toTextTreeAttributes(const PIValueTree & root, PIString prefix, PIValueTreeConversions::Options options) {
|
||||
PIString ret;
|
||||
for (const auto & a: root.attributes()) {
|
||||
if (a.first == "type") continue;
|
||||
ret += prefix + _attribute_ + "." + a.first;
|
||||
ret += " = " + mask(a.second.toString());
|
||||
ret += '\n';
|
||||
}
|
||||
if (options[PIValueTreeConversions::WithType]) {
|
||||
ret += prefix + _attribute_ + ".type";
|
||||
ret += " = " + root.value().typeName();
|
||||
ret += '\n';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString toTextTree(const PIValueTree & root, PIString prefix, PIValueTreeConversions::Options options) {
|
||||
PIString ret;
|
||||
if (prefix.isNotEmpty()) prefix += '.';
|
||||
prefix += root.name();
|
||||
if (root.hasChildren()) {
|
||||
ret += "\n[" + prefix + "]\n";
|
||||
if (root.isArray() && options[PIValueTreeConversions::WithAttributes])
|
||||
ret += toTextTreeAttributes(root, "", options);
|
||||
for (const auto & c: root.children()) {
|
||||
PIString cp = prefix;
|
||||
ret += toTextTree(c, prefix, options);
|
||||
}
|
||||
} else {
|
||||
if (root.value().isValid()) {
|
||||
ret += root.name() + " = ";
|
||||
ret += mask(root.value().toString()).replacedAll('\n', " \\\n");
|
||||
}
|
||||
if (root.comment().isNotEmpty() && options[PIValueTreeConversions::WithComment]) {
|
||||
ret += " # ";
|
||||
ret += root.comment();
|
||||
}
|
||||
ret += "\n";
|
||||
if (options[PIValueTreeConversions::WithAttributes])
|
||||
ret += toTextTreeAttributes(root, root.name() + ".", options);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIValueTreeConversions::toText(const PIValueTree & root, Options options) {
|
||||
PIString ret;
|
||||
for (const auto & c: root.children()) {
|
||||
ret += toTextTree(c, PIString(), options);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIValueTree PIValueTreeConversions::fromText(const PIString & str) {
|
||||
PIIOString dev(str);
|
||||
return fromText(&dev);
|
||||
}
|
||||
|
||||
@@ -33,12 +33,24 @@ class PIJSON;
|
||||
class PIIODevice;
|
||||
|
||||
namespace PIValueTreeConversions {
|
||||
|
||||
enum Option {
|
||||
WithAttributes = 0x1,
|
||||
WithComment = 0x2,
|
||||
WithType = 0x4,
|
||||
WithAll = 0xFFFFFF,
|
||||
Default = WithAll
|
||||
};
|
||||
typedef PIFlags<Option> Options;
|
||||
|
||||
PIP_EXPORT PIValueTree fromPropertyStorage(const PIPropertyStorage & ps);
|
||||
PIP_EXPORT PIValueTree fromVariantMap(const PIVariantMap & vm);
|
||||
PIP_EXPORT PIValueTree fromJSON(const PIJSON & json);
|
||||
PIP_EXPORT PIValueTree fromText(PIIODevice * device);
|
||||
PIP_EXPORT PIJSON toJSON(const PIValueTree & root);
|
||||
PIP_EXPORT PIString toText(const PIValueTree & root);
|
||||
PIP_EXPORT PIValueTree fromText(const PIString & str);
|
||||
PIP_EXPORT PIJSON toJSON(const PIValueTree & root, Options options = Default);
|
||||
PIP_EXPORT PIString toText(const PIValueTree & root, Options options = Default);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user