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.2 2002/03/07 21:55:52 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 #include "expat/expat.h"
00039 
00040 #include <cstdio>
00041 #include <cstring>
00042 #include <list>
00043 #include <map>
00044 #include <string>
00045 #include <set>
00046 #include <algorithm>
00047 
00048 #ifdef TEST
00049 #define TESTER(s) friend class s;
00050 #else
00051 #define TESTER(s)
00052 #endif
00053 
00057 namespace judo
00058 {
00059     class XMLAccumulator;
00060 
00064     class Node
00065     {
00066     public:
00067         enum Type
00068         {
00069             ntElement,
00070             ntCDATA
00071         };
00072 
00078         Node(const std::string& name, Type ntype)
00079             : _name(name), _type(ntype)
00080             {}
00081         virtual ~Node() {}
00082     public:
00087         const std::string& getName() const
00088             { return _name; }
00089 
00094         Node::Type getType() const
00095             { return _type; }
00096 
00103         virtual std::string toString() const = 0;
00104 
00111         virtual void accumulate(XMLAccumulator& acc) const = 0;
00112 
00113     protected:
00114         std::string        _name;
00115         Node::Type _type;    
00116 
00117         // Ensure that no one can initialize this variable without
00118         // using the proper constructor
00119         Node();
00120     };
00121 
00122     // Utility routines
00123     void   unescape(const char* src, unsigned int srcLen, std::string& dest, bool append = false);  
00124     std::string escape(const std::string& src);
00125 
00126     class XMLAccumulator
00127     {
00128     public:
00129         XMLAccumulator(std::string& s)
00130             : _result(s) {}
00131 
00132         void operator()(const Node* n)
00133             { n->accumulate(*this); }
00134         void operator()(const std::pair<const std::string, std::string> p)
00135             { _result += " " + p.first + "='" + 
00136                   escape(p.second) + "'";
00137             }
00138         template <class T>
00139         XMLAccumulator& operator<<(T data)
00140             { _result += data; return *this; }
00141     private:
00142         std::string& _result;
00143     };
00144 
00148     class CDATA : 
00149         public Node
00150     {
00151     public:
00155         CDATA(const char* text, unsigned int textsz, bool escaped = false)
00156             : Node("#CDATA", Node::ntCDATA)
00157             {
00158                 if (escaped)
00159                 {
00160                     unescape(text, textsz, _text);
00161                 }
00162                 else
00163                 {
00164                     _text.assign(text, textsz);
00165                 }
00166             }
00167         
00175         void setText(const char* text, unsigned int textsz, bool escaped = false)
00176             { 
00177                 if (escaped)
00178                 {
00179                     unescape(text, textsz, _text); 
00180                 }
00181                 else
00182                 {
00183                     _text.assign(text, textsz);
00184                 }
00185             }
00186 
00194         void appendText(const char* text, unsigned int textsz, bool escaped = false)
00195             { 
00196                 if (escaped)
00197                 {
00198                     unescape(text, textsz, _text, true); 
00199                 }
00200                 else
00201                 {
00202                     _text.append(text, textsz);
00203                 }
00204             }
00205 
00211         const std::string& getText() const
00212             { return _text; }
00213 
00219         std::string toString() const
00220             { return escape(_text); }
00221 
00222         void accumulate(XMLAccumulator& acc) const
00223             { acc << escape(_text); }
00224 
00225     private:
00226         TESTER(CDATATest)
00227 
00228         std::string _text;           
00229     };
00230 
00234     class Element: 
00235         public Node
00236     {
00237     public:
00238         Element(const std::string& name, const char** attribs = NULL);
00239         Element(const Element& e);
00240         ~Element();
00241 
00242         Element& operator=(const Element& e);
00243 
00244         Element* addElement(const std::string& name, const char** attribs = NULL);
00245         Element* addElement(const std::string& name, const std::string& cdata, 
00246                             bool escaped = false);
00247         CDATA*   addCDATA(const char* data, int datasz, bool escaped = false);  
00248 
00249         void   putAttrib(const std::string& name, const std::string& value);
00250         std::string getAttrib(const std::string& name) const;
00251         void   delAttrib(const std::string& name);
00252         bool   cmpAttrib(const std::string& name, const std::string& value) const;
00253 
00254         std::string toString() const;
00255         std::string toStringEx(bool recursive = false, bool closetag = false) const;
00256 
00257         void accumulate(XMLAccumulator& acc) const;
00258 
00259         std::string getCDATA() const;
00260         
00261 
00262         typedef std::list<Node*>::iterator iterator;
00263         typedef std::list<Node*>::const_iterator const_iterator;
00264 
00269         void appendChild(Node* child)
00270             { _children.push_back(child); }
00271         
00272         Node* detachChild(iterator it);
00273         
00278         bool empty() const
00279             { return _children.empty(); }
00280 
00286         int size() const
00287             { return _children.size(); }
00288         
00292         iterator begin()
00293             { return _children.begin(); }
00294 
00298         const_iterator begin() const
00299             { return _children.begin(); }
00300 
00304         iterator end()
00305             { return _children.end(); }
00306 
00310         const_iterator end() const
00311             { return _children.end(); }
00312 
00313         iterator find(const std::string& name, Node::Type type = Node::ntElement);
00314 
00315         const_iterator find(const std::string& name, Node::Type type = Node::ntElement) const;
00320         void Element::erase(Element::iterator it)
00321             { delete *it; _children.erase(it); }
00322 
00323         Element* findElement(const std::string& name);
00324         const Element* findElement(const std::string& name) const;
00325         void     eraseElement(const std::string& name);
00326 
00327         std::string getChildCData(const std::string& name) const;
00328         int         getChildCDataAsInt(const std::string& name, int defaultvalue) const;
00329 
00330 
00331     protected:
00332         TESTER(ElementTest)
00333         
00334         std::list<Node*>        _children;
00335         std::map<std::string,std::string> _attribs;
00336     };
00337     
00341     class ElementStreamEventListener
00342     {
00343     public:
00344         virtual ~ElementStreamEventListener() {}
00351         virtual void onDocumentStart(Element* e) = 0;
00352 
00360         virtual void onElement(Element* e) = 0;
00361 
00372         virtual void onCDATA(CDATA* c) 
00373             { delete c; }
00374             
00375 
00380         virtual void onDocumentEnd() = 0;
00381     };
00382     
00383 
00387     class ElementStream 
00388     {
00389     public:
00390         ElementStream(ElementStreamEventListener* l);
00391         virtual ~ElementStream();
00392 
00393         void push(const char* data, int datasz);
00394         void reset();
00395 
00396         static Element* parseAtOnce(const char* buffer);
00397 
00398         struct exception
00399         {
00400             class ParserError 
00401                 {
00402                 public:
00403                     ParserError(int code)
00404                         : _code(code), _message(XML_ErrorString(code))
00405                         {}
00406                     const std::string& getMessage() const
00407                         { return _message; }
00408                     int getCode() const
00409                         { return _code; }
00410                 private:
00411                     int _code;
00412                     std::string _message;
00413                 };
00414             class IncompleteParse{};
00415         };
00416 
00417     private:
00418         TESTER(ElementStreamTest)
00419 
00420         XML_Parser     _parser;
00421         bool           _parser_ready;
00422         std::list<Element*> _element_stack;
00423         bool           _document_started;
00424         bool           _document_ended;
00425 
00426         ElementStreamEventListener* _event_listener;
00427 
00428         // Expat callbacks
00429         static void onStartElement(void* userdata, const char* name, const char** attribs);
00430         static void onEndElement(void* userdata, const char* name);
00431         static void onCDATA(void* userdata, const char* cdata, int cdatasz);
00432 
00433         // Expat initializers
00434         void initExpat();
00435         void cleanupExpat();
00436        };
00437 }
00438 #endif

Generated at Tue Apr 16 17:09:06 2002 for jabberoo by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001