Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

plistBase.cc

Go to the documentation of this file.
00001 #include "plistBase.h"
00002 #include "plistPrimitives.h"
00003 #include <libxml/xmlmemory.h>
00004 #include <libxml/parser.h>
00005 
00006 //better to put this here instead of the header
00007 using namespace std; 
00008 
00009 namespace plist {
00010   
00011   ObjectBase::ObjectBase()
00012   : XMLLoadSave()
00013   {}
00014   
00015   ObjectBase::~ObjectBase() {}
00016   
00017   void ObjectBase::setParseTree(xmlDoc * doc) const {
00018     XMLLoadSave::setParseTree(doc);
00019     if(xmldocument==NULL)
00020       return;
00021     xmlNode* root=XMLLoadSave::FindRootXMLElement(doc);
00022     if(root != NULL && xmlStrcmp(root->name, (const xmlChar *)"plist")==0)
00023       return;
00024     xmlNodePtr cur = xmlNewNode(NULL,(const xmlChar*)"plist");
00025     xmlNewProp(cur,(const xmlChar*)"version",(const xmlChar*)"1.0");
00026     xmlDocSetRootElement(xmldocument,cur);
00027     xmlCreateIntSubset(xmldocument,(const xmlChar*)"plist",(const xmlChar*)"-//Apple//DTD PLIST 1.0//EN",(const xmlChar*)"http://www.apple.com/DTDs/PropertyList-1.0.dtd");
00028   }
00029   
00030   xmlNode* ObjectBase::FindRootXMLElement(xmlDoc* doc) const {
00031     if(doc==NULL)
00032       return NULL;
00033     xmlNode* root=XMLLoadSave::FindRootXMLElement(doc);
00034     if(root == NULL)
00035       throw bad_format(root,"Error: plist read empty document");
00036     if(xmlStrcmp(root->name, (const xmlChar *)"plist"))
00037       throw bad_format(root,"Error: plist read document of the wrong type, root node != plist");
00038     string filename;
00039     if(doc->name!=NULL && doc->name[0]!='\0') {
00040       filename="document '";
00041       filename+=doc->name;
00042       filename+="' ";
00043     }
00044     if(!xmlHasProp(root,(const xmlChar*)"version"))
00045       cerr << "Warning: plist " << filename << "does not carry version number, assuming 1.0" << endl;
00046     else {
00047       xmlChar* strv=xmlGetProp(root,(const xmlChar*)"version");
00048       double version=strtod((const char*)strv,NULL);
00049       if(version>1.0)
00050         cerr << "WARNING: plist " << filename << "is version " << strv << ", this software only knows 1.0.  Trying anyway..." << endl;
00051       if(version==0)
00052         cerr << "WARNING: plist " << filename << "seems to have invalid version '" << strv << "', this software only knows 1.0.  Trying anyway..." << endl;
00053       xmlFree(strv);
00054     }
00055     
00056     // find first element node within the plist
00057     xmlNode* cur=root->children;
00058     while(cur!=NULL && cur->type!=XML_ELEMENT_NODE)
00059       cur=cur->next;
00060     if(cur==NULL) //empty plist
00061       cur = xmlNewChild(root,NULL,(const xmlChar*)"",NULL);
00062     return cur;
00063   }
00064   
00065   bool ObjectBase::xNodeHasName(xmlNode* node, const char* name) {
00066     return xmlStrcasecmp(node->name,(const xmlChar*)name)==0;
00067   }
00068   const xmlChar* ObjectBase::xNodeGetName(xmlNode* node) {
00069     return node->name;
00070   }
00071   xmlNode* ObjectBase::xNodeGetChildren(xmlNode* node) {
00072     return node->children;
00073   }
00074   xmlNode* ObjectBase::xNodeGetLastChild(xmlNode* node) {
00075     return node->last;
00076   }
00077   xmlNode* ObjectBase::xNodeGetNextNode(xmlNode* node) {
00078     return node->next;
00079   }
00080   xmlNode* ObjectBase::xNodeGetPrevNode(xmlNode* node) {
00081     return node->prev;
00082   }
00083   xmlNode* ObjectBase::xNodeGetParent(xmlNode* node) {
00084     return node->parent;
00085   }
00086   xmlDoc* ObjectBase::xNodeGetDoc(xmlNode* node) {
00087     return node->doc;
00088   }
00089   bool ObjectBase::xNodeIsText(xmlNode* node) {
00090     return node->type==XML_TEXT_NODE;
00091   }
00092   bool ObjectBase::xNodeIsElement(xmlNode* node) {
00093     return node->type==XML_ELEMENT_NODE;
00094   }
00095   bool ObjectBase::xNodeIsComment(xmlNode* node) {
00096     return node->type==XML_COMMENT_NODE;
00097   }
00098     
00099 
00100   PrimitiveBase& PrimitiveBase::operator=(const Primitive<std::string>& v) { *this = static_cast<const PrimitiveBase&>(v); return *this; }
00101   PrimitiveBase& PrimitiveBase::operator=(const std::string& v) { *this=static_cast<const PrimitiveBase&>(Primitive<std::string>(v)); return *this; }
00102   PrimitiveBase& PrimitiveBase::operator=(long v) { *this=Primitive<long>(v); return *this; }
00103   PrimitiveBase& PrimitiveBase::operator=(unsigned long v) { *this=Primitive<unsigned long>(v); return *this; }
00104   PrimitiveBase& PrimitiveBase::operator=(double v) { *this=Primitive<double>(v); return *this; }
00105   
00106   PrimitiveBase::~PrimitiveBase() {
00107     delete primitiveListeners;
00108     primitiveListeners=NULL;
00109   }
00110   
00111   void PrimitiveBase::addPrimitiveListener(PrimitiveListener* vl) {
00112     if(vl!=NULL) {
00113       if(primitiveListeners==NULL)
00114         primitiveListeners=new std::set<PrimitiveListener*>;
00115       primitiveListeners->insert(vl);
00116     }
00117   }
00118   void PrimitiveBase::removePrimitiveListener(PrimitiveListener* vl) {
00119     if(primitiveListeners==NULL)
00120       return;
00121     std::set<PrimitiveListener*>::iterator it=primitiveListeners->find(vl);
00122     if(it!=primitiveListeners->end()) {
00123       primitiveListeners->erase(it);
00124       if(primitiveListeners->empty()) {
00125         delete primitiveListeners;
00126         primitiveListeners=NULL;
00127       }
00128     }
00129   }
00130   bool PrimitiveBase::isPrimitiveListener(PrimitiveListener* vl) {
00131     if(vl==NULL)
00132       return false;
00133     if(primitiveListeners==NULL)
00134       return false;
00135     std::set<PrimitiveListener*>::iterator it=primitiveListeners->find(vl);
00136     return it!=primitiveListeners->end();
00137   }
00138   void PrimitiveBase::fireValueChanged(bool touchOnly) const {
00139     if(primitiveListeners==NULL)
00140       return;
00141     // copy primitive listeners so we aren't screwed if a listener is removed during processing, particularly if it's the *last* listener
00142     std::set<PrimitiveListener*> pls=*primitiveListeners;
00143     if(touchOnly) {
00144       for(std::set<PrimitiveListener*>::const_iterator it=pls.begin(); primitiveListeners!=NULL && it!=pls.end(); ++it) {
00145         // make sure current listener hasn't been removed
00146         if(primitiveListeners->find(*it)!=primitiveListeners->end())
00147           (*it)->plistValueTouched(*this);
00148       }
00149     } else {
00150       for(std::set<PrimitiveListener*>::const_iterator it=pls.begin(); primitiveListeners!=NULL && it!=pls.end(); ++it) {
00151         // make sure current listener hasn't been removed
00152         if(primitiveListeners->find(*it)!=primitiveListeners->end())
00153           (*it)->plistValueChanged(*this);
00154       }
00155     }
00156   }
00157     
00158 } //namespace plist
00159 
00160 
00161 /*! @file
00162  * @brief 
00163  * @author Ethan Tira-Thompson (ejt) (Creator)
00164  *
00165  * $Author: ejt $
00166  * $Name: tekkotsu-4_0 $
00167  * $Revision: 1.7 $
00168  * $State: Exp $
00169  * $Date: 2007/11/15 02:00:50 $
00170  */

Tekkotsu v4.0
Generated Thu Nov 22 00:54:54 2007 by Doxygen 1.5.4