Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members  

judo.hpp

00001 //============================================================================
00002 // Project:       Jabber Universal Document Objects (Judo)
00003 // Filename:      judo.h
00004 // Description:   Primary header
00005 // Created at:    Mon Jul  2 17:27:04 2001
00006 // Modified at:   Tue Oct 16 10:28:40 2001
00007 // 
00008 //   License:
00009 // 
00010 // The contents of this file are subject to the Jabber Open Source License
00011 // Version 1.0 (the "License").  You may not copy or use this file, in either
00012 // source code or executable form, except in compliance with the License.  You
00013 // may obtain a copy of the License at http://www.jabber.com/license/ or at
00014 // http://www.opensource.org/.  
00015 //
00016 // Software distributed under the License is distributed on an "AS IS" basis,
00017 // WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
00018 // for the specific language governing rights and limitations under the
00019 // License.
00020 //
00021 //   Copyrights
00022 //
00023 // Portions created by or assigned to Jabber.com, Inc. are 
00024 // Copyright (c) 1999-2001 Jabber.com, Inc.  All Rights Reserved.  
00025 // 
00026 // $Id: judo.hpp,v 1.7 2003/05/04 06:15:04 julian Exp $
00027 //============================================================================
00028 
00029 #ifndef INCL_JUDO_H
00030 #define INCL_JUDO_H
00031 
00032 #ifdef WIN32
00033 #pragma warning (disable:4786)
00034 #include <windows.h>
00035 #endif
00036 
00037 #include <assert.h>
00038 
00039 #include <cstdio>
00040 #include <cstring>
00041 #include <list>
00042 #include <map>
00043 #include <string>
00044 #include <set>
00045 #include <algorithm>
00046 
00047 #include "expat.h"
00048 
00049 #ifdef TEST
00050 #define TESTER(s) friend class s;
00051 #else
00052 #define TESTER(s)
00053 #endif
00054 
00058 namespace judo
00059 {
00060     class XMLAccumulator;
00061 
00065     class Node
00066     {
00067     public:
00068         enum Type
00069         {
00070             ntElement,
00071             ntCDATA
00072         };
00073 
00079         Node(const std::string& name, Type ntype)
00080             : _name(name), _type(ntype)
00081             {}
00082         virtual ~Node() {}
00083     public:
00088         const std::string& getName() const
00089             { return _name; }
00090 
00095         Node::Type getType() const
00096             { return _type; }
00097 
00104         virtual std::string toString() const = 0;
00105 
00112         virtual void accumulate(XMLAccumulator& acc) const = 0;
00113 
00114     protected:
00115         std::string        _name;
00116         Node::Type _type;    
00117 
00118         // Ensure that no one can initialize this variable without
00119         // using the proper constructor
00120         Node();
00121     };
00122 
00123     // Utility routines
00124     void   unescape(const char* src, unsigned int srcLen, std::string& dest, bool append = false);  
00125     std::string escape(const std::string& src);
00126 
00127     class XMLAccumulator
00128     {
00129     public:
00130         XMLAccumulator(std::string& s)
00131             : _result(s) {}
00132 
00133         void operator()(const Node* n)
00134             { n->accumulate(*this); }
00135         void operator()(const std::pair<const std::string, std::string> p)
00136             { _result += " " + p.first + "='" + 
00137                   escape(p.second) + "'";
00138             }
00139         template <class T>
00140         XMLAccumulator& operator<<(T data)
00141             { _result += data; return *this; }
00142     private:
00143         std::string& _result;
00144     };
00145 
00149     class CDATA : 
00150         public Node
00151     {
00152     public:
00156         CDATA(const char* text, unsigned int textsz, bool escaped = false)
00157             : Node("#CDATA", Node::ntCDATA)
00158             {
00159                 if (escaped)
00160                 {
00161                     unescape(text, textsz, _text);
00162                 }
00163                 else
00164                 {
00165                     _text.assign(text, textsz);
00166                 }
00167             }
00168         
00176         void setText(const char* text, unsigned int textsz, bool escaped = false)
00177             { 
00178                 if (escaped)
00179                 {
00180                     unescape(text, textsz, _text); 
00181                 }
00182                 else
00183                 {
00184                     _text.assign(text, textsz);
00185                 }
00186             }
00187 
00195         void appendText(const char* text, unsigned int textsz, bool escaped = false)
00196             { 
00197                 if (escaped)
00198                 {
00199                     unescape(text, textsz, _text, true); 
00200                 }
00201                 else
00202                 {
00203                     _text.append(text, textsz);
00204                 }
00205             }
00206 
00212         const std::string& getText() const
00213             { return _text; }
00214 
00220         std::string toString() const
00221             { return escape(_text); }
00222 
00223         void accumulate(XMLAccumulator& acc) const
00224             { acc << escape(_text); }
00225 
00226     private:
00227         TESTER(CDATATest)
00228 
00229         std::string _text;           
00230     };
00231 
00235     class Element: 
00236         public Node
00237     {
00238     public:
00239         Element(const std::string& name, const char** attribs = NULL);
00240         Element(const Element& e);
00241         ~Element();
00242 
00243         Element& operator=(const Element& e);
00244 
00245         Element* addElement(const std::string& name, const char** attribs = NULL);
00246         Element* addElement(const std::string& name, const std::string& cdata, 
00247                             bool escaped = false);
00248         CDATA*   addCDATA(const char* data, int datasz, bool escaped = false);  
00249 
00250         void   putAttrib(const std::string& name, const std::string& value);
00251         std::string getAttrib(const std::string& name) const;
00252         void   delAttrib(const std::string& name);
00253         bool   cmpAttrib(const std::string& name, const std::string& value) const;
00254         std::map<std::string,std::string> getAttribs() const { return _attribs; }
00255 
00256         std::string toString() const;
00257         std::string toStringEx(bool recursive = false, bool closetag = false) const;
00258 
00259         void accumulate(XMLAccumulator& acc) const;
00260 
00261         std::string getCDATA() const;
00262         
00263 
00264         typedef std::list<Node*>::iterator iterator;
00265         typedef std::list<Node*>::const_iterator const_iterator;
00266 
00271         void appendChild(Node* child)
00272             { _children.push_back(child); }
00273         
00274         Node* detachChild(iterator it);
00275         
00280         bool empty() const
00281             { return _children.empty(); }
00282 
00288         int size() const
00289             { return _children.size(); }
00290         
00294         iterator begin()
00295             { return _children.begin(); }
00296 
00300         const_iterator begin() const
00301             { return _children.begin(); }
00302 
00306         iterator end()
00307             { return _children.end(); }
00308 
00312         const_iterator end() const
00313             { return _children.end(); }
00314 
00315         iterator find(const std::string& name, Node::Type type = Node::ntElement);
00316 
00317         const_iterator find(const std::string& name, Node::Type type = Node::ntElement) const;
00322         void Element::erase(Element::iterator it)
00323             { delete *it; _children.erase(it); }
00324 
00325         Element* findElement(const std::string& name);
00326         const Element* findElement(const std::string& name) const;
00327         void     eraseElement(const std::string& name);
00328 
00329         std::string getChildCData(const std::string& name) const;
00330         int         getChildCDataAsInt(const std::string& name, int defaultvalue) const;
00331 
00332 
00333     protected:
00334         TESTER(ElementTest)
00335         
00336         std::list<Node*>        _children;
00337         std::map<std::string,std::string> _attribs;
00338     };
00339     
00343     class ElementStreamEventListener
00344     {
00345     public:
00346         virtual ~ElementStreamEventListener() {}
00353         virtual void onDocumentStart(Element* e) = 0;
00354 
00362         virtual void onElement(Element* e) = 0;
00363 
00374         virtual void onCDATA(CDATA* c) 
00375             { delete c; }
00376             
00377 
00382         virtual void onDocumentEnd() = 0;
00383     };
00384     
00385 
00389     class ElementStream 
00390     {
00391     public:
00392         ElementStream(ElementStreamEventListener* l);
00393         virtual ~ElementStream();
00394 
00395         void push(const char* data, int datasz);
00396         void reset();
00397 
00398         static Element* parseAtOnce(const char* buffer);
00399 
00400         struct exception
00401         {
00402             class ParserError 
00403                 {
00404                 public:
00405                     ParserError(int code)
00406                         : _code(code), _message(XML_ErrorString((XML_Error)code))
00407                         {}
00408                     const std::string& getMessage() const
00409                         { return _message; }
00410                     int getCode() const
00411                         { return _code; }
00412                 private:
00413                     int _code;
00414                     std::string _message;
00415                 };
00416             class IncompleteParse{};
00417         };
00418 
00419     private:
00420         TESTER(ElementStreamTest)
00421 
00422         XML_Parser     _parser;
00423         bool           _parser_ready;
00424         std::list<Element*> _element_stack;
00425         bool           _document_started;
00426         bool           _document_ended;
00427 
00428         ElementStreamEventListener* _event_listener;
00429 
00430         // Expat callbacks
00431         static void onStartElement(void* userdata, const char* name, const char** attribs);
00432         static void onEndElement(void* userdata, const char* name);
00433         static void onCDATA(void* userdata, const char* cdata, int cdatasz);
00434 
00435         // Expat initializers
00436         void initExpat();
00437         void cleanupExpat();
00438        };
00439 }
00440 #endif

Generated on Thu Jul 24 13:31:51 2003 for jabberoo by doxygen1.3-rc3