INOstream.hxx

Go to the documentation of this file.
00001 #ifndef LIBSHERPA_INOSTREAM_HXX
00002 #define LIBSHERPA_INOSTREAM_HXX
00003 
00004 /**************************************************************************
00005  *
00006  * Copyright (C) 2006, Johns Hopkins University.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or
00010  * without modification, are permitted provided that the following
00011  * conditions are met:
00012  *
00013  *   - Redistributions of source code must contain the above
00014  *     copyright notice, this list of conditions, and the following
00015  *     disclaimer.
00016  *
00017  *   - Redistributions in binary form must reproduce the above
00018  *     copyright notice, this list of conditions, and the following
00019  *     disclaimer in the documentation and/or other materials
00020  *     provided with the distribution.
00021  *
00022  *   - Neither the names of the copyright holders nor the names of any
00023  *     of any contributors may be used to endorse or promote products
00024  *     derived from this software without specific prior written
00025  *     permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00028  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00029  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00030  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00031  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00032  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00033  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00034  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00035  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00037  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  **************************************************************************/
00040 
00041 #include <assert.h>
00042 #include <stdlib.h>
00043 #include <errno.h>
00044 #include <dirent.h>
00045 #include <string.h>
00046 #include <fstream>
00047 #include <iostream>
00048 #include <string>
00049 #include <sstream>
00050 
00051 namespace sherpa {
00052 
00053 // This is a completely sleazy way of making an automatically indenting
00054 // stream.
00055 struct INOstream {
00056   size_t depth;
00057   size_t col;
00058   bool needIndent;
00059   std::ostream &ostrm;
00060 
00061   // Following is useful for emitting block comments. Note that this
00062   // is inserted AFTER indentation occurs
00063   std::string postIndent;
00064 
00065   INOstream(std::ostream &os)
00066     :ostrm(os)
00067   {
00068     depth = 0;
00069     col = 0;
00070     needIndent = true;
00071   }
00072 
00073   void setPostindent(const std::string& s) 
00074   {
00075     postIndent = s;
00076   }
00077 
00078   inline void indent(int i)
00079   {
00080     depth += i;
00081   }
00082 
00083   size_t indent_for_macro()
00084   {
00085     size_t odepth = depth;
00086     depth = 0;
00087     return odepth;
00088   }
00089 
00090   inline int indentToHere()
00091   {
00092     size_t old_depth = depth;
00093     depth = (depth > col) ? depth : col;
00094     return old_depth;
00095   }
00096   inline void setIndent(size_t theCol)
00097   {
00098     depth = theCol;
00099   }
00100 
00101   inline void more()
00102   {
00103     indent(2);
00104   }
00105 
00106   inline void less()
00107   {
00108     assert(depth >= 2);
00109     indent(-2);
00110   }
00111 
00112   void
00113   doIndent()
00114   {
00115     //std::cout << "Indent = " << depth << "; needIndent = " << needIndent << endl;
00116     if (needIndent) {
00117       while (col < depth) {
00118         ostrm << ' ';
00119         col++;
00120       }
00121       ostrm << postIndent;
00122     }
00123     needIndent = false;
00124   }
00125 
00126   inline
00127   INOstream& operator<<(const char c)
00128   {
00129     INOstream& inostrm = *this;
00130     inostrm.doIndent();
00131 
00132     inostrm.ostrm << c;
00133     inostrm.col++;
00134 
00135     if (c == '\n') {
00136       inostrm.col = 0;
00137       inostrm.needIndent = true;
00138     }
00139     return inostrm;
00140   }
00141 
00142   inline
00143   INOstream& operator<<(const unsigned char c)
00144   {
00145     INOstream& inostrm = *this;
00146     inostrm.doIndent();
00147 
00148     inostrm.ostrm << c;
00149     inostrm.col++;
00150     if (c == '\n') {
00151       inostrm.col = 0;
00152       inostrm.needIndent = true;
00153     }
00154     return inostrm;
00155   }
00156 
00157   // This is where the magic happens. The way that a C++ stream recognizes
00158   // things like std::endl is by overloading this argument type. std::endl
00159   // is actually a procedure!
00160   //
00161   // Note, however, that INOstream does not forward the endl. We need
00162   // it in order to recognize when a fill is required, but we don't
00163   // really intend to flush the underlying output stream.
00164   inline
00165   INOstream& operator<<(std::ostream& (*pf)(std::ostream&))
00166   {
00167     INOstream& inostrm = *this;
00168     if (pf == (std::ostream& (*)(std::ostream&)) std::endl) {
00169       inostrm << '\n';
00170     }
00171     else {
00172       inostrm.doIndent();
00173       inostrm.ostrm << pf;
00174     }
00175     return inostrm;
00176   }
00177 
00178   inline
00179   INOstream& operator<<(std::ios_base& (*pf)(std::ios_base&))
00180   {
00181     INOstream& inostrm = *this;
00182     inostrm.doIndent();
00183     inostrm.ostrm << pf;
00184     return inostrm;
00185   }
00186 
00187   inline
00188   INOstream& operator<<(const char *s)
00189   {
00190     INOstream& inostrm = *this;
00191 
00192     for (size_t i = 0; i < strlen(s); i++)
00193       inostrm << s[i];
00194 
00195     return inostrm;
00196   }
00197 
00198 #if 0
00199   inline
00200   INOstream& operator<<(const unsigned long long ull)
00201   {
00202     char digits[64];            // sufficient in all cases
00203     sprintf(digits, "%ull", ull);
00204 
00205     INOstream& inostrm = *this;
00206     inostrm << digits;
00207 
00208     return inostrm;
00209   }
00210 
00211   inline
00212   INOstream& operator<<(const long long ll)
00213   {
00214     char digits[64];            // sufficient in all cases
00215     sprintf(digits, "%ll", ll);
00216 
00217     INOstream& inostrm = *this;
00218     inostrm << digits;
00219 
00220     return inostrm;
00221   }
00222 
00223   inline
00224   INOstream& operator<<(const unsigned long ul)
00225   {
00226     char digits[64];            // sufficient in all cases
00227     sprintf(digits, "%ul", ul);
00228 
00229     INOstream& inostrm = *this;
00230     inostrm << digits;
00231 
00232     return inostrm;
00233   }
00234 
00235   inline
00236   INOstream& operator<<(const long l)
00237   {
00238     char digits[64];            // sufficient in all cases
00239     sprintf(digits, "%l", l);
00240 
00241     INOstream& inostrm = *this;
00242     inostrm << digits;
00243 
00244     return inostrm;
00245   }
00246 
00247   INOstream& operator<<(const unsigned int ui)
00248   {
00249     char digits[64];            // sufficient in all cases
00250     sprintf(digits, "%ul", ui);
00251 
00252     INOstream& inostrm = *this;
00253     inostrm << digits;
00254 
00255     return inostrm;
00256   }
00257 
00258   inline
00259   INOstream& operator<<(const int i)
00260   {
00261     char digits[64];            // sufficient in all cases
00262     sprintf(digits, "%l", i);
00263 
00264     INOstream& inostrm = *this;
00265     inostrm << digits;
00266 
00267     return inostrm;
00268   }
00269 #endif
00270 
00271   inline
00272   INOstream& operator<<(const std::string& s)
00273   {
00274     INOstream& inostrm = *this;
00275 
00276     for (size_t i = 0; i < s.size(); i++)
00277       inostrm << s[i];
00278 
00279     return inostrm;
00280   }
00281 
00282   template<typename T>
00283   inline
00284   INOstream& operator<<(T ob)
00285   {
00286     std::stringstream ss;
00287     ss << ob;
00288 
00289     INOstream& inostrm = *this;
00290     inostrm << ss.str();
00291     return inostrm;
00292   }
00293 
00294 };
00295 
00296 } /* namespace sherpa */
00297 
00298 #endif /* LIBSHERPA_INOSTREAM_HXX */

Generated on Fri Feb 10 07:59:20 2012 for BitC Compiler by  doxygen 1.4.7