Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
plist Namespace ReferenceDetailed DescriptionA collection of classes to implement the Propery List data storage format, a XML standard used by Apple and others.The plist namespace provides convenient serialization for persistent storage, dynamic introspection, and polymorphic primitive values. The classes happen to use Apple's XML-based "property list" format for serialization, using libxml2 for the low level parsing. The choice of storage format was based on a desire for human readability, including per-value comments and inline documentation, as well as the desire to make use of syntax hilighting or high-level editing tools. Individual values are based on templated instances of the Primitive<T> class, while groups of values are based on the Collection interface. Currently, the concrete collections available are Array (one dimensional ordered list of mixed primitive types), ArrayOf<T> (ordered list of a single type), or Dictionary (unordered mapping from string names to mixed primitives). Generally, there are two ways you might use the functionality contained within this namespace. One is as an external storage interface, such as the STL vector and map classes are used. This might be only a intermediary instance for conversion to and from existing data structures, as a higher-level interface than directly accessing libxml. However, to fully benefit from this namespace's functionality, you will generally want your classes to inherit from plist::Dictionary, define your members as public plist Primitives and Collections, and register listeners for notification when these values are modified (either by loading from file or programmatic modification.) Example usage is shown below, you can find this code and more in Tekkotsu/tools/test/plist/. #include "Shared/plist.h" using namespace std; // you might want to 'using namespace plist'... // we'll be using plist:: scoping everywhere below just for clarity /* Generic base class for "shapes"... we specify a generic Collection, * as its base, allows either Dictionary or Array-based! */ class Shape : virtual public plist::Collection {}; /* We will use a float for coordinates, wrapped by a plist::Primitive<> * The Primitive class provides transparent conversions and operations, * so we can usually pretend this is just a regular float! */ typedef plist::Primitive<float> coord_t; /* A point is defined as an array of coordinates, one for each dimension. * We'll assume 2D points unless otherwise directed. * An alternative definition could use explicit 'x' and 'y' members, and/or * use a Dictionary with labels instead of an Array with subscripts... */ class Point : public Shape, virtual public plist::ArrayOf<coord_t> { public: explicit Point(size_t n=2) : plist::ArrayOf<coord_t>(n,0), Shape() { } Point(float xVal, float yVal) : plist::ArrayOf<coord_t>(2,0), Shape() { getEntry(0)=xVal; getEntry(1)=yVal; } }; /* We'll define a rectangle by the lower-left point and the upper-right point. * Further, we'll set up an accessor to maintain this invariant. */ class Rectangle : public Shape, public virtual plist::DictionaryOf<Point> { public: Rectangle() : plist::DictionaryOf<Point>(), Shape(), lower(), upper(), xm(lower[0],upper[0]), ym(lower[1],upper[1]) { /* The next line 'fixes' the entries during load, save, or assignment. * The default is to allow dynamic resizing, so you should call this when * you expect the entry structure to be immutable. (e.g. if you are using * members as collection entries.) */ setLoadSavePolicy(FIXED,SYNC); addEntry("lower",lower); // still can always 'explicitly' add or remove entries addEntry("upper",upper); // ... the LoadSavePolicy only restricts 'implicit' changes } /* Can provide public access to members, the Monitor will provide * the flexibility usually provided by get/set accessor functions. */ Point lower, upper; /* Note automatic conversion to value type, will never be negative due to our Monitor */ float getWidth() const { return upper[0] - lower[0]; } float getHeight() const { return upper[1] - lower[1]; } protected: /* Implements plist::PrimitiveListener to receive notification when * a member's value is changed. We could also do this by having * rectangle itself be the listener instead of an inner class. */ class Monitor : public plist::PrimitiveListener { public: Monitor(coord_t& low, coord_t& high) : _low(low), _high(high) { _low.addPrimitiveListener(this); _high.addPrimitiveListener(this); } virtual void plistValueChanged(const plist::PrimitiveBase&) { if(_low>_high) std::swap(_low,_high); } protected: coord_t &_low, &_high; } xm, ym; }; /* Here's an example of a purely dynamic class... just a resizeable list * of points! For a "real" implementation, you'd probably want to use * a dictionary, add a few more properties (e.g. 'isClosed'), and have * the point list as a member variable... */ class Polygon : public Shape, public virtual plist::ArrayOf<Point> {}; // Here's some sample usage... int main(int argc, const char** argv) { Point p; p[0] = 1; // transparent conversion from value type to plist::Primitive p[1] = 2.5; p.saveFile("point.plist"); Rectangle r; r.upper = Point(4,5); // we can assign to directly to member... r["lower"] = p; // ... or dynamically via operator[] lookup r.saveFile("rectangle.plist"); // test the low/high invariant cout << "Original r, width: " << r.getWidth() << '\n' << r; /* Original r, width: 3 * lower.0 = 1 * lower.1 = 2.5 * upper.0 = 4 * upper.1 = 5 */ r.upper[0] = -4; // note we assign to upper.x, but it's lower.x that will be -4 // (because of the PrimitiveListener added by Rectangle's constructor) cout << "Negated r, width: " << r.getWidth() << '\n' << r; /* Negated r, width: 5 * lower.0 = -4 * lower.1 = 2.5 * upper.0 = 1 * upper.1 = 5 */ // dynamic resizing: Polygon poly; /* Notice we are adding pointers here, vs. references in Rectangle, * vs. float values in Point. (De)allocation from pointers or converted * values is handled by the collection, whereas entries added from * references are *not* deallocated. */ poly.addEntry(new Point(1,2)); poly.addEntry(new Point(3,4)); poly.addEntry(new Point(5,0)); poly.saveFile("poly.plist"); return 0; }
Typedef Documentation
plist::Array can handle any mixture of types, whereas plist::ArrayOf<PO> will only accept the plist objects of type PO (or their subclasses). This typedef is simply for convenience and passes ObjectBase for the template parameter. Definition at line 1174 of file plistCollections.h.
plist::Dictionary can handle any mixture of types, whereas plist::DictionaryOf<PO> will only accept the plist objects of type PO (or their subclasses). This typedef is simply for convenience and passes ObjectBase for the template parameter. Definition at line 514 of file plistCollections.h.
Function Documentation
take a compiled regex and maximum depth for display
Definition at line 802 of file plistCollections.cc.
take a regex and maximum depth for display (displays entries whos names match the filter sel
Definition at line 792 of file plistCollections.cc. Referenced by filteredDisplay(), and operator<<().
template<typename T>
returns a string indicating the plist entry type to use for the specified type some primitives (bool, char) aren't handled because they require a specialization of Primitive and won't use this function. If you want to use a plist Primitive of some custom type, you might be able to just define a new specialization of this function and provide iostream <</>> operators for your type...
Attempts to parse the buffer found at buf, using plist::loadXML().
Attempts to parse the file found at file, using plist::loadXML().
From the name of node, will instantiate a new ObjectBase subclass to load it. The mapping from node names to actual instantiated types is:
If successful, returns a pointer to a newly allocated region, which the caller is responsible for freeing. If an error occurs, NULL is returned. Definition at line 7 of file plist.cc. Referenced by plist::PolymorphicLoader::loadXML(), plist::ArrayOf< PO, Alloc >::loadXMLNode(), and plist::DictionaryOf< PO, Alloc >::loadXMLNode().
output stringified value (from PrimitiveBase::get()) to stream
Definition at line 275 of file plistBase.h.
input value from next word in is, via PrimitiveBase::set()
Definition at line 279 of file plistBase.h.
|
Tekkotsu v4.0 |
Generated Thu Nov 22 00:58:51 2007 by Doxygen 1.5.4 |