1 /* Copyright (C) 2015 Cotton Seed
2
3 This file is part of arachne-pnr. Arachne-pnr is free software;
4 you can redistribute it and/or modify it under the terms of the GNU
5 General Public License version 2 as published by the Free Software
6 Foundation.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef PNR_BSTREAM_HH
17 #define PNR_BSTREAM_HH
18
19 #include "util.hh"
20 #include <iostream>
21 #include <vector>
22 #include <string>
23 #include <tuple>
24 #include <cstring>
25 #include <cassert>
26
27 #include <cstring>
28 #include <climits>
29
30 class obstream
31 {
32 private:
33 std::ostream &os;
34
35 public:
obstream(std::ostream & os_)36 obstream(std::ostream &os_)
37 : os(os_)
38 {}
39
write(const char * p,size_t n)40 void write(const char *p, size_t n)
41 {
42 os.write(p, n);
43 if (os.bad())
44 fatal(fmt("std::ostream::write: "
45 << strerror(errno)));
46 }
47 };
48
operator <<(obstream & obs,bool x)49 inline obstream &operator<<(obstream &obs, bool x)
50 {
51 // *logs << "bwrite bool " << x << "\n";
52 obs.write(reinterpret_cast<const char *>(&x), sizeof(x));
53 return obs;
54 }
55
operator <<(obstream & obs,char x)56 inline obstream &operator<<(obstream &obs, char x)
57 {
58 // *logs << "bwrite char " << x << "\n";
59 obs.write(reinterpret_cast<const char *>(&x), sizeof(x));
60 return obs;
61 }
62
operator <<(obstream & obs,unsigned char x)63 inline obstream &operator<<(obstream &obs, unsigned char x)
64 {
65 // *logs << "bwrite unsigned char " << x << "\n";
66 obs.write(reinterpret_cast<const char *>(&x), sizeof(x));
67 return obs;
68 }
69
70 template<typename T> obstream &
bwrite_signed_integral_type(obstream & obs,T x)71 bwrite_signed_integral_type(obstream &obs, T x)
72 {
73 char buf[sizeof(T) + 1];
74 size_t n = 0;
75 bool more = true;
76 while (more)
77 {
78 char b = (char)(x & 0x7f);
79 x >>= 7;
80
81 if ((x == 0
82 && !(b & 0x40))
83 || (x == -1
84 && (b & 0x40) == 0x40))
85 more = false;
86 else
87 b |= 0x80;
88 assert(n < sizeof(T) + 1);
89 buf[n] = b;
90 n ++;
91 }
92 obs.write(buf, n);
93 return obs;
94 }
95
96 template<typename T> obstream &
bwrite_unsigned_integral_type(obstream & obs,T x)97 bwrite_unsigned_integral_type(obstream &obs, T x)
98 {
99 char buf[sizeof(T) + 1];
100 size_t n = 0;
101
102 bool more = true;
103 while (more)
104 {
105 char b = (char)(x & 0x7f);
106 x >>= 7;
107
108 if ((x == 0
109 && ! (b & 0x40)))
110 more = false;
111 else
112 b |= 0x80;
113
114 assert(n < sizeof(T) + 1);
115 buf[n] = b;
116 n ++;
117 }
118 obs.write(buf, n);
119 return obs;
120 }
121
operator <<(obstream & obs,short x)122 inline obstream &operator<<(obstream &obs, short x)
123 {
124 return bwrite_signed_integral_type<short>(obs, x);
125 }
126
operator <<(obstream & obs,unsigned short x)127 inline obstream &operator<<(obstream &obs, unsigned short x)
128 {
129 return bwrite_unsigned_integral_type<unsigned short>(obs, x);
130 }
131
operator <<(obstream & obs,int x)132 inline obstream &operator<<(obstream &obs, int x)
133 {
134 return bwrite_signed_integral_type<int>(obs, x);
135 }
136
operator <<(obstream & obs,unsigned x)137 inline obstream &operator<<(obstream &obs, unsigned x)
138 {
139 return bwrite_unsigned_integral_type<unsigned>(obs, x);
140 }
141
operator <<(obstream & obs,long x)142 inline obstream &operator<<(obstream &obs, long x)
143 {
144 return bwrite_signed_integral_type<long>(obs, x);
145 }
146
operator <<(obstream & obs,unsigned long x)147 inline obstream &operator<<(obstream &obs, unsigned long x)
148 {
149 return bwrite_unsigned_integral_type<unsigned long>(obs, x);
150 }
151
operator <<(obstream & obs,unsigned long long x)152 inline obstream &operator<<(obstream &obs, unsigned long long x)
153 {
154 return bwrite_unsigned_integral_type<unsigned long long>(obs, x);
155 }
156
operator <<(obstream & obs,const std::string & s)157 inline obstream &operator<<(obstream &obs, const std::string &s)
158 {
159 obs << s.size();
160 obs.write(&s[0], s.size());
161 return obs;
162 }
163
164 template<class T> obstream &
operator <<(obstream & obs,const std::vector<T> & v)165 operator<<(obstream &obs, const std::vector<T> &v)
166 {
167 obs << v.size();
168 for (const auto &x : v)
169 obs << x;
170 return obs;
171 }
172
173 template<class T> obstream &
operator <<(obstream & obs,const std::set<T> & s)174 operator<<(obstream &obs, const std::set<T> &s)
175 {
176 obs << s.size();
177 for (const auto &x : s)
178 obs << x;
179 return obs;
180 }
181
182 template<typename K, typename V, typename C> obstream &
operator <<(obstream & obs,const std::map<K,V,C> & m)183 operator<<(obstream &obs, const std::map<K, V, C> &m)
184 {
185 obs << m.size();
186 for (const auto &x : m)
187 obs << x;
188 return obs;
189 }
190
191 template<typename F, typename S> inline obstream &
operator <<(obstream & obs,const std::pair<F,S> & p)192 operator<<(obstream &obs, const std::pair<F, S> &p)
193 {
194 return obs << p.first << p.second;
195 }
196
197 template<typename F, typename S, typename T> inline obstream &
operator <<(obstream & obs,const std::tuple<F,S,T> & t)198 operator<<(obstream &obs, const std::tuple<F, S, T> &t)
199 {
200 return obs << std::get<0>(t)
201 << std::get<1>(t)
202 << std::get<2>(t);
203 }
204
205 class ibstream
206 {
207 private:
208 std::istream &is;
209
210 public:
ibstream(std::istream & is_)211 ibstream(std::istream &is_)
212 : is(is_)
213 {}
214
read(char * p,size_t n)215 void read(char *p, size_t n)
216 {
217 is.read(p, n);
218 size_t rn = is.gcount();
219 if (is.bad()
220 || rn != n)
221 fatal(fmt("std::istream::read: " << strerror(errno)));
222 }
223 };
224
operator >>(ibstream & ibs,bool & x)225 inline ibstream &operator>>(ibstream &ibs, bool &x)
226 {
227 ibs.read(reinterpret_cast<char *>(&x), sizeof(x));
228 // *logs << "bread bool " << x << "\n";
229 return ibs;
230 }
231
operator >>(ibstream & ibs,char & x)232 inline ibstream &operator>>(ibstream &ibs, char &x)
233 {
234 ibs.read(reinterpret_cast<char *>(&x), sizeof(x));
235 // *logs << "bread char " << x << "\n";
236 return ibs;
237 }
238
operator >>(ibstream & ibs,unsigned char & x)239 inline ibstream &operator>>(ibstream &ibs, unsigned char &x)
240 {
241 ibs.read(reinterpret_cast<char *>(&x), sizeof(x));
242 // *logs << "bread unsigned char " << x << "\n";
243 return ibs;
244 }
245
246 template<typename T> ibstream &
bread_signed_integral_type(ibstream & ibs,T & x)247 bread_signed_integral_type(ibstream &ibs, T &x)
248 {
249 x = 0;
250 constexpr int T_bits = CHAR_BIT*sizeof(T);
251 int shift = 0;
252 for (;;)
253 {
254 char b;
255 ibs >> b;
256 x |= (int)(b & 0x7f) << shift;
257 shift += 7;
258 if (! (b & 0x80))
259 {
260 if (shift < T_bits
261 && (b & 0x40))
262 x = (x << (T_bits - shift)) >> (T_bits - shift);
263 break;
264 }
265 }
266 return ibs;
267 }
268
269 template<typename T> ibstream &
bread_unsigned_integral_type(ibstream & ibs,T & x)270 bread_unsigned_integral_type(ibstream &ibs, T &x)
271 {
272 x = 0;
273 unsigned shift = 0;
274 for (;;)
275 {
276 char b;
277 ibs >> b;
278 x |= ((unsigned)(b & 0x7f) << shift);
279 shift += 7;
280 if (! (b & 0x80))
281 break;
282 }
283 return ibs;
284 }
285
operator >>(ibstream & ibs,short & x)286 inline ibstream &operator>>(ibstream &ibs, short &x)
287 {
288 return bread_signed_integral_type<short>(ibs, x);
289 }
290
operator >>(ibstream & ibs,unsigned short & x)291 inline ibstream &operator>>(ibstream &ibs, unsigned short &x)
292 {
293 return bread_unsigned_integral_type<unsigned short>(ibs, x);
294 }
295
operator >>(ibstream & ibs,int & x)296 inline ibstream &operator>>(ibstream &ibs, int &x)
297 {
298 return bread_signed_integral_type<int>(ibs, x);
299 }
300
operator >>(ibstream & ibs,unsigned & x)301 inline ibstream &operator>>(ibstream &ibs, unsigned &x)
302 {
303 return bread_unsigned_integral_type<unsigned>(ibs, x);
304 }
305
operator >>(ibstream & ibs,long & x)306 inline ibstream &operator>>(ibstream &ibs, long &x)
307 {
308 return bread_signed_integral_type<long>(ibs, x);
309 }
310
operator >>(ibstream & ibs,unsigned long & x)311 inline ibstream &operator>>(ibstream &ibs, unsigned long &x)
312 {
313 return bread_unsigned_integral_type<unsigned long>(ibs, x);
314 }
315
operator >>(ibstream & ibs,unsigned long long & x)316 inline ibstream &operator>>(ibstream &ibs, unsigned long long &x)
317 {
318 return bread_unsigned_integral_type<unsigned long long>(ibs, x);
319 }
320
operator >>(ibstream & ibs,std::string & s)321 inline ibstream &operator>>(ibstream &ibs, std::string &s)
322 {
323 size_t n;
324 ibs >> n;
325 s.resize(n);
326 ibs.read(&s[0], n);
327 s[n] = 0;
328 return ibs;
329 }
330
331 template<class T> ibstream &
operator >>(ibstream & ibs,std::vector<T> & v)332 operator>>(ibstream &ibs, std::vector<T> &v)
333 {
334 size_t n;
335 ibs >> n;
336 v.resize(n);
337 for (size_t i = 0; i < n; ++i)
338 ibs >> v[i];
339 return ibs;
340 }
341
342 template<class T> ibstream &
operator >>(ibstream & ibs,std::set<T> & s)343 operator>>(ibstream &ibs, std::set<T> &s)
344 {
345 s.clear();
346 size_t n;
347 ibs >> n;
348 for (size_t i = 0; i < n; ++i)
349 {
350 T x;
351 ibs >> x;
352 s.insert(x);
353 }
354 return ibs;
355 }
356
357 template<typename K, typename V, typename C> ibstream &
operator >>(ibstream & ibs,std::map<K,V,C> & m)358 operator>>(ibstream &ibs, std::map<K, V, C> &m)
359 {
360 m.clear();
361 size_t n;
362 ibs >> n;
363 for (size_t i = 0; i < n; ++i)
364 {
365 std::pair<K, V> x;
366 ibs >> x;
367 m.insert(x);
368 }
369 return ibs;
370 }
371
372
373 template<typename F, typename S> inline ibstream &
operator >>(ibstream & ibs,std::pair<F,S> & p)374 operator>>(ibstream &ibs, std::pair<F, S> &p)
375 {
376 return ibs >> p.first >> p.second;
377 }
378
379 template<typename F, typename S, typename T> inline ibstream &
operator >>(ibstream & ibs,std::tuple<F,S,T> & t)380 operator>>(ibstream &ibs, std::tuple<F, S, T> &t)
381 {
382 return ibs >> std::get<0>(t)
383 >> std::get<1>(t)
384 >> std::get<2>(t);
385 }
386
387
388 #endif
389