Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

plist Namespace Reference

A collection of classes to implement the Propery List data storage format, a XML standard used by Apple and others. More...

Classes

class  Listener
 Base class for the plist listener callbacks. More...
class  PrimitiveListener
 If you wish to be notified any time a particular plist primitive's value has been changed, inherit from this and implement the callback, then register it with the plist object through Primitive::addPrimitiveListener(). More...
class  CollectionListener
 If you wish to be notified any time an entry is added, removed, or replaced from a Dictionary, Array, or Vector, inherit from this and implement one or both of the functions, then register it with the collection's addCollectionListener(). More...
class  ObjectBase
 This base class provides the root functionality for all plist entities -- Dictionary and the various templated subclasses of PrimitiveBase. More...
class  PrimitiveBase
 Provides common functionality to all primitive value classes (implemented in a templated subclass Primitive). More...
class  Collection
struct  AutoCollectionListener
 Monitors a collection to keep tabs on all its entries, so PrimitiveListener::plistValueChanged will be called if any entry is changed. More...
struct  CollectionCallbackMember
 Produces a callback on a member function when a value in the collection changes. More...
class  DictionaryBase
 Maintains a set of (key,value) pairs, see DictionaryOf, and the Dictionary typedef. More...
class  DictionaryOf
 A dictionary which requires all elements to be subtypes of the PO template argument. More...
class  ArrayBase
 Maintains an array of value, see ArrayOf, and the Array typedef. More...
class  ArrayOf
 A collection of plist objects, similar to a Dictionary, but no keys -- order matters!, see plist::Array. More...
class  Primitive
struct  AutoPrimitiveListener
 Auto subscribe/unsubscribe from a Primitive. More...
struct  PrimitiveCallbackMember
 Produces a callback on a member function when the value changes. More...
class  NamedEnumerationBase
class  NamedEnumeration
 Provides an interface for the use of enumerations in a plist -- you can specify values by either the string name or the corresponding integer value. More...
class  OutputSelector
 Handles mapping <string> elements to the appropriate numeric offset using Capabilities database. More...
class  Angle
 Handles angle measurements by adding a 'unit' attribute to numeric values, or a character suffix in a string value. */. More...
class  Point
 A simple class for storing 3D points, will be serialized as an array and provides operator[], but you can also use the x, y, z fields directly if preferred. More...
class  RGBColor

Typedefs

typedef DictionaryOf< ObjectBaseDictionary
typedef ArrayOf< ObjectBaseArray
typedef float PLISTREAL

Functions

template<>
SensorInfoloadXML (xmlNode *node)
 This specialization looks for the SensorInfo::sensorType, then has the factory construct the correct subtype before loading the node into and returning that.
template<>
SensorInfoallocate ()
 SensorInfo::sensorType.set() could still lead to trouble, although with a little work we could probably find a way to support it...
template<>
void assign< PlannerObstacle2D > (PlannerObstacle2D &, PlannerObstacle2D const &)
template<>
void assign< PlannerObstacle3D > (PlannerObstacle3D &, PlannerObstacle3D const &)
ObjectBaseloadFile (const std::string &file)
 Attempts to parse the file found at file, using plist::loadXML().
ObjectBaseloadBuffer (const char *buf, unsigned int len)
 Attempts to parse the buffer found at buf, using plist::loadXML().
std::ostream & operator<< (std::ostream &os, const ObjectBase &pb)
 output of an ObjectBase to a stream
std::ostream & operator<< (std::ostream &os, const PrimitiveBase &pb)
 output stringified value (from PrimitiveBase::get()) to stream
std::istream & operator>> (std::istream &is, PrimitiveBase &pb)
 input value from next word in is, via PrimitiveBase::set()
std::ostream & filteredDisplay (std::ostream &os, const ObjectBase &c, const std::string &sel, int selType, unsigned int depth)
 take a regex and maximum depth for display (displays entries whos names match the filter sel
std::ostream & filteredDisplay (std::ostream &os, const ObjectBase &c, const regex_t *reg, unsigned int depth)
 take a compiled regex and maximum depth for display
template<class T >
T * allocate ()
 allocates a new T instance, unless T is a known abstract type (ObjectBase, PrimitiveBase, Collection), in which case will throw a bad_cast via template specialization
template<class T >
void assign (T &a, const T &b)
 assigns one T to another using operator=, unless T is ObjectBase, in which case set() is used via template specialization
template<class T >
T * loadXML (xmlNode *node)
std::ostream & operator<< (std::ostream &os, const DictionaryBase &d)
 provides textual output
std::ostream & operator<< (std::ostream &os, const ArrayBase &d)
 provides textual output
template<typename T >
const char * getTypeName ()
 returns a string indicating the plist entry type to use for the specified type

Detailed Description

A 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 1345 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 641 of file plistCollections.h.

Definition at line 14 of file plistSpecialty.h.


Function Documentation

template<class T >
T* plist::allocate (  ) 

allocates a new T instance, unless T is a known abstract type (ObjectBase, PrimitiveBase, Collection), in which case will throw a bad_cast via template specialization

Definition at line 15 of file plistCollections.h.

template<>
PlannerObstacle3D * plist::allocate (  ) 

SensorInfo::sensorType.set() could still lead to trouble, although with a little work we could probably find a way to support it...

not supported

Definition at line 36 of file PlannerObstacles.h.

template<class T >
void plist::assign ( T &  a,
const T &  b 
)

assigns one T to another using operator=, unless T is ObjectBase, in which case set() is used via template specialization

Definition at line 17 of file plistCollections.h.

Referenced by plist::ArrayOf< PO, Alloc >::operator=(), and plist::DictionaryOf< PO, Alloc >::operator=().

template<>
void plist::assign< PlannerObstacle2D > ( PlannerObstacle2D ,
PlannerObstacle2D const &   
)
template<>
void plist::assign< PlannerObstacle3D > ( PlannerObstacle3D ,
PlannerObstacle3D const &   
)
std::ostream & plist::filteredDisplay ( std::ostream &  os,
const ObjectBase &  c,
const regex_t *  reg,
unsigned int  depth 
)

take a compiled regex and maximum depth for display

Parameters:
os the ostream to write into
c the collection to dump
reg a pre-compiled regular expression, or NULL to match everything
depth maximum recursion depth for sub-collections
std::ostream & plist::filteredDisplay ( std::ostream &  os,
const ObjectBase &  c,
const std::string &  sel,
int  selType,
unsigned int  depth 
)

take a regex and maximum depth for display (displays entries whos names match the filter sel

Parameters:
os the ostream to write into
c the collection to dump
sel the regular expression in string form
selType how to interpret sel, this is the flags argument to regcomp(), e.g. REG_EXTENDED or REG_BASIC
depth maximum recursion depth for sub-collections

Referenced by operator<<().

template<typename T >
const char* plist::getTypeName (  ) 

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...

ObjectBase * plist::loadBuffer ( const char *  buf,
unsigned int  len 
)

Attempts to parse the buffer found at buf, using plist::loadXML().

ObjectBase * plist::loadFile ( const std::string &  file  ) 

Attempts to parse the file found at file, using plist::loadXML().

template<class T >
T* plist::loadXML ( xmlNode node  ) 

attempts to load a new T instance from the specified xmlNode

Definition at line 27 of file plistCollections.h.

template<>
ObjectBase * plist::loadXML ( xmlNode node  ) 

This specialization looks for the SensorInfo::sensorType, then has the factory construct the correct subtype before loading the node into and returning that.

From the name of node, will instantiate a new ObjectBase subclass to load it.

supports use of plist::ArrayOf<PlannerObstacle> for polymorphic load/save

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 28 of file PlannerObstacles.cc.

std::ostream& plist::operator<< ( std::ostream &  os,
const ArrayBase &  d 
)

provides textual output

Definition at line 1581 of file plistCollections.h.

std::ostream& plist::operator<< ( std::ostream &  os,
const DictionaryBase &  d 
)

provides textual output

Definition at line 1578 of file plistCollections.h.

std::ostream& plist::operator<< ( std::ostream &  os,
const PrimitiveBase &  pb 
)

output stringified value (from PrimitiveBase::get()) to stream

Definition at line 290 of file plistBase.h.

std::ostream& plist::operator<< ( std::ostream &  os,
const ObjectBase &  pb 
)

output of an ObjectBase to a stream

Definition at line 208 of file plistBase.h.

std::istream& plist::operator>> ( std::istream &  is,
PrimitiveBase &  pb 
)

input value from next word in is, via PrimitiveBase::set()

Definition at line 294 of file plistBase.h.


Tekkotsu v5.1CVS
Generated Mon May 9 04:59:24 2016 by Doxygen 1.6.3