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