sisi4s
Loading...
Searching...
No Matches
Scanner.hpp
Go to the documentation of this file.
1#ifndef SCANNER_DEFINED
2#define SCANNER_DEFINED
3
4#include <math/Float.hpp>
5#include <math/Complex.hpp>
6#include <util/Log.hpp>
7#include <util/Exception.hpp>
8#include <sstream>
9#include <istream>
10#include <cstring>
11
12namespace sisi4s {
13class Scanner {
14protected:
15 static unsigned int constexpr BUFFER_SIZE = 128 * 1024 * 1024;
16 static unsigned int constexpr REFILL_SIZE = 128;
17
18 std::istream *stream;
19 char *buffer, *pos, *end;
20 bool eof;
21
22 void refillBuffer() {
23 if (pos + REFILL_SIZE > buffer + BUFFER_SIZE && !eof) {
24 // move remaining text to beginning of buffer
25 std::memmove(buffer, pos, end - pos);
26 // set the buffer end to the end of the remaining text
27 end = buffer + (end - pos);
28 // the next character to read is now at the beginning
29 pos = buffer;
30 // fill the rest of the buffer from the file
31 int64_t size(buffer + BUFFER_SIZE - end);
32 int64_t count(stream->read(end, size).gcount());
33#ifdef DEBUG
34 LOG(2, "Scanner") << count << " bytes fetched." << std::endl;
35#endif
36 // account the read characters to the buffer
37 end += count;
38 // if not all requested characters could be read the file is done
39 if (count < size) {
40 eof = true;
41 *end = 0;
42 }
43 }
44 }
45
46public:
47 Scanner(std::istream *stream_)
48 : stream(stream_)
49 , buffer(new char[BUFFER_SIZE])
50 , pos(buffer + BUFFER_SIZE - 1)
51 , end(pos)
52 , eof(false) {}
53
54 std::string nextLine(char const delimiter = '\n') {
55 std::stringstream lineStream;
56 bool terminated(false);
57 do {
59 switch (*pos) {
60 case 0: terminated = true; break;
61 default:
62 char c(*pos++);
63 if (c != delimiter) lineStream.put(c);
64 else terminated = true;
65 break;
66 }
67 } while (!terminated);
68 return lineStream.str();
69 }
70
71 template <typename NumberType>
72 friend class NumberScanner;
73};
74
75// double precision float
76template <typename NumberType = Float64>
78template <>
80public:
82 : scanner(scanner_) {}
84 scanner->refillBuffer();
85 return scanReal(&scanner->pos);
86 }
87 static Float64 scanReal(char **position) {
88 return std::strtod(*position, position);
89 }
90
91protected:
93};
94
95// complex numbers
96template <typename Real>
97class NumberScanner<Complex<Real>> {
98public:
100 : scanner(scanner_) {}
102 scanner->refillBuffer();
103 while (isspace(*scanner->pos) || *scanner->pos == '(') ++scanner->pos;
104 // read real part
105 Real r(NumberScanner<Real>::scanReal(&scanner->pos));
106 // skip ','
107 ++scanner->pos;
108 // read imaginary part
109 Real i(NumberScanner<Real>::scanReal(&scanner->pos));
110 // skip ')'
111 ++scanner->pos;
112 return complex(r, i);
113 }
114
115protected:
117};
118} // namespace sisi4s
119#endif
#define LOG(...)
Definition Log.hpp:119
NumberScanner(Scanner *scanner_)
Definition Scanner.hpp:99
Complex< Real > nextNumber()
Definition Scanner.hpp:101
Scanner * scanner
Definition Scanner.hpp:116
Float64 nextNumber()
Definition Scanner.hpp:83
Scanner * scanner
Definition Scanner.hpp:92
NumberScanner(Scanner *scanner_)
Definition Scanner.hpp:81
static Float64 scanReal(char **position)
Definition Scanner.hpp:87
Definition Scanner.hpp:77
Definition Scanner.hpp:13
bool eof
Definition Scanner.hpp:20
std::string nextLine(char const delimiter='\n')
Definition Scanner.hpp:54
void refillBuffer()
Definition Scanner.hpp:22
std::istream * stream
Definition Scanner.hpp:18
Scanner(std::istream *stream_)
Definition Scanner.hpp:47
static unsigned int constexpr REFILL_SIZE
Definition Scanner.hpp:16
char * buffer
Definition Scanner.hpp:19
char * pos
Definition Scanner.hpp:19
char * end
Definition Scanner.hpp:19
static unsigned int constexpr BUFFER_SIZE
Definition Scanner.hpp:15
Definition Algorithm.hpp:10
FloatTypes< 64 >::type Float64
Definition Float.hpp:30
std::complex< Real > Complex
Definition Complex.hpp:10
Complex< real > complex
Definition Complex.hpp:17