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