sexpostream.h

Go to the documentation of this file.
00001 // -*-Mode: C++;-*-
00002 // $Header: /Volumes/cvsrep/developer/OpenADFortTk/src/lib/support/sexpostream.h,v 1.7 2005/01/17 15:22:50 eraxxon Exp $
00003 
00004 // * BeginCopyright *********************************************************
00005 // *********************************************************** EndCopyright *
00006 
00007 //***************************************************************************
00008 //
00009 // File:
00010 //   $Source: /Volumes/cvsrep/developer/OpenADFortTk/src/lib/support/sexpostream.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 sexpostream_INCLUDED_h
00021 #define sexpostream_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 // ---------------------------------------------------------
00036 // sexp::ostream:
00037 // 
00038 // An ostream class for generating S-expressions.
00039 // ---------------------------------------------------------
00040 namespace sexp {
00041 
00042   namespace IOFlags {
00043     
00044     enum IOFlags_t {
00045       ATOM_MASK  = 0x0000ffff, // reserves x bits for atom flags
00046       LIST_MASK  = 0xffff0000, // reserves x bits for list flags
00047       
00048       NONE       = 0x00000000, // no flag
00049       
00050       // atom flags
00051       A_SQUOTE   = 0x00000001, // single quote atom: 'x (tick-mark)
00052       A_DQUOTE   = 0x00000002, // double quote atom: "x" (uses EscapeString)
00053       A_OCT      = 0x00000010, // use oct mode; revert to dec 
00054       A_HEX      = 0x00000020, // use hex mode; revert to dec
00055 
00056       // list flags
00057       L_foofoo1  = 0x10000000, // ...
00058       
00059       L_NONEMPTY = 0x80000000  // internal use: list is not empty
00060     };
00061     
00062     inline bool 
00063     IsFlag(int flags, IOFlags_t flg) { return (flags & flg); }
00064     
00065     inline void 
00066     SetFlag(int& flags, IOFlags_t flg) { flags = (flags | flg); }
00067     
00068     inline void 
00069     ResetFlag(int& flags, IOFlags_t flg) { flags = (flags & ~flg); }
00070     
00071   } /* namespace IOFlags */
00072 
00073 
00074 class ostream : public std::ostream {
00075  public:
00076   ostream(std::streambuf* sb);
00077   virtual ~ostream();
00078 
00079   // ---------------------------------------------------------
00080 
00081   class Exception {
00082   public:
00083     Exception (const char* msg_) { msg = msg_; }
00084     virtual ~Exception () { }
00085 
00086     virtual const std::string& GetMessage() const { return msg; }
00087     virtual void Report(std::ostream& os) const { 
00088       os << "sexp::ostream::Exception: " << msg << std::endl; 
00089     }    
00090     virtual void Report() const { Report(std::cerr); }
00091 
00092   private: 
00093     std::string msg;
00094   };
00095   
00096   // ---------------------------------------------------------
00097 
00098   // Atom: Output the sexp-atom 'atom', leaving the stream ready to
00099   // accept another sexp. Uses the atom flag to override default
00100   // formatting for this atom.
00101   // N.B.: See specializations below
00102   template <class T>
00103     void Atom(int xflags, const T& val);
00104 
00105   template <class T>
00106     void Atom(const T& val) { Atom(IOFlags::NONE, val); }
00107   
00108 
00109   // BegAtom and EndAtom together are equivalent to Atom.  These
00110   // functions are useful, e.g., when the atom needs to be
00111   // formed from several sub-strings.
00112   
00113   // BegAtom: Prepare the stream for the atom, using flags for formatting.
00114   void BegAtom(int xflags = IOFlags::NONE);
00115   
00116   // EndAtom: End the atom and prepare the stream for another sexp.
00117   void EndAtom();
00118 
00119   
00120   // BegList: Generate a new list [(...], using flags to override
00121   // default formatting (atom flags apply to all atoms in list).
00122   // Indentation is incremented, if necessary.
00123   void BegList(int xflags = IOFlags::NONE)
00124     throw (Exception);
00125 
00126   // EndList: End the current list [...)].  Indentation is decremented, if
00127   // necessary.
00128   void EndList();
00129     
00130 
00131   // Quote: Quote the subsequent S-expression (atom or list) (e.g. 'x)
00132   void Quote();
00133     
00134   // ---------------------------------------------------------
00135   
00136   // BegComment/EndComment: Ouput an arbitrary comment at the end of
00137   // the current line.  Note that EndComment() necessarily ends the
00138   // line.
00139   void BegComment();
00140   void EndComment();
00141 
00142   // Comment: Output an indented, one-line comment (including
00143   // newline).  A previous incomplete start tag is closed.
00144   void Comment(const char* str);
00145 
00146   // ---------------------------------------------------------
00147 
00148   // EscapeString: Output an escaped string, ready for double quotes.
00149   void EscapeString(const char* val);
00150   
00151   // ---------------------------------------------------------
00152   
00153   // EndLine: Output a new line and set prepare indentation.
00154   void EndLine();
00155   
00156   // Indentation: Both IndentAmnt (whitespace between the left margin
00157   // and the text) and the IndentStep (amount the indentation changes
00158   // for the next level) can be set independently.  It is
00159   // possible to have a negative step, but a negative amount is
00160   // ignored.
00161   void Indent();
00162   void IndentIncr() { indentAmnt += indentStep; }
00163   void IndentDecr() { indentAmnt -= indentStep; }
00164   bool IsIndent() { return (indentStep == 0 && indentAmnt == 0); }
00165 
00166   void SetIndentAmnt(int amnt) { indentAmnt = amnt; }
00167   void SetIndentStep(int step) { indentStep = step; }
00168   int GetIndentAmnt() { return indentAmnt; }
00169   int GetIndentStep() { return indentStep; }
00170   
00171   // FIXME Add a setIndent(sexp::ostream) to coordinate indentation settings
00172 
00173  protected:
00174 
00175  private:
00176   // Disable
00177   ostream(const ostream& x);
00178   ostream& operator=(const ostream& x) { return *this; }
00179 
00180   void AddSpaceIfNecessary(int flags);
00181   
00182  private: 
00183   // Stack of elements.  Contains IOFlags::IOFlags_t that apply to the
00184   // current list.  (Use a list instead a stack so that we can easily
00185   // examine contents.  The top of the stack will be the *front* of
00186   // the list. (push_front, pop_front).
00187   typedef std::list<int> SListStack; 
00188   
00189  private: 
00190 
00191   enum State {
00192     // A list of mutually exclusive states 
00193     INIT       = 0x00000001, // initial state, nothing has happened
00194     DEFAULT    = 0x00000002, // no open list; ATOM_OPEN is possible
00195     LIST_OPEN  = 0x00000004, // open list; ATOM_OPEN is possible
00196     
00197     STMASK     = 0xff000000, // reserves 8 bits for state qualifiers
00198     
00199     // A list of state qualifiers (can co-exist with some/all of the above)
00200     ERR        = 0x10000000, // error
00201     ATOM_OPEN  = 0x20000000, // open atom
00202     COMMENT    = 0x40000000  // within a comment
00203   };
00204   
00205   enum Action {
00206     // A list of mutually exclusive actions, affecting context of sexp
00207     QUOTE,
00208     BEG_ATOM, END_ATOM,
00209     BEG_LIST, END_LIST,
00210     BEG_COMMENT, END_COMMENT, 
00211     END_LINE,
00212     INDENT
00213   };
00214 
00215   // Access to mutually exclusive states (do not use with state qualifiers!)
00216   bool IsState(State st) { return (st & state); }
00217   void SetState(State st) { state = ((state & STMASK) | st); }
00218   
00219   // Access to state qualifiers
00220   bool IsStateError() { return (state & ERR); }
00221   void SetStateError() { state = (state | ERR); }
00222   
00223   bool IsStateQ(State st) { return (state & st); }
00224   void SetStateQ(State st) { state = (state | st); }
00225   void ResetStateQ(State st) { state = (state & ~st); }
00226 
00227   bool IsStateQClear() { return ((state & STMASK) == 0); }
00228 
00229   // Access to actions
00230   bool WasAction(Action a) { return (lastAction == a); }
00231   void SetAction(Action a) { lastAction = a; }
00232   
00233  private:
00234   SListStack slistStack; // represents nesting level of sexp-lists
00235   int curAtomFlags;      // flags for the current atom only
00236   unsigned int state;
00237   Action lastAction;     // most recent action
00238   
00239   int indentAmnt;
00240   int indentStep;
00241 };
00242 
00243 }; /* namespace sexp */
00244 
00245 
00246 //***************************************************************************
00247 // Definitions/specializations for sexp::ostream member template functions
00248 //***************************************************************************
00249 
00250 namespace sexp {
00251 
00252 template<class T> 
00253 void
00254 sexp::ostream::Atom(int xflags, const T& val)
00255 {
00256   // Sanity check -- rely on BegAtom()
00257   BegAtom(xflags);
00258   (*this) << val;
00259   EndAtom();
00260 }
00261 
00262 template <>
00263 void 
00264 sexp::ostream::Atom(int xflags, const char* const & val);
00265 
00266 }
00267 
00268 //***************************************************************************
00269 // sexp::ostream operators that take no arguments
00270 //***************************************************************************
00271 
00272 namespace sexp {
00273 
00274 typedef ostream& (*omanip)(ostream&);
00275 
00276 inline ostream& 
00277 operator<<(std::ostream& os, omanip f)
00278 { 
00279   ostream& sos = dynamic_cast<ostream&>(os);
00280   return f(sos);
00281 }
00282 
00283 
00284 inline ostream& 
00285 EndAtom(ostream& sos)
00286 { 
00287   sos.EndAtom();
00288   return sos;
00289 }
00290 
00291 inline ostream& 
00292 EndList(ostream& sos)
00293 { 
00294   sos.EndList();
00295   return sos;
00296 }
00297 
00298 inline ostream& 
00299 Quote(ostream& sos)
00300 { 
00301   sos.Quote();
00302   return sos;
00303 }
00304 
00305 
00306 inline ostream& 
00307 BegComment(ostream& sos)
00308 { 
00309   sos.BegComment();
00310   return sos;
00311 }
00312 
00313 inline ostream& 
00314 EndComment(ostream& sos)
00315 { 
00316   sos.EndComment();
00317   return sos;
00318 }
00319 
00320 
00321 inline ostream& 
00322 EndLine(ostream& sos)
00323 { 
00324   sos.EndLine();
00325   return sos;
00326 }
00327 
00328 inline ostream& 
00329 Indent(ostream& sos)
00330 { 
00331   sos.Indent();
00332   return sos;
00333 }
00334 
00335 inline ostream& 
00336 IndentIncr(ostream& sos)
00337 { 
00338   sos.IndentIncr();
00339   return sos;
00340 }
00341 
00342 inline ostream& 
00343 IndentDecr(ostream& sos)
00344 { 
00345   sos.IndentDecr();
00346   return sos;
00347 }
00348 
00349 }; /* namespace sexp */
00350 
00351 
00352 //***************************************************************************
00353 // sexp::ostream operators that take arguments
00354 //***************************************************************************
00355 
00356 namespace sexp {
00357 
00358 // ---------------------------------------------------------
00359 // BegAtom, BegList
00360 // ---------------------------------------------------------
00361 struct FlagElemInfo_ {
00362   int flags;
00363 };
00364 
00365 inline ostream&
00366 operator<<(std::ostream& os, const FlagElemInfo_ x) // ok to pass x directly
00367 {
00368   ostream& sos = dynamic_cast<ostream&>(os); // FIXME
00369   sos.BegList(x.flags);
00370   return sos;
00371 }
00372 
00373 inline FlagElemInfo_ 
00374 BegAtom(int flags)
00375 {
00376   FlagElemInfo_ x;
00377   x.flags = flags;
00378   return x;
00379 }
00380 
00381 inline ostream&
00382 BegAtom(ostream& sos)
00383 {
00384   sos.BegAtom();
00385   return sos;
00386 }
00387 
00388 inline FlagElemInfo_ 
00389 BegList(int flags)
00390 {
00391   FlagElemInfo_ x;
00392   x.flags = flags;
00393   return x;
00394 }
00395 
00396 inline ostream&
00397 BegList(ostream& sos)
00398 {
00399   sos.BegList();
00400   return sos;
00401 }
00402 
00403 
00404 // ---------------------------------------------------------
00405 // Atom
00406 // ---------------------------------------------------------
00407 
00408 template<class T> 
00409 struct AtomInfo_ {
00410   AtomInfo_(int f, const T& v) : flags(f), val(v) { }
00411   int flags;
00412   const T& val;
00413 };
00414 
00415 template<class T> 
00416 ostream& 
00417 operator<<(std::ostream& os, const AtomInfo_<T>& x)
00418 {
00419   ostream& sos = dynamic_cast<ostream&>(os); // FIXME
00420   sos.Atom(x.flags, x.val);
00421   return sos;
00422 }
00423 
00424 template<class T> 
00425 AtomInfo_<T>
00426 Atom(int xflags, const T& val)
00427 {
00428   AtomInfo_<T> x(xflags, val);
00429   return x;
00430 }
00431 
00432 template<class T> 
00433 AtomInfo_<T>
00434 Atom(const T& val)
00435 {
00436   AtomInfo_<T> x(IOFlags::NONE, val);
00437   return x;
00438 }
00439 
00440 
00441 // ---------------------------------------------------------
00442 // Comment
00443 // ---------------------------------------------------------
00444 struct CommentInfo_ {
00445   const char* str;
00446 };
00447 
00448 inline ostream&
00449 operator<<(std::ostream& os, const CommentInfo_ x) // ok to pass x directly
00450 {
00451   ostream& sos = dynamic_cast<ostream&>(os);
00452   sos.Comment(x.str);
00453   return sos;
00454 }
00455 
00456 inline CommentInfo_ 
00457 Comment(const char* str_)
00458 {
00459   CommentInfo_ x;
00460   x.str = str_;
00461   return x;
00462 }
00463 
00464 
00465 // ---------------------------------------------------------
00466 // Escape
00467 // ---------------------------------------------------------
00468 
00469 struct EscapeStringInfo_ {
00470   EscapeStringInfo_(const char* v) : val(v) { }
00471   const char* val;
00472 };
00473 
00474 inline ostream& 
00475 operator<<(std::ostream& os, const EscapeStringInfo_& x)
00476 {
00477   ostream& sos = dynamic_cast<ostream&>(os); // FIXME
00478   sos.EscapeString(x.val);
00479   return sos;
00480 }
00481 
00482 inline EscapeStringInfo_
00483 EscapeString(const char* val)
00484 {
00485   EscapeStringInfo_ x(val);
00486   return x;
00487 }
00488 
00489 
00490 // ---------------------------------------------------------
00491 // SetIndentAmnt
00492 // ---------------------------------------------------------
00493 struct IndentAmntInfo_ {
00494   int amnt;
00495 };
00496 
00497 inline ostream& 
00498 operator<<(std::ostream& os, const IndentAmntInfo_ x) // ok to pass x directly
00499 {
00500   ostream& sos = dynamic_cast<ostream&>(os);
00501   sos.SetIndentAmnt(x.amnt);
00502   return sos;
00503 }
00504 
00505 inline IndentAmntInfo_ 
00506 SetIndentAmnt(int amnt_)
00507 {
00508   IndentAmntInfo_ x;
00509   x.amnt = amnt_;
00510   return x;
00511 }
00512 
00513 // ---------------------------------------------------------
00514 // SetIndentStep
00515 // ---------------------------------------------------------
00516 struct IndentStepInfo_ {
00517   int step;
00518 };
00519 
00520 inline ostream& 
00521 operator<<(std::ostream& os, const IndentStepInfo_ x) // ok to pass x directly
00522 {
00523   ostream& sos = dynamic_cast<ostream&>(os);
00524   sos.SetIndentStep(x.step);
00525   return sos;
00526 }
00527 
00528 inline IndentStepInfo_ 
00529 SetIndentStep(int step_)
00530 {
00531   IndentStepInfo_ x;
00532   x.step = step_;
00533   return x;
00534 }
00535 
00536 }; /* namespace sexp */
00537 
00538 //****************************************************************************
00539 
00540 #endif /* sexpostream_INLUCDED_h */

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