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 /*************************************************************************************************/ |