stlab.adobe.com Adobe Systems Incorporated

istream.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef ADOBE_ISTREAM_HPP
00010 #define ADOBE_ISTREAM_HPP
00011 
00012 #include <adobe/config.hpp>
00013 
00014 #include <ios>
00015 #include <istream>
00016 #include <stdexcept>
00017 #include <vector>
00018 
00019 #include <adobe/name_fwd.hpp>
00020 #include <adobe/istream_fwd.hpp>
00021 
00022 #include <boost/any.hpp>
00023 #include <boost/shared_ptr.hpp>
00024 #include <boost/function.hpp>
00025 
00026 /*************************************************************************************************/
00027 
00028 namespace adobe {
00029 
00030 /*************************************************************************************************/
00031 
00032 #if 0
00033 std::istream& getline(std::istream& is, std::string& str);
00034 #endif
00035 
00036 /*************************************************************************************************/
00037 
00077 //***************************************************************************//
00078 //***************************************************************************//
00079 //***************************************************************************//
00080 
00133 //***************************************************************************//
00134 //***************************************************************************//
00135 //***************************************************************************//
00136 
00151 // line_position_t is used to remember a position on a particular line of a file.
00152 
00153 struct line_position_t
00154 {
00155 public:
00156     typedef boost::function<std::string (name_t, std::streampos)>    getline_proc_impl_t;
00157     typedef boost::shared_ptr<getline_proc_impl_t>                          getline_proc_t;
00158 
00159     // line_number starts at 1.
00160     line_position_t(    name_t   file_path,
00161                         getline_proc_t  getline_proc,
00162                         int             line_number = 1,
00163                         std::streampos  line_start = 0,
00164                         std::streampos  position = -1);
00165 
00166     // This constructor is used with __FILE__ and __LINE__, line_index starts at 0
00167     explicit line_position_t(const char*, int line_index = 0);
00168 
00169 #if !defined(ADOBE_NO_DOCUMENTATION)
00170     line_position_t();
00171 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00172 
00173     const char* stream_name() const
00174         { return file_name_m.c_str(); }
00175 
00176     std::string file_snippet() const
00177     {
00178         return getline_proc_m ?
00179             (*getline_proc_m)(file_name_m, line_start_m) :
00180             std::string();
00181     }
00182 
00183     int             line_number_m; // type int to match __LINE__ token
00184     std::streampos  line_start_m;
00185     std::streampos  position_m;
00186 
00187 #if !defined(ADOBE_NO_DOCUMENTATION)
00188 private:
00189     name_t   file_name_m;
00190     getline_proc_t  getline_proc_m;
00191 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00192 };
00193 
00194 /*************************************************************************************************/
00195 
00196 std::ostream& operator<<(std::ostream&, const line_position_t&);
00197 
00198 /*************************************************************************************************/
00199 
00200 class stream_error_t : public std::logic_error
00201 {
00202  public:
00203     typedef std::vector<line_position_t> position_set_t;
00204  
00205     stream_error_t(const std::exception& base, const line_position_t& position) :
00206         std::logic_error(base.what())
00207      {
00208         try {
00209             const stream_error_t* error = dynamic_cast<const stream_error_t*>(&base);
00210                 
00211             if (error) line_position_set_m = error->line_position_set_m;
00212             
00213             line_position_set_m.push_back(position);
00214         } catch (...) { }
00215     }
00216     
00217     stream_error_t(const char* what, const line_position_t& position) :
00218         std::logic_error(what),
00219         line_position_set_m(1, position)
00220     { }
00221     
00222     stream_error_t(const std::string& what, const line_position_t& position) :
00223         std::logic_error(what),
00224         line_position_set_m(1, position)
00225     { }
00226 
00227     const position_set_t& line_position_set() const
00228     { return line_position_set_m; }
00229 
00230 #if !defined(ADOBE_NO_DOCUMENTATION)
00231     ~stream_error_t() throw()
00232     { }
00233  
00234 private:
00235     position_set_t line_position_set_m;
00236 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00237 };
00238 
00239 /*************************************************************************************************/
00240 
00241 /*
00242     REVISIT (sparent) : I'm not certain this code is correct when used with an istream iterator
00243     which might do line ending conversions with operator <<. Read up on this.
00244 */
00245 
00246 /*
00247     REVISIT (sparent) : The interface to is_line_end should take an iterator pair and return
00248     a pair (first, bool) - not work on a reference to first.
00249 */
00250 
00251 template <typename I> // I models InputIterator
00252 bool is_line_end(I& first, I last)
00253 {
00254     // Handle any type of line ending.
00255 
00256     typename std::iterator_traits<I>::value_type c(*first);
00257 
00258     if (c != '\n' && c != '\r') return false;
00259 
00260     ++first;
00261 
00262     if (c == '\r' && first != last && *first == '\n') ++first;
00263 
00264     return true;
00265 }
00266 
00267 /*************************************************************************************************/
00268 
00269 template <typename I> // I models InputIterator
00270 std::size_t is_line_end(I& first, I last, char c)
00271 {
00272     // Handle any type of line ending.
00273 
00274     if (c == '\n') return 1;
00275 
00276     if (c == '\r')
00277     {
00278         if (first != last && *first == '\n')
00279         {
00280             ++first;
00281 
00282             return 2;
00283         }
00284 
00285         return 1;
00286     }
00287 
00288     return 0;
00289 }
00290 
00291 /*************************************************************************************************/
00292 
00293 template <typename I> // I models InputIterator
00294 std::pair<I, std::string> get_line(I first, I last)
00295 {
00296     std::string result;
00297     
00298     while (first != last && !is_line_end(first, last))
00299     {
00300         result.append(1, *first);
00301         ++ first;
00302     }
00303     
00304     return std::make_pair(first, result);
00305 }
00306 
00307 /*************************************************************************************************/
00308 
00309 } // namespace adobe
00310 
00311 /*************************************************************************************************/
00312 
00313 #endif
00314 
00315 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google