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