1 /*******************************************************************************
2 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 associated documentation files (the "Software"), to deal in the Software without restriction,
6 including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
9 
10 The above copyright notice and this permission notice shall be included in all copies or
11 substantial portions of the Software.
12 
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************************/
19 
20 #ifndef STREAMBUFFER_H
21 #define STREAMBUFFER_H
22 
23 static const unsigned chunk_limit = 148576;
24 
25 #include <stdio.h>
26 #include <iostream>
27 #include <iomanip>
28 #include <limits>
29 #include <string>
30 #include <memory>
31 #include <cmath>
32 
33 #ifdef USE_ZLIB
34 #include <zlib.h>
35 struct GZ {
readGZ36     static inline int read(void* buf, size_t num, size_t count, gzFile f)
37     {
38         return gzread(f, buf, num*count);
39     }
40 };
41 #endif
42 
43 struct FN {
readFN44     static inline int read(void* buf, size_t num, size_t count, FILE* f)
45     {
46         return fread(buf, num, count, f);
47     }
48 };
49 
50 struct CH {
readCH51     static inline int read(void* buf, size_t num, size_t count, const char*& f)
52     {
53         int toread = num*count;
54         char* mybuf = (char*)buf;
55 
56         int read = 0;
57         while(*f != 0 && read < toread) {
58             *mybuf = *f;
59             mybuf++;
60             f++;
61             read++;
62         }
63         return read;
64     }
65 };
66 
67 template<typename A, typename B>
68 class StreamBuffer
69 {
70     A  in;
assureLookahead()71     void assureLookahead() {
72         if (pos >= size) {
73             pos  = 0;
74             size = B::read(buf.get(), 1, chunk_limit, in);
75         }
76     }
77     int     pos;
78     int     size;
79     std::unique_ptr<char[]> buf;
80 
advance()81     void advance()
82     {
83         operator++();
84     }
value()85     int value()
86     {
87         return operator*();
88     }
89 
90 public:
StreamBuffer(A i)91     StreamBuffer(A i) :
92         in(i)
93         , pos(0)
94         , size(0)
95         , buf(new char[chunk_limit]())
96     {
97         assureLookahead();
98     }
99 
100     int  operator *  () {
101         return (pos >= size) ? EOF : buf[pos];
102     }
103     void operator ++ () {
104         pos++;
105         assureLookahead();
106     }
107 
skipWhitespace()108     void skipWhitespace()
109     {
110         char c = value();
111         while (c == '\t' || c == '\r' || c == ' ') {
112             advance();
113             c = value();
114         }
115     }
116 
skipLine()117     void skipLine()
118     {
119         for (;;) {
120             if (value() == EOF || value() == '\0') return;
121             if (value() == '\n') {
122                 advance();
123                 return;
124             }
125             advance();
126         }
127     }
128 
skipEOL(const size_t lineNum)129     bool skipEOL(const size_t lineNum)
130     {
131         for (;;) {
132             if (value() == EOF || value() == '\0') return true;
133             if (value() == '\n') {
134                 advance();
135                 return true;
136             }
137             if (value() != '\r') {
138                 std::cerr
139                 << "PARSE ERROR! Unexpected char (hex: " << std::hex
140                 << std::setw(2)
141                 << std::setfill('0')
142                 << "0x" << value()
143                 << std::setfill(' ')
144                 << std::dec
145                 << ")"
146                 << " At line " << lineNum+1
147                 << " we expected an end of line character (\\n or \\r + \\n)"
148                 << std::endl;
149                 return false;
150             }
151             advance();
152         }
153         exit(-1);
154     }
155 
parseDouble(double & ret,size_t lineNum)156     inline bool parseDouble(double& ret, size_t lineNum)
157     {
158         int32_t head;
159         bool rc = parseInt(head, lineNum);
160         if (!rc) {
161             return false;
162         }
163         if (value() == '.') {
164             advance();
165             int64_t tail;
166             rc = parseInt<int64_t>(tail, lineNum);
167             if (!rc) {
168                 return false;
169             }
170             uint32_t num_10s = std::floor(std::log10(tail));
171             ret = head + tail/std::pow(10, num_10s+1);
172         } else {
173             ret = head;
174         }
175         return true;
176     }
177 
178     template<class T=int32_t>
179     inline bool parseInt(T& ret, size_t lineNum, bool allow_eol = false)
180     {
181         T val = 0;
182         T mult = 1;
183         skipWhitespace();
184         if (value() == '-') {
185             mult = -1;
186             advance();
187         } else if (value() == '+') {
188             advance();
189         }
190 
191         char c = value();
192         if (allow_eol && c == '\n') {
193             ret = std::numeric_limits<T>::max();
194             return true;
195         }
196         if (c < '0' || c > '9') {
197             std::cerr
198             << "PARSE ERROR! Unexpected char (dec: '" << c << ")"
199             << " At line " << lineNum
200             << " we expected a number"
201             << std::endl;
202             return false;
203         }
204 
205         while (c >= '0' && c <= '9') {
206             T val2 = val*10 + (c - '0');
207             if (val2 < val) {
208                 std::cerr << "PARSE ERROR! At line " << lineNum
209                 << " the variable number is to high"
210                 << std::endl;
211                 return false;
212             }
213             val = val2;
214             advance();
215             c = value();
216         }
217         ret = mult*val;
218         return true;
219     }
220 
parseString(std::string & str)221     void parseString(std::string& str)
222     {
223         str.clear();
224         skipWhitespace();
225         while (value() != ' ' && value() != '\n' && value() != EOF) {
226             str.push_back(value());
227             advance();
228         }
229     }
230 };
231 
232 #endif //STREAMBUFFER_H
233