xmlostream.h

Go to the documentation of this file.
00001 // -*-Mode: C++;-*-
00002 // $Header: /Volumes/cvsrep/developer/OpenADFortTk/src/lib/support/xmlostream.h,v 1.7 2004/08/05 18:35:24 eraxxon Exp $
00003 
00004 // * BeginCopyright *********************************************************
00005 // *********************************************************** EndCopyright *
00006 
00007 //***************************************************************************
00008 //
00009 // File:
00010 //   $Source: /Volumes/cvsrep/developer/OpenADFortTk/src/lib/support/xmlostream.h,v $
00011 //
00012 // Purpose:
00013 //   [The purpose of this file]
00014 //
00015 // Description:
00016 //   [The set of functions, macros, etc. defined in the file]
00017 //
00018 //***************************************************************************
00019 
00020 #ifndef xmlostream_INCLUDED_h
00021 #define xmlostream_INCLUDED_h
00022 
00023 //************************* System Include Files ****************************
00024 
00025 #include <iostream>
00026 #include <string>
00027 #include <list> // STL
00028 
00029 //*************************** User Include Files ****************************
00030 
00031 //*************************** Forward Declarations ***************************
00032 
00033 //****************************************************************************
00034 
00035 // FIXME: add xml escaping routines
00036 
00037 // ---------------------------------------------------------
00038 // xml::ostream:
00039 // 
00040 // FIXME: we do not require that this be a full xml document (no state
00041 // for dtd, etc.) since one should be able to create subdocuments that
00042 // can be appended to larger ones.
00043 // ---------------------------------------------------------
00044 namespace xml {
00045 
00046 class ostream : public std::ostream {
00047  public:
00048   ostream(std::streambuf* sb);
00049   virtual ~ostream();
00050 
00051   // ---------------------------------------------------------
00052 
00053   class Exception {
00054   public:
00055     Exception (const char* msg_) { msg = msg_; }
00056     virtual ~Exception () { }
00057 
00058     virtual const std::string& GetMessage() const { return msg; }
00059     virtual void Report(std::ostream& os) const { 
00060       os << "xml::ostream::Exception: " << msg << std::endl; 
00061     }    
00062     virtual void Report() const { Report(std::cerr); }
00063 
00064   private: 
00065     std::string msg;
00066   };
00067 
00068   // ---------------------------------------------------------
00069   
00070   // BegElem: Output an incomplete start tag [<tag...] for the
00071   // element 'etag' automatically closing any previous incomplete
00072   // start tags.  The start tag is incomplete so that an arbitrary
00073   // number of attributes can be added.  Indentation is incremented,
00074   // if necessary.
00075   void BegElem(const char* etag)
00076     throw (Exception);
00077 
00078   // EndElem: Output the current element's end tag, using either the
00079   // 'compact' form [<.../>] or the 'normal' form [</tag>], whichever
00080   // is appropriate.  Indentation is decremented, if necessary.
00081   void EndElem();
00082 
00083 
00084   // Attr: Output the attribute 'attr' with the value 'val'
00085   // [attr="val"] for the element's start tag, leaving the stream
00086   // ready to accept another attribute (i.e. the element's start tag
00087   // is still incomplete).  (FIXME: check for invalid character?)
00088   template <class T>
00089     void Attr(const char* attr, const T& val);
00090 
00091   // BegAttr and EndAttr together are equivalent to Attr.  These
00092   // functions are useful, e.g., when the attribute value needs to be
00093   // concatenated together from several sub-values.
00094   
00095   // BegAttr: Prepare the stream for the attribute value,
00096   // automatically closing any previous incomplete attributes.
00097   void BegAttr(const char* attr);
00098 
00099   // EndAttr: End this attribute and prepare the stream for the end of
00100   // the attribute list or another attribute.
00101   void EndAttr();
00102   
00103 
00104   // EndAttrs: Manually complete the attribute list and end the
00105   // current element's start tag (ending any open attribute).  This is
00106   // useful, e.g., if comments or newlines need to be inserted.
00107   void EndAttrs();
00108 
00109   // ---------------------------------------------------------
00110   
00111   // BegComment/EndComment: Ouput an arbitrary comment, automatically
00112   // closing any previous incomplete start tag or attribute.  Comments
00113   // cannot be nested. No indentation. EndComment() ends the current
00114   // line.
00115   void BegComment();
00116   void EndComment();
00117 
00118   // Comment: Output an indented, one-line comment (including
00119   // newline).  A previous incomplete start tag is closed.
00120   void Comment(const char* str);
00121 
00122   // ---------------------------------------------------------
00123 
00124   // Indentation: Both IndentAmnt (whitespace between the left margin
00125   // and the text) and the IndentStep (amount the indentation changes
00126   // for the next level) can be set independently.  It is
00127   // possible to have a negative step, but a negative amount is
00128   // ignored.
00129   void Indent();
00130   void IndentIncr() { indentAmnt += indentStep; }
00131   void IndentDecr() { indentAmnt -= indentStep; }
00132   bool IsIndent() { return (indentStep == 0 && indentAmnt == 0); }
00133 
00134   void SetIndentAmnt(int amnt) { indentAmnt = amnt; }
00135   void SetIndentStep(int step) { indentStep = step; }
00136   int GetIndentAmnt() { return indentAmnt; }
00137   int GetIndentStep() { return indentStep; }
00138   
00139   // FIXME Add a setIndent(xml::ostream) to coordinate indentation settings
00140 
00141  protected:
00142 
00143  private:
00144   // Disable
00145   ostream(const ostream& x);
00146   ostream& operator=(const ostream& x) { return *this; }
00147 
00148   void EndElemUpdateState();
00149 
00150  private: 
00151   // Stack of elements.  (Use a list instead a stack so that we can
00152   // easily examine contents.  The top of the stack will be the
00153   // *front* of the list. (push_front, pop_front).
00154   typedef std::list<std::string>           ElemStack;
00155   typedef std::list<std::string>::iterator ElemStackIt;
00156   typedef std::list<std::string>::const_iterator ElemStackItC;
00157 
00158   enum State {
00159     // A list of mutually exclusive states 
00160     INIT       = 0x00000001, // initial state, nothing has happened
00161     FINI       = 0x00000002, // a complete, top-level element has been finished
00162 
00163     ELEM_OPENI = 0x00000004, // within element, incomplete start tag
00164                              //   no incomplete attrs
00165     ELEM_OPENA = 0x00000008, // within element, incomplete start tag
00166                              //   incomplete attr
00167     ELEM_OPEN  = 0x00000010, // within element, complete start tag
00168 
00169     STMASK     = 0xff000000, // reserves 8 bits for state qualifiers
00170 
00171     // A list of state qualifiers (can co-exist with some/all of the above)
00172     ERR        = 0x10000000, // error
00173     COMMENT    = 0x20000000  // within a comment
00174   };
00175 
00176   // Access to mutually exclusive states (do not use with state qualifiers!)
00177   bool IsState(State st) { return (st & state); }
00178   void SetState(State st) { state = ((state & STMASK) | st); }
00179 
00180   // Access to state qualifiers
00181   bool IsStateError() { return (state & ERR); }
00182   void SetStateError() { state = (state | ERR); }
00183 
00184   bool IsStateComment() { return (state & COMMENT); }
00185   void SetStateComment() { state = (state | COMMENT); }
00186   void ResetStateComment() { state = (state & ~COMMENT); }
00187   
00188  private:
00189   ElemStack elemstack;
00190   unsigned int state;
00191   
00192   int indentAmnt;
00193   int indentStep;
00194 };
00195 
00196 }; /* namespace xml */
00197 
00198 
00199 //***************************************************************************
00200 // Definitions for xml::ostream member template functions
00201 //***************************************************************************
00202 
00203 template<class T> 
00204 void
00205 xml::ostream::Attr(const char* attr, const T& val)
00206 {
00207   // Sanity check -- rely on BegAttr()
00208 
00209   BegAttr(attr);
00210   (*this) << val;
00211   EndAttr();
00212 }
00213 
00214 //***************************************************************************
00215 // xml::ostream operators that take no arguments
00216 //***************************************************************************
00217 
00218 namespace xml {
00219 
00220 typedef ostream& (*omanip)(ostream&);
00221 
00222 inline ostream& 
00223 operator<<(std::ostream& os, omanip f)
00224 { 
00225   ostream& xos = dynamic_cast<ostream&>(os);
00226   return f(xos);
00227 }
00228 
00229 
00230 inline ostream& 
00231 EndElem(ostream& xos)
00232 { 
00233   xos.EndElem();
00234   return xos;
00235 }
00236 
00237 inline ostream& 
00238 EndAttr(ostream& xos)
00239 { 
00240   xos.EndAttr();
00241   return xos;
00242 }
00243 
00244 inline ostream& 
00245 EndAttrs(ostream& xos)
00246 { 
00247   xos.EndAttrs();
00248   return xos;
00249 }
00250 
00251 
00252 inline ostream& 
00253 BegComment(ostream& xos)
00254 { 
00255   xos.BegComment();
00256   return xos;
00257 }
00258 
00259 inline ostream& 
00260 EndComment(ostream& xos)
00261 { 
00262   xos.EndComment();
00263   return xos;
00264 }
00265 
00266 
00267 inline ostream& 
00268 Indent(ostream& xos)
00269 { 
00270   xos.Indent();
00271   return xos;
00272 }
00273 
00274 inline ostream& 
00275 IndentIncr(ostream& xos)
00276 { 
00277   xos.IndentIncr();
00278   return xos;
00279 }
00280 
00281 inline ostream& 
00282 IndentDecr(ostream& xos)
00283 { 
00284   xos.IndentDecr();
00285   return xos;
00286 }
00287 
00288 }; /* namespace xml */
00289 
00290 
00291 //***************************************************************************
00292 // xml::ostream operators that take arguments
00293 //***************************************************************************
00294 
00295 namespace xml {
00296 
00297 // ---------------------------------------------------------
00298 // BegElem
00299 // ---------------------------------------------------------
00300 struct BegElemInfo_ {
00301   const char* etag;
00302 };
00303 
00304 inline ostream&
00305 operator<<(std::ostream& os, const BegElemInfo_ x) // ok to pass x directly
00306 {
00307   ostream& xos = dynamic_cast<ostream&>(os); // FIXME
00308   xos.BegElem(x.etag);
00309   return xos;
00310 }
00311 
00312 inline BegElemInfo_ 
00313 BegElem(const char* etag_)
00314 {
00315   BegElemInfo_ x;
00316   x.etag = etag_;
00317   return x;
00318 }
00319 
00320 // ---------------------------------------------------------
00321 // Attr
00322 // ---------------------------------------------------------
00323 template<class T> 
00324 struct AttrInfo_ {
00325   const char* attr;
00326   const T* val;
00327 };
00328 
00329 template<class T> 
00330 ostream& 
00331 operator<<(std::ostream& os, const AttrInfo_<T>& x)
00332 {
00333   ostream& xos = dynamic_cast<ostream&>(os);
00334   xos.Attr(x.attr, *x.val);
00335   return xos;
00336 }
00337 
00338 template<class T> 
00339 AttrInfo_<T>
00340 Attr(const char* attr_, const T& val_)
00341 {
00342   AttrInfo_<T> x;
00343   x.attr = attr_;
00344   x.val = &val_;
00345   return x;
00346 }
00347 
00348 // ---------------------------------------------------------
00349 // BegAttr
00350 // ---------------------------------------------------------
00351 struct BegAttrInfo_ {
00352   const char* attr;
00353 };
00354 
00355 inline ostream&
00356 operator<<(std::ostream& os, const BegAttrInfo_ x) // ok to pass x directly
00357 {
00358   ostream& xos = dynamic_cast<ostream&>(os); // FIXME
00359   xos.BegAttr(x.attr);
00360   return xos;
00361 }
00362 
00363 inline BegAttrInfo_ 
00364 BegAttr(const char* attr_)
00365 {
00366   BegAttrInfo_ x;
00367   x.attr = attr_;
00368   return x;
00369 }
00370 
00371 // ---------------------------------------------------------
00372 // Comment
00373 // ---------------------------------------------------------
00374 struct CommentInfo_ {
00375   const char* str;
00376 };
00377 
00378 inline ostream&
00379 operator<<(std::ostream& os, const CommentInfo_ x) // ok to pass x directly
00380 {
00381   ostream& xos = dynamic_cast<ostream&>(os);
00382   xos.Comment(x.str);
00383   return xos;
00384 }
00385 
00386 inline CommentInfo_ 
00387 Comment(const char* str_)
00388 {
00389   CommentInfo_ x;
00390   x.str = str_;
00391   return x;
00392 }
00393 
00394 // ---------------------------------------------------------
00395 // SetIndentAmnt
00396 // ---------------------------------------------------------
00397 struct IndentAmntInfo_ {
00398   int amnt;
00399 };
00400 
00401 inline ostream& 
00402 operator<<(std::ostream& os, const IndentAmntInfo_ x) // ok to pass x directly
00403 {
00404   ostream& xos = dynamic_cast<ostream&>(os);
00405   xos.SetIndentAmnt(x.amnt);
00406   return xos;
00407 }
00408 
00409 inline IndentAmntInfo_ 
00410 SetIndentAmnt(int amnt_)
00411 {
00412   IndentAmntInfo_ x;
00413   x.amnt = amnt_;
00414   return x;
00415 }
00416 
00417 // ---------------------------------------------------------
00418 // SetIndentStep
00419 // ---------------------------------------------------------
00420 struct IndentStepInfo_ {
00421   int step;
00422 };
00423 
00424 inline ostream& 
00425 operator<<(std::ostream& os, const IndentStepInfo_ x) // ok to pass x directly
00426 {
00427   ostream& xos = dynamic_cast<ostream&>(os);
00428   xos.SetIndentStep(x.step);
00429   return xos;
00430 }
00431 
00432 inline IndentStepInfo_ 
00433 SetIndentStep(int step_)
00434 {
00435   IndentStepInfo_ x;
00436   x.step = step_;
00437   return x;
00438 }
00439 
00440 }; /* namespace xml */
00441 
00442 //****************************************************************************
00443 
00444 // FIXME:
00445 inline void Append_Token_String(xml::ostream& xos, const char *string)
00446 {
00447   xos << string << " ";
00448 }
00449 
00450 //****************************************************************************
00451 
00452 #endif /* xmlostream_INLUCDED_h */

Generated on Fri Jul 24 04:29:08 2009 for OpenADFortTk (extended to Open64) by  doxygen 1.5.7.1