|
OpenADFortTk (basic)
|
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 */