reSIProcate/stack  9373
XMLCursor.hxx
Go to the documentation of this file.
00001 #if !defined(RESIP_XMLCURSOR_HXX)
00002 #define RESIP_XMLCURSOR_HXX 
00003 
00004 #include <iosfwd>
00005 #include <vector>
00006 
00007 #include "rutil/ParseBuffer.hxx"
00008 #include "rutil/HashMap.hxx"
00009 
00010 namespace resip
00011 {
00012 
00013 /*
00014 // XML tree traversal.
00015 // XMLCursor starts at the root.
00016 // The attributes and value of the cursor are those of the root.
00017 // To descend to the first child of the root, call firstChild().
00018 // To traverse the children of root from root, call firstChild();nextSibling();nextSibling();...
00019 // To descend into the first child of the current element, call firstChild.
00020 // To return to the parent of the current element, call parent.
00021 // The traversal state among the siblings of the parent is maintained.
00022 //
00023 //                          root
00024 //                        /     \
00025 //                       P1     P2
00026 //                      /  \   /  \
00027 //                     A1  A2 B1  B2
00028 //
00029 //  atRoot() == true;
00030 //  firstChild(); // P1
00031 //  firstChild(); // A1
00032 //  nextSibling(); // A2
00033 //  parent();   // P1
00034 //  nextSibling(); // P2
00035 //  firstChild(); // B1
00036 //  nextSibling(); // B2
00037 //  parent();   // P2
00038 //  nextSibling(); // false, stay at P2
00039 //  parent();   // root
00040 //  nextSibling(); // false, stay at root
00041 //  parent();   // false, stay at root
00042 //  firstChild(); // P1
00043 
00044 // E.g.: Depth first traversal
00045 //
00046 // void traverse(XMLCursor& c)
00047 // {
00048 //    if (c.firstChild())
00049 //    {
00050 //       traverse(c);
00051 //       c.parent();
00052 //    }
00053 // 
00054 //    process(c);
00055 //    
00056 //    if (c.nextSibling())
00057 //    {
00058 //       traverse(c);
00059 //    }
00060 // }
00061 //
00062 // E.g.: Lexical Order traversal
00063 //
00064 // void
00065 // traverse(XMLCursor& c, int i = 0)
00066 // {
00067 //    for (int ii = 0; ii < i; ++ii)
00068 //    {
00069 //       cerr << " ";
00070 //    }
00071 
00072 //    cerr << c.getTag();
00073 //    if (c.atLeaf())
00074 //    {
00075 //       cerr << "[" << c.getValue() << "]" << endl;
00076 //    }
00077 //    else
00078 //    {
00079 //       cerr << endl;
00080 //    }
00081 
00082 //    if (c.firstChild())
00083 //    {
00084 //       traverse(c, i+2);
00085 //       c.parent();
00086 //    }
00087    
00088 //    if (c.nextSibling())
00089 //    {
00090 //       traverse(c, i+2);
00091 //    }
00092 // }
00093 
00094 */
00095 
00096 class XMLCursor
00097 {
00098    public:
00099       // !dlb! should be determined by the document
00100       // see http://www.w3.org/TR/1998/REC-xml-19980210#sec-white-space
00101       enum {WhitespaceSignificant = false};
00102 
00103       XMLCursor(const ParseBuffer& pb);
00104       ~XMLCursor();
00105 
00106       bool nextSibling();
00107       bool firstChild();
00108       bool parent();
00109       void reset();
00110 
00111       bool atRoot() const;
00112       bool atLeaf() const;
00113 
00114       const Data& getTag() const;
00115       typedef HashMap<Data, Data> AttributeMap;
00116       const AttributeMap& getAttributes() const;
00117       const Data& getValue() const;
00118 
00119       static EncodeStream& encode(EncodeStream& strm, const AttributeMap& attrs);
00120       class Node;
00121 
00122                 class AttributeValueEqual {
00123                         Data data_;
00124                         public:
00125                                 AttributeValueEqual(const Data& data) : data_(data) {};
00126                                 bool operator()(const std::pair<Data, Data>& data) { return data.second == data_; }
00127                 };
00128 
00129    private:
00130       static void skipProlog(ParseBuffer& pb);
00131       static void decode(Data&);
00132       static void decodeName(Data&);
00133 
00134       void parseNextRootChild();
00135 
00136 
00137       Node* mRoot;
00138       Node* mCursor;
00139 
00140       //bool isEmpty;
00141 
00142       // store for undecoded root tag
00143       Data mTag;
00144 
00145       // store for copy of input if commented
00146       Data mData;
00147 
00148       // store date for decoding
00149       mutable Data mValue;
00150       // store attributes for reference
00151       mutable AttributeMap mAttributes;
00152       mutable bool mAttributesSet;
00153 
00154 public:
00155       class Node
00156       {
00157          public:
00158             Node(const ParseBuffer& pb);
00159             ~Node();
00160 
00161             void addChild(Node*);
00162             // return true if <foo/>
00163             bool extractTag();
00164             void skipToEndTag();
00165             static const char* skipComments(ParseBuffer& pb);
00166 
00167             ParseBuffer mPb;
00168             Node* mParent;
00169             std::vector<Node*> mChildren;
00170             std::vector<Node*>::const_iterator mNext;
00171 
00172             bool mIsLeaf;
00173             Data mTag;
00174 
00175          private:
00176             Node(const Node&);
00177             Node& operator=(const Node&);
00178 
00179             friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor& cursor);
00180             // friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor::Node& cursor); // this line won't compile in windows 
00181       };
00182    private:
00183       friend EncodeStream& operator<<(EncodeStream&, const XMLCursor&);
00184       friend EncodeStream& operator<<(EncodeStream&, const XMLCursor::Node&);
00185 
00186       // no value semantics
00187       XMLCursor(const XMLCursor&);
00188       XMLCursor& operator=(const XMLCursor&);
00189       friend class Node;
00190 };
00191 
00192 EncodeStream&
00193 operator<<(EncodeStream& str, const XMLCursor& cursor);
00194 
00195 EncodeStream&
00196 operator<<(EncodeStream& str, const XMLCursor::Node& cursor);
00197 
00198 }
00199 
00200 #endif
00201 
00202 /* ====================================================================
00203  * The Vovida Software License, Version 1.0 
00204  * 
00205  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00206  * 
00207  * Redistribution and use in source and binary forms, with or without
00208  * modification, are permitted provided that the following conditions
00209  * are met:
00210  * 
00211  * 1. Redistributions of source code must retain the above copyright
00212  *    notice, this list of conditions and the following disclaimer.
00213  * 
00214  * 2. Redistributions in binary form must reproduce the above copyright
00215  *    notice, this list of conditions and the following disclaimer in
00216  *    the documentation and/or other materials provided with the
00217  *    distribution.
00218  * 
00219  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00220  *    and "Vovida Open Communication Application Library (VOCAL)" must
00221  *    not be used to endorse or promote products derived from this
00222  *    software without prior written permission. For written
00223  *    permission, please contact vocal@vovida.org.
00224  *
00225  * 4. Products derived from this software may not be called "VOCAL", nor
00226  *    may "VOCAL" appear in their name, without prior written
00227  *    permission of Vovida Networks, Inc.
00228  * 
00229  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00230  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00231  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00232  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00233  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00234  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00235  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00236  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00237  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00238  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00239  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00240  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00241  * DAMAGE.
00242  * 
00243  * ====================================================================
00244  * 
00245  * This software consists of voluntary contributions made by Vovida
00246  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00247  * Inc.  For more information on Vovida Networks, Inc., please see
00248  * <http://www.vovida.org/>.
00249  *
00250  */