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 #include <more/io/readline.h>
00030 #include <more/gen/utility.h>
00031 #include <algorithm>
00032 #include <stdexcept>
00033 #include <cstdlib>
00034
00035
00036 #ifndef MORE_BUFFER_H
00037 #define MORE_BUFFER_H
00038
00039 namespace more {
00040 namespace io {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template<typename T>
00056 struct buffer : gen::noncopyable
00057 {
00058 typedef std::size_t size_type;
00059 typedef std::ptrdiff_t difference;
00060 typedef T value_type;
00061
00062
00063 struct driver
00064 {
00065 typedef buffer::difference difference;
00066 typedef buffer::size_type size_type;
00067 typedef buffer::value_type value_type;
00068
00069
00070
00071
00072
00073
00074
00075
00076 virtual T* read(T* first, T* last) { return last; }
00077
00078
00079
00080
00081 virtual void write(T* first, T* last) {}
00082
00083
00084 virtual bool is_error() { return false; }
00085
00086 virtual ~driver() {}
00087 };
00088
00089 private:
00090 static size_type const n_buf_init = 512;
00091
00092 public:
00093
00094
00095
00096 explicit buffer(driver* drv = 0, bool is_interactive = false)
00097 : m_drv(drv? drv : new driver),
00098 m_alloc(0), m_begin(0), m_cur(0), m_stop(0), m_end(0),
00099 have_eof(false),
00100 m_is_interactive(is_interactive)
00101 {
00102 lookahead(1);
00103 }
00104
00105
00106 ~buffer()
00107 {
00108 sync();
00109 delete[] m_alloc;
00110 delete m_drv;
00111
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 driver* install(driver* b)
00134 {
00135 driver* old = m_drv;
00136 this->~buffer();
00137 new ((void*)this) buffer(b);
00138 return old;
00139 }
00140
00141
00142 void sync() {
00143 if (m_begin != m_cur)
00144 m_drv->write(m_begin, m_cur);
00145 }
00146
00147
00148
00149
00150 T& at(size_type n) { return m_cur[n]; }
00151 T const& at(size_type n) const { return m_cur[n]; }
00152
00153
00154
00155
00156
00157 T* data() { return m_cur; }
00158 T const* data() const { return m_cur; }
00159
00160
00161
00162
00163 T* data(size_type n)
00164 {
00165 if (lookahead(n) >= n)
00166 return m_cur;
00167 else
00168 throw std::length_error("more::io::buffer::data: "
00169 "Too few items in input sequence.");
00170 }
00171
00172
00173
00174
00175
00176
00177 T* get_n(size_type n)
00178 {
00179 if (lookahead(n+1) >= n) {
00180 m_cur += n;
00181 return m_cur - n;
00182 }
00183 else
00184 throw std::length_error("more::io::buffer::data: "
00185 "Too few items in input sequence.");
00186 }
00187
00188
00189
00190
00191
00192
00193 T& get()
00194 {
00195 if (lookahead(2) < 1)
00196 throw std::length_error("more::io::buffer::get: "
00197 "Too few items in input sequence.");
00198 ++m_cur;
00199 return m_cur[-1];
00200 }
00201
00202
00203
00204
00205 T& peek() { return *m_cur; }
00206 T const& peek() const { return *m_cur; }
00207
00208
00209
00210 size_type lookahead(size_type n)
00211 {
00212 if (m_cur + n > m_stop)
00213 extend(n);
00214 return m_stop - m_cur;
00215 }
00216
00217
00218
00219 bool is_eof() { return m_cur >= m_stop; }
00220
00221
00222 bool is_error() { return m_drv->is_error(); }
00223
00224
00225 void swap(buffer& b)
00226 {
00227 std::iter_swap(m_drv, b.m_drv);
00228 std::iter_swap(m_alloc, b.m_alloc);
00229 std::iter_swap(m_begin, b.m_begin);
00230 std::iter_swap(m_cur, b.m_cur);
00231 std::iter_swap(m_stop, b.m_stop);
00232 std::iter_swap(m_end, b.m_end);
00233 std::swap(have_eof, b.have_eof);
00234
00235 }
00236
00237 protected:
00238
00239
00240 void set_fixed(T* first, T* end, bool have_eof = false)
00241 {
00242 delete[] m_alloc;
00243 m_alloc = 0;
00244 m_begin = first;
00245 m_cur = first;
00246 m_stop = end;
00247 m_end = end;
00248 if (have_eof) ++m_end;
00249 }
00250
00251 private:
00252 void extend(size_type n);
00253
00254 driver* m_drv;
00255 T* m_alloc;
00256 T* m_begin;
00257 T* m_cur;
00258 T* m_stop;
00259 T* m_end;
00260 bool have_eof;
00261
00262 bool m_is_interactive;
00263 };
00264
00265 template<typename Char, typename Traits>
00266 typename buffer<Char>::driver*
00267 new_isdriver(std::basic_string<Char, Traits> const& str, bool want_eof);
00268
00269 template<typename Char, typename Traits>
00270 typename buffer<Char>::driver*
00271 new_osdriver(std::basic_string<Char, Traits>& str);
00272
00273
00274
00275 template<typename Char>
00276 typename buffer<Char>::driver*
00277 new_ifdriver(char const* name, bool want_eof);
00278
00279
00280 template<typename Char>
00281 typename buffer<Char>::driver*
00282 new_ofdriver(char const* name);
00283
00284 template<typename Char>
00285 struct readline_driver {};
00286
00287 template<>
00288 struct readline_driver<char> : buffer<char>::driver
00289 {
00290 readline_driver(char* prompt, bool want_eof, char* sep = "\n");
00291 ~readline_driver();
00292 void set_prompt(char* prompt) { m_prompt = prompt; }
00293 protected:
00294 char* read(char* first, char* last);
00295 private:
00296 char* m_prompt;
00297 char* m_pending;
00298 bool m_want_eof;
00299 char* m_sep;
00300 bool m_toggle;
00301 };
00302
00303 template<>
00304 struct readline_driver<wchar_t> : buffer<wchar_t>::driver
00305 {
00306 readline_driver(char* prompt, bool want_eof, wchar_t* sep = L"\n");
00307 ~readline_driver();
00308 void set_prompt(char* prompt) { m_prompt = prompt; }
00309 protected:
00310 wchar_t* read(wchar_t* first, wchar_t* last);
00311 private:
00312 char* m_prompt;
00313 wchar_t* m_pending;
00314 wchar_t* m_alloc;
00315 bool m_want_eof;
00316 wchar_t* m_sep;
00317 bool m_toggle;
00318 };
00319
00320
00321
00322
00323 template<typename Char>
00324 inline typename buffer<Char>::driver*
00325 new_readline_driver(char* prompt, bool want_eof = false)
00326 {
00327 return new readline_driver<Char>(prompt, want_eof);
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337 template<typename Char>
00338 inline typename buffer<Char>::driver*
00339 new_readline_driver(char* prompt, bool want_eof, Char* sep)
00340 {
00341 return new readline_driver<Char>(prompt, want_eof, sep);
00342 }
00343
00344 }}
00345
00346 #include <more/bits/buffer.tcc>
00347
00348 #endif