00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00048 #ifndef STLSOFT_INCL_STLSOFT_FILESYSTEM_HPP_READ_LINE
00049 #define STLSOFT_INCL_STLSOFT_FILESYSTEM_HPP_READ_LINE
00050
00051 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00052 # define STLSOFT_VER_STLSOFT_FILESYSTEM_HPP_READ_LINE_MAJOR 2
00053 # define STLSOFT_VER_STLSOFT_FILESYSTEM_HPP_READ_LINE_MINOR 1
00054 # define STLSOFT_VER_STLSOFT_FILESYSTEM_HPP_READ_LINE_REVISION 2
00055 # define STLSOFT_VER_STLSOFT_FILESYSTEM_HPP_READ_LINE_EDIT 14
00056 #endif
00057
00058
00059
00060
00061
00062 #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
00063 # include <stlsoft/stlsoft.h>
00064 #endif
00065
00066 #ifndef STLSOFT_INCL_STDEXCEPT
00067 # define STLSOFT_INCL_STDEXCEPT
00068 # include <stdexcept>
00069 #endif
00070
00071 #ifndef STLSOFT_INCL_H_STDIO
00072 # define STLSOFT_INCL_H_STDIO
00073 # include <stdio.h>
00074 #endif
00075
00076
00077
00078
00079
00080 #ifndef _STLSOFT_NO_NAMESPACE
00081 namespace stlsoft
00082 {
00083 #endif
00084
00085
00086
00087
00088
00097 struct read_line_flags
00098 {
00099 enum flags_t
00100 {
00102 recogniseCrAsEOL = 0x0001,
00104 recogniseLfAsEOL = 0x0002,
00106 recogniseCrLfAsEOL = 0x0004,
00108 recogniseAll = (recogniseCrAsEOL | recogniseLfAsEOL | recogniseCrLfAsEOL),
00109
00111 mask = 0x0007
00112 };
00113 };
00114
00115 inline read_line_flags::flags_t operator |(read_line_flags::flags_t const& lhs, read_line_flags::flags_t const& rhs)
00116 {
00117 return static_cast<read_line_flags::flags_t>(int(lhs) | int(rhs));
00118 }
00119
00120
00121
00122
00123
00124 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00125
00126 namespace readers
00127 {
00128 class read_from_FILE
00129 {
00130 public:
00131 typedef read_from_FILE class_type;
00132
00133 public:
00134 ss_explicit_k read_from_FILE(FILE* stm)
00135 : m_stm(stm)
00136 {}
00137 read_from_FILE(class_type const& rhs)
00138 : m_stm(rhs.m_stm)
00139 {}
00140 private:
00141 class_type& operator =(class_type const&);
00142
00143 public:
00144 int read_char()
00145 {
00146 return ::fgetc(m_stm);
00147 }
00148
00149 int peek_next_char()
00150 {
00151 int ch = ::fgetc(m_stm);
00152
00153 if(EOF != ch)
00154 {
00155 ::ungetc(ch, m_stm);
00156 }
00157
00158 return ch;
00159 }
00160
00161 private:
00162 FILE* const m_stm;
00163 };
00164
00165 template <ss_typename_param_k I>
00166 class read_from_iterator_range
00167 {
00168 private:
00169 typedef I iterator_type_;
00170 public:
00171 typedef read_from_iterator_range<iterator_type_> class_type;
00172
00173 public:
00174 ss_explicit_k read_from_iterator_range(iterator_type_ from, iterator_type_ to)
00175 : m_from(from)
00176 , m_to(to)
00177 {}
00178 read_from_iterator_range(class_type const& rhs)
00179 : m_from(rhs.m_from)
00180 , m_to(rhs.m_to)
00181 {}
00182 private:
00183 class_type& operator =(class_type const&);
00184
00185 public:
00186 int read_char()
00187 {
00188 if(m_from == m_to)
00189 {
00190 return -1;
00191 }
00192 else
00193 {
00194 return *m_from++;
00195 }
00196 }
00197
00198 int peek_next_char()
00199 {
00200 if(m_from == m_to)
00201 {
00202 return -1;
00203 }
00204 else
00205 {
00206 return *m_from;
00207 }
00208 }
00209
00210 private:
00211 iterator_type_ m_from;
00212 iterator_type_ const m_to;
00213 };
00214
00215 class read_from_char_buffer
00216 {
00217 public:
00218 typedef read_from_char_buffer class_type;
00219
00220 public:
00221 ss_explicit_k read_from_char_buffer(char const* buffer, int size)
00222 : m_buffer(buffer)
00223 , m_size(calc_length_(buffer, size))
00224 , m_current(0)
00225 {}
00226 read_from_char_buffer(class_type const& rhs)
00227 : m_buffer(rhs.m_buffer)
00228 , m_size(rhs.m_size)
00229 , m_current(rhs.m_current)
00230 {}
00231 private:
00232 static ss_size_t calc_length_(char const* buffer, int size)
00233 {
00234 if(size < 0)
00235 {
00236 size_t len = 0;
00237
00238 if(NULL != buffer)
00239 {
00240 for(; '\0' != *buffer; ++len, ++buffer)
00241 {}
00242 }
00243
00244 return len;
00245 }
00246 else
00247 {
00248 return static_cast<ss_size_t>(size);
00249 }
00250 }
00251 class_type& operator =(class_type const&);
00252
00253 public:
00254 int read_char()
00255 {
00256 if(m_current == m_size)
00257 {
00258 return -1;
00259 }
00260 else
00261 {
00262 return m_buffer[m_current++];
00263 }
00264 }
00265
00266 int peek_next_char()
00267 {
00268 if(m_current == m_size)
00269 {
00270 return -1;
00271 }
00272 else
00273 {
00274 return m_buffer[m_current];
00275 }
00276 }
00277
00278 private:
00279 char const* const m_buffer;
00280 const ss_size_t m_size;
00281 ss_size_t m_current;
00282 };
00283
00284 }
00285
00286 namespace read_line_impl
00287 {
00288 template< ss_typename_param_k S
00289 , ss_typename_param_k P
00290 >
00291 static ss_bool_t read_line(P& policy, S& line, read_line_flags::flags_t flags)
00292 {
00293 ss_size_t numCr = 0;
00294
00295 if(0 == (read_line_flags::mask & flags))
00296 {
00297 flags = read_line_flags::recogniseAll;
00298 }
00299
00300 S().swap(line);
00301
00302 { for (int ch; EOF != (ch = policy.read_char()); )
00303 {
00304 switch(ch)
00305 {
00306 case '\r':
00307
00308
00309
00310
00311
00312
00313
00314 if(0 != ((read_line_flags::recogniseCrAsEOL | read_line_flags::recogniseCrLfAsEOL) & flags))
00315 {
00316 if(read_line_flags::recogniseCrLfAsEOL & flags)
00317 {
00318
00319
00320 int ch2 = policy.peek_next_char();
00321
00322 if('\n' == ch2)
00323 {
00324 policy.read_char();
00325
00326 line.append(numCr, '\r');
00327
00328 return true;
00329 }
00330 }
00331
00332 if(read_line_flags::recogniseCrAsEOL & flags)
00333 {
00334 return true;
00335 }
00336 }
00337
00338 ++numCr;
00339 continue;
00340 case '\n':
00341
00342
00343
00344
00345
00346
00347
00348
00349 if( numCr > 0 &&
00350 (read_line_flags::recogniseCrLfAsEOL & flags))
00351 {
00352
00353
00354
00355
00356 line.append(numCr - 1, '\r');
00357
00358 return true;
00359 }
00360 else if(read_line_flags::recogniseLfAsEOL & flags)
00361 {
00362 line.append(numCr, '\r');
00363
00364 return true;
00365 }
00366 break;
00367 default:
00368 if(numCr > 0)
00369 {
00370 line.append(numCr, '\r');
00371 numCr = 0;
00372 }
00373 break;
00374 }
00375
00376 line.append(1, static_cast<char>(ch));
00377 }}
00378
00379 return !line.empty();
00380 }
00381
00382 }
00383
00384 #endif
00385
00386
00387
00388
00389
00408 template <ss_typename_param_k S>
00409 ss_bool_t read_line(
00410 FILE* stm
00411 , S& line
00412 , read_line_flags::flags_t flags = read_line_flags::recogniseAll
00413 )
00414 {
00415 readers::read_from_FILE policy(stm);
00416
00417 return read_line_impl::read_line(policy, line, flags);
00418 }
00419
00422 template< ss_typename_param_k I
00423 , ss_typename_param_k S
00424 >
00425 ss_bool_t read_line(
00426 I from
00427 , I to
00428 , S& line
00429 , read_line_flags::flags_t flags = read_line_flags::recogniseAll
00430 )
00431 {
00432 readers::read_from_iterator_range<I> policy(from, to);
00433
00434 return read_line_impl::read_line(policy, line, flags);
00435 }
00436
00437
00438
00439 #ifndef _STLSOFT_NO_NAMESPACE
00440 }
00441 #endif
00442
00443
00444
00445 #endif
00446
00447