/* PIP - Platform Independent Primitives Config parser Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PICONFIG_H #define PICONFIG_H #include "pifile.h" #define PICONFIG_GET_VALUE \ Entry & getValue(const PIString & vname, const char * def, bool * exist = 0) {return getValue(vname, PIString(def), exist);} \ Entry & getValue(const PIString & vname, const PIStringList & def, bool * exist = 0) {return getValue(vname, def.join("%|%"), exist);} \ Entry & getValue(const PIString & vname, const bool def, bool * exist = 0) {return getValue(vname, PIString::fromBool(def), exist);} \ Entry & getValue(const PIString & vname, const short def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \ Entry & getValue(const PIString & vname, const int def, bool * exist = 0) {return getValue(vname, itos(def), exist);} \ Entry & getValue(const PIString & vname, const long def, bool * exist = 0) {return getValue(vname, ltos(def), exist);} \ Entry & getValue(const PIString & vname, const uchar def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const ushort def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const uint def, bool * exist = 0) {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const ulong def, bool * exist = 0) {return getValue(vname, ultos(def), exist);} \ Entry & getValue(const PIString & vname, const float def, bool * exist = 0) {return getValue(vname, ftos(def), exist);} \ Entry & getValue(const PIString & vname, const double def, bool * exist = 0) {return getValue(vname, dtos(def), exist);} \ \ Entry & getValue(const PIString & vname, const char * def, bool * exist = 0) const {return getValue(vname, PIString(def), exist);} \ Entry & getValue(const PIString & vname, const PIStringList & def, bool * exist = 0) const {return getValue(vname, def.join("%|%"), exist);} \ Entry & getValue(const PIString & vname, const bool def, bool * exist = 0) const {return getValue(vname, PIString::fromBool(def), exist);} \ Entry & getValue(const PIString & vname, const short def, bool * exist = 0) const {return getValue(vname, itos(def), exist);} \ Entry & getValue(const PIString & vname, const int def, bool * exist = 0) const {return getValue(vname, itos(def), exist);} \ Entry & getValue(const PIString & vname, const long def, bool * exist = 0) const {return getValue(vname, ltos(def), exist);} \ Entry & getValue(const PIString & vname, const uchar def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const ushort def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const uint def, bool * exist = 0) const {return getValue(vname, uitos(def), exist);} \ Entry & getValue(const PIString & vname, const ulong def, bool * exist = 0) const {return getValue(vname, ultos(def), exist);} \ Entry & getValue(const PIString & vname, const float def, bool * exist = 0) const {return getValue(vname, ftos(def), exist);} \ Entry & getValue(const PIString & vname, const double def, bool * exist = 0) const {return getValue(vname, dtos(def), exist);} class PIConfig: public PIFile { friend class Entry; friend class Branch; public: PIConfig(const PIString & path, PIFlags mode = Read | Write); ~PIConfig() {piForeach (Entry * i, root._children) deleteEntry(i);} class Entry; class Branch: public PIVector { friend class PIConfig; friend class Entry; friend std::ostream & operator <<(std::ostream & s, const Branch & v); public: Branch() {;} Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast(this)->getValue(vname, def, exist);} PICONFIG_GET_VALUE Branch allLeaves(); Branch getValues(const PIString & name); Branch getLeaves(); Branch getBranches(); Branch & filter(const PIString & f); bool isEntryExists(const PIString & name) const {piForeachC (Entry * i, *this) if (entryExists(i, name)) return true; return false;} int indexOf(const Entry * e) {for (int i = 0; i < size_s(); ++i) if (at(i) == e) return i; return -1;} void clear() {piForeach (Entry * i, *this) delete i; PIVector::clear();} private: bool entryExists(const Entry * e, const PIString & name) const; void allLeaves(Branch & b, Entry * e) {piForeach (Entry * i, e->_children) {if (i->isLeaf()) b << i; else allLeaves(b, i);}} void coutt(std::ostream & s, const PIString & p) const {piForeachC (Entry * i, *this) i->coutt(s, p);} static Entry _empty; PIString delim; }; class Entry { friend class PIConfig; friend class Branch; public: Entry() {_parent = 0;} Entry * parent() const {return _parent;} int childCount() {return _children.size_s();} Branch & children() {_children.delim = delim; return _children;} Entry * child(const int index) const {return _children[index];} Entry * findChild(const PIString & name) {piForeach (Entry * i, _children) if (i->_name == name) return i; return 0;} const Entry * findChild(const PIString & name) const {piForeachC (Entry * i, _children) if (i->_name == name) return i; return 0;} bool isLeaf() const {return _children.isEmpty();} const PIString & name() const {return _name;} const PIString & value() const {return _value;} const PIString & type() const {return _type;} const PIString & comment() const {return _comment;} const PIString & fullName() const {return _full_name;} Entry & setName(const PIString & value) {_name = value; return *this;} Entry & setType(const PIString & value) {_type = value; return *this;} Entry & setComment(const PIString & value) {_comment = value; return *this;} Entry & setValue(const PIString & value) {_value = value; return *this;} Entry & setValue(const PIStringList & value) {setValue(value.join("%|%")); setType("l"); return *this;} Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;} Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;} Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;} Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;} Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;} Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;} Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;} Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;} Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;} Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;} Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;} Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;} Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast(this)->getValue(vname, def, exist);} PICONFIG_GET_VALUE Branch getValues(const PIString & vname); bool isEntryExists(const PIString & name) const {return entryExists(this, name);} operator bool() {return _value.toBool();} operator char() {return (_value.isEmpty() ? 0 : _value[0].toAscii());} operator short() {return _value.toShort();} operator int() {return _value.toInt();} operator long() {return _value.toLong();} operator uchar() {return _value.toInt();} operator ushort() {return _value.toShort();} operator uint() {return _value.toInt();} operator ulong() {return _value.toLong();} operator float() {return _value.toFloat();} operator double() {return _value.toDouble();} operator PIString() {return _value;} operator PIStringList() {return _value.split("%|%");} private: static bool compare(const PIConfig::Entry * f, const PIConfig::Entry * s) {return f->_line < s->_line;} bool entryExists(const Entry * e, const PIString & name) const; void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;} void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;} void coutt(std::ostream & s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << endl; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->coutt(s, nl);} static Entry _empty; Entry * _parent; Branch _children; PIString _tab; PIString _name; PIString _value; PIString _type; PIString _comment; PIString _all; PIString _full_name; PIString delim; int _line; }; Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast(this)->getValue(vname, def, exist);} PICONFIG_GET_VALUE Branch getValues(const PIString & vname); void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void setValue(const PIString & name, const PIStringList & value, bool write = true) {setValue(name, value.join("%|%"), "l", write);} void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);} void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);} void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);} void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);} void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);} void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);} void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);} void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);} void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);} void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);} void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);} Entry & rootEntry() {return root;} int entriesCount() const {return childCount(&root);} bool isEntryExists(const PIString & name) const {return entryExists(&root, name);} Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; return b;} Branch allLeaves() {Branch b; allLeaves(b, &root); std::sort(b.begin(), b.end(), Entry::compare); return b;} int entryIndex(const PIString & name); PIString getName(uint number) {return entryByIndex(number)._name;} PIString getValue(uint number) {return entryByIndex(number)._value;} PIChar getType(uint number) {return entryByIndex(number)._type[0];} PIString getComment(uint number) {return entryByIndex(number)._comment;} void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void setName(uint number, const PIString & name, bool write = true); void setValue(uint number, const PIString & value, bool write = true); void setType(uint number, const PIString & type, bool write = true); void setComment(uint number, const PIString & comment, bool write = true); void removeEntry(const PIString & name, bool write = true); void removeEntry(uint number, bool write = true); void readAll(); void writeAll(); const PIString & delimiter() const {return delim;} void setDelimiter(const PIString & d) {delim = d; setEntryDelim(&root, d); readAll();} private: int childCount(const Entry * e) const {int c = 0; piForeachC (Entry * i, e->_children) c += childCount(i); c += e->_children.size_s(); return c;} bool entryExists(const Entry * e, const PIString & name) const; void buildFullNames(Entry * e) {piForeach (Entry * i, e->_children) {if (e != &root) i->_full_name = e->_full_name + delim + i->_name; else i->_full_name = i->_name; buildFullNames(i);}} void allLeaves(Branch & b, Entry * e) {piForeach (Entry * i, e->_children) {if ((!i->_value.isEmpty() && !i->isLeaf()) || i->isLeaf()) b << i; allLeaves(b, i);}} void setEntryDelim(Entry * e, const PIString & d) {piForeach (Entry * i, e->_children) setEntryDelim(i, d); e->delim = d;} Entry & entryByIndex(const int index) {Branch b = allLeaves(); if (index < 0 || index >= b.size_s()) return empty; return *(b[index]);} void removeEntry(Branch & b, Entry * e); void deleteEntry(Entry * e) {piForeach (Entry * i, e->_children) deleteEntry(i); delete e;} void parse(); int centry; PIString delim; Entry root, empty; uint lines; PIStringList other; }; inline std::ostream & operator <<(std::ostream & s, const PIConfig::Branch & v) {v.coutt(s, ""); return s;} inline std::ostream & operator <<(std::ostream & s, const PIConfig::Entry & v) {s << v.value(); return s;} #endif // PICONFIG_H