1 | // -------------------------------------------------------------------------------- |
---|
2 | // Copyright (C) 2000 |
---|
3 | // Ralf Westram |
---|
4 | // |
---|
5 | // Permission to use, copy, modify, distribute and sell this software |
---|
6 | // and its documentation for any purpose is hereby granted without fee, |
---|
7 | // provided that the above copyright notice appear in all copies and |
---|
8 | // that both that copyright notice and this permission notice appear |
---|
9 | // in supporting documentation. Ralf Westram makes no |
---|
10 | // representations about the suitability of this software for any |
---|
11 | // purpose. It is provided "as is" without express or implied warranty. |
---|
12 | // -------------------------------------------------------------------------------- |
---|
13 | |
---|
14 | #ifndef BUFFEREDFILEREADER_H |
---|
15 | #define BUFFEREDFILEREADER_H |
---|
16 | |
---|
17 | #ifndef _GLIBCXX_CSTDIO |
---|
18 | #include <cstdio> |
---|
19 | #endif |
---|
20 | #ifndef _GLIBCXX_STRING |
---|
21 | #include <string> |
---|
22 | #endif |
---|
23 | #ifndef ARBTOOLS_H |
---|
24 | #include <arbtools.h> |
---|
25 | #endif |
---|
26 | #ifndef ARB_ASSERT_H |
---|
27 | #include <arb_assert.h> |
---|
28 | #endif |
---|
29 | |
---|
30 | #define fb_assert(cond) arb_assert(cond) |
---|
31 | |
---|
32 | using std::string; |
---|
33 | |
---|
34 | class LineReader : virtual Noncopyable { |
---|
35 | /*! may represent any source that can be read line by line |
---|
36 | */ |
---|
37 | |
---|
38 | size_t lineNumber; // current line number |
---|
39 | string *next_line; |
---|
40 | bool showFilename; // @@@ rename (not necessarily a file) |
---|
41 | |
---|
42 | virtual bool getLine_intern(string& line) = 0; |
---|
43 | |
---|
44 | protected: |
---|
45 | void reset() { |
---|
46 | if (next_line) { |
---|
47 | delete next_line; |
---|
48 | next_line = NULp; |
---|
49 | } |
---|
50 | lineNumber = 0; |
---|
51 | } |
---|
52 | |
---|
53 | public: |
---|
54 | LineReader() |
---|
55 | : lineNumber(0), |
---|
56 | next_line(NULp), |
---|
57 | showFilename(true) |
---|
58 | {} |
---|
59 | virtual ~LineReader() { |
---|
60 | delete next_line; |
---|
61 | } |
---|
62 | |
---|
63 | string lineError(const string& msg) const; |
---|
64 | string lineError(const char *msg) const { return lineError(string(msg)); } |
---|
65 | |
---|
66 | void showFilenameInLineError(bool show) { showFilename = show; } // @@@ rename (not necessarily a file) |
---|
67 | |
---|
68 | bool getLine(string& line) { |
---|
69 | lineNumber++; |
---|
70 | if (next_line) { |
---|
71 | line = *next_line; |
---|
72 | delete next_line; |
---|
73 | next_line = NULp; |
---|
74 | return true; |
---|
75 | } |
---|
76 | return getLine_intern(line); |
---|
77 | } |
---|
78 | |
---|
79 | void backLine(const string& line) { // push line back |
---|
80 | fb_assert(!next_line); |
---|
81 | next_line = new string(line); |
---|
82 | lineNumber--; |
---|
83 | } |
---|
84 | |
---|
85 | size_t getLineNumber() const { return lineNumber; } |
---|
86 | void setLineNumber(size_t line) { lineNumber = line; } |
---|
87 | |
---|
88 | virtual const string& getFilename() const = 0; // @@@ rename (not necessarily a file) |
---|
89 | |
---|
90 | void copyTo(FILE *out) { |
---|
91 | string line; |
---|
92 | while (getLine(line)) { |
---|
93 | fputs(line.c_str(), out); |
---|
94 | fputc('\n', out); |
---|
95 | } |
---|
96 | } |
---|
97 | }; |
---|
98 | |
---|
99 | |
---|
100 | const size_t BUFFERSIZE = 64*1024; |
---|
101 | |
---|
102 | class BufferedFileReader : public LineReader { // derived from Noncopyable |
---|
103 | char buf[BUFFERSIZE]; |
---|
104 | size_t read; // chars in buf |
---|
105 | size_t offset; // offset to next line |
---|
106 | |
---|
107 | FILE *fp; |
---|
108 | |
---|
109 | string filename; |
---|
110 | |
---|
111 | void fillBuffer(); |
---|
112 | |
---|
113 | protected: |
---|
114 | FILE*& get_fp() { return fp; } |
---|
115 | bool getLine_intern(string& line) OVERRIDE; |
---|
116 | |
---|
117 | public: |
---|
118 | BufferedFileReader(const string& filename_, FILE *in) { |
---|
119 | filename = filename_; |
---|
120 | fp = in; |
---|
121 | |
---|
122 | fb_assert(fp); |
---|
123 | read = BUFFERSIZE; |
---|
124 | fillBuffer(); |
---|
125 | } |
---|
126 | virtual ~BufferedFileReader() { |
---|
127 | if (fp) fclose(fp); |
---|
128 | } |
---|
129 | |
---|
130 | bool good() { return fp; } |
---|
131 | void rewind(); |
---|
132 | |
---|
133 | const string& getFilename() const FINAL_OVERRIDE { return filename; } |
---|
134 | |
---|
135 | PREPARE_MARK_NONFINAL_CLASS(BufferedFileReader); |
---|
136 | }; |
---|
137 | MARK_NONFINAL_CLASS(BufferedFileReader); |
---|
138 | MARK_NONFINAL_FUNCTION(BufferedFileReader,bool,getLine_intern,(string&),false); |
---|
139 | |
---|
140 | #else |
---|
141 | #error BufferedFileReader.h included twice |
---|
142 | #endif // BUFFEREDFILEREADER_H |
---|