SHORE API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
streams.hpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2008,2009,2010,2011,2012 Stephan Ossowski, Korbinian Schneeberger,
4  * Felix Ott, Joerg Hagmann, Alf Scotland, Sebastian Bender
5  *
6  * This file is part of SHORE.
7  *
8  * SHORE is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * SHORE is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with SHORE. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
25 
26 #ifndef STREAMSET_HPP__
27 #define STREAMSET_HPP__
28 
29 
30 #ifdef HAVE_CONFIG_H
31  #include "config.h"
32 #endif
33 
34 #include <iostream>
35 #include <stdexcept>
36 #include <string>
37 #include <vector>
38 
39 #include <boost/iostreams/stream.hpp>
40 #include <boost/iostreams/device/file_descriptor.hpp>
41 #include <boost/iostreams/device/null.hpp>
42 #include <boost/iostreams/concepts.hpp>
43 #include <boost/iostreams/categories.hpp>
44 #include <boost/thread/recursive_mutex.hpp>
45 
46 #include "shore/base/stringops.hpp"
47 #include "shore/base/memops.hpp"
48 
49 namespace shore {
50 
53 {
54  public:
55 
57  enum Codec
58  {
59  CODEC_PLAIN,
60  CODEC_GZIP,
61  CODEC_XZ
62  };
63 
66  {
67  GRANULARITY_FAST,
68  GRANULARITY_MEDIUM,
69  GRANULARITY_SLOW
70  };
71 
72  static const int BLOCKSIZE_PRESET_VALUES[3];
73 
75  static const std::string COMPRESSION_FILEEXTS[3];
76 };
77 
78 S_MAKE_ENUM_TRAITS(streams_base::Codec)
79 S_MAKE_ENUM_TRAITS(streams_base::RandomAccessGranularity)
80 
82 class istreams
83 :public streams_base
84 {
85  private:
86 
87  typedef boost::recursive_mutex mutex_t;
88  typedef boost::recursive_mutex::scoped_lock lock_t;
89  static int m_filecount;
90  static mutex_t m_filecountmutex;
91 
93  struct stream_info
94  {
95  std::string streamname;
96  std::vector<std::istream *> stream_stack;
97  std::vector<int64_t> streamsizes;
98  bool stream_seekable;
99  bool delete_ptr;
100 
101  stream_info(const std::string &name);
102  };
103 
104  std::vector<stream_info> m_streams;
105 
106  bool m_use_mmap;
107 
108  static bool filecount_inc();
109  static void filecount_dec();
110  std::istream *rawstream_alloc(const std::string &fn);
111 
112 
113  istreams(const istreams &);
114  istreams &operator=(const istreams &);
115 
116  public:
117 
119  static bool has_magic(std::istream *const in,const int m1,const int m2);
120 
122  static bool has_gzip_magic(std::istream *const in);
123 
125  static bool has_xz_magic(std::istream *const in);
126 
128  static bool is_gzip(const std::string &fn);
129 
131  static bool is_xz(const std::string &fn);
132 
134  static Codec get_codec(const std::string &fn);
135 
137  static uint64_t uncompressed_file_size(const std::string &fn);
138 
140  static void read_error_check(std::istream &s,
141  const std::string &stream_name,
142  const std::string &label=std::string());
143 
145  static void read_error_eof_check(std::istream &s,
146  const std::string &stream_name,
147  const std::string &label=std::string());
148 
150  static void read_error_check_rdbuf(std::istream &s,
151  const std::string &stream_name,
152  const std::string &label=std::string());
153 
155  static void save_stream_to_string(std::string &res,std::istream &s,
156  const std::string &streamname);
157 
159  static void save_stream_to_string(std::string &res,const std::string &s);
160 
162  istreams();
163 
165  explicit istreams(const std::string& fn);
166 
168  explicit istreams(const std::vector<std::string>& fn);
169 
171  template<class Iter>
172  istreams(Iter f_beg,Iter f_end)
173  :m_use_mmap(false)
174  {
175  open_files(f_beg,f_end);
176  }
177 
179  ~istreams();
180 
183  std::istream &open_file(const std::string &fnam);
184 
187  std::istream &open_file(const std::string &fnam,const Codec c);
188 
191  template<class Iter>
192  void open_files(Iter f_beg,Iter f_end)
193  {
194  for(Iter itr=f_beg;itr!=f_end;++itr)
195  {
196  open_file(*itr);
197  }
198  }
199 
201  std::istream &open_normalfile(const std::string &fn,const Codec c=CODEC_PLAIN);
202 
204  std::istream &push_back(std::istream& stream,const std::string &name=std::string(),
205  const Codec c=CODEC_PLAIN);
206 
208  std::istream& open_pipe(const std::string& command,const bool tolerant=false,
209  const Codec c=CODEC_PLAIN);
210 
212  void add_codec(const size_t index,const Codec c);
213 
215  void read_error_check(const int index,const std::string &label=std::string());
216 
218  void read_error_check_rdbuf(const int index,const std::string &label=std::string());
219 
222  void close_all();
223 
225  void close_stream(const std::istream*const s);
226 
228  void close_stream(const size_t i);
230  void close_stream(const int i);
231 
233  void use_mmap(const bool b);
234 
236  size_t size() const;
237 
239  std::istream& operator[](size_t n);
240 
242  std::istream &front();
243 
245  std::istream &back();
246 
248  uint64_t get_streamsize(const size_t i) const;
249 
251  const std::string &get_streamname(const size_t i) const;
252 
254  bool is_raw_seekable(const size_t i) const;
255 
257  bool is_stream_seekable(const size_t i) const;
258 };
259 
261 class ostreams
262 :public std::ostream,
263  public streams_base
264 {
265  public:
266 
269  {
270  EXISTS_FAIL,
271  EXISTS_REPLACE,
272  EXISTS_APPEND
273  };
274 
275  // \brief Automatically throw a (pretty uninformative) exception, e.g.
276  // if disk is full.
277  enum ErrorCheck
278  {
279  ERRCHECK_MANUAL,
280  ERRCHECK_AUTO
281  };
282 
283  private:
284 
286  static Codec DEFAULT_ENC;
288  static Codec DEFAULT_FASTENC;
289 
291  static size_t DEFAULT_ENCBS;
292 
294  struct stream_info
295  {
297  std::string streamname;
299  std::vector<std::ostream *> stream_stack;
303  bool delete_ptr;
305  bool tempfile;
307  std::string rename_name;
308  };
309 
310  struct output_flushable
311  :boost::iostreams::output,
312  boost::iostreams::flushable_tag
313  {};
314 
317  class streamset_sink
318  :public boost::iostreams::device<output_flushable>
319  {
320  private:
321 
322  std::vector<stream_info> *const m_streams;
323 
324  public:
325 
326  streamset_sink(std::vector<stream_info> *const streams);
327 
328  std::streamsize write(const char* s,std::streamsize n);
329 
330  bool flush();
331 
332  void close();
333 
334  void imbue(const std::locale& l);
335  };
336 
339  boost::iostreams::stream_buffer<streamset_sink>* m_streambuf;
340 
342  boost::iostreams::stream<boost::iostreams::null_sink> m_null;
343 
345  std::vector<stream_info> m_streams;
346 
348  size_t m_enc_bs;
349 
351  void init();
352 
353 
354  ostreams(const ostreams &);
355  ostreams &operator=(const ostreams &);
356 
357  public:
358 
360  static void set_default_enc(const Codec c);
361 
364  static void set_default_fastenc(const Codec c);
365 
367  static void set_default_enc_bs(const size_t t);
368 
370  static void set_default_enc_bs(const RandomAccessGranularity g);
371 
373  static Codec default_enc();
374 
376  static size_t default_enc_bs();
377 
380  static Codec default_fastenc();
381 
383  static const std::string &default_ext();
384 
387  static void write_error_check(std::ostream &s,
388  const std::string &stream_name,
389  const std::string &label=std::string());
390 
391 
393  ostreams();
394 
395  explicit ostreams(const std::string &fn,const FileExistsOp exo=EXISTS_FAIL);
396 
397  explicit ostreams(const std::vector<std::string> &fn,
398  const FileExistsOp exo=EXISTS_FAIL);
399 
400  template<class Iter>
401  ostreams(Iter f_beg,Iter f_end,const FileExistsOp exo=EXISTS_FAIL)
402  :std::ostream(0)
403  {
404  init();
405  open_files(f_beg,f_end,exo);
406  }
407 
409  ~ostreams();
410 
412  void set_enc_blocksize(const size_t bs);
413 
417 
424  std::ostream &open_file(const std::string& fn,
425  const FileExistsOp exo=EXISTS_FAIL,
426  const ErrorCheck ec=ERRCHECK_AUTO);
427 
433  std::ostream &open_file(const std::string& fn,const Codec c,
434  const FileExistsOp exo=EXISTS_FAIL,
435  const ErrorCheck ec=ERRCHECK_AUTO);
436 
439  template<class Iter>
440  void open_files(Iter f_beg,Iter f_end,const FileExistsOp exo=EXISTS_FAIL)
441  {
442  for(Iter itr=f_beg;itr!=f_end;++itr)
443  {
444  open_file(*itr,exo);
445  }
446  }
447 
449  std::ostream &open_normalfile(const std::string &fn,
450  const Codec c=CODEC_PLAIN,
451  const FileExistsOp exists_op=EXISTS_FAIL,
452  const ErrorCheck ec=ERRCHECK_AUTO);
453 
466  std::ostream &open_tempfile(const std::string &pathprefix,
467  const std::string &rename_name,
468  const Codec c=default_fastenc(),
469  const FileExistsOp exists_op=EXISTS_FAIL,
470  const ErrorCheck ec=ERRCHECK_AUTO);
471 
473  std::ostream &open_tempfile(const std::string &pathprefix,
474  const Codec c,
475  const ErrorCheck ec=ERRCHECK_AUTO);
476 
479  std::ostream &open_tempfile(const std::string &pathprefix,
480  const ErrorCheck ec=ERRCHECK_AUTO);
481 
484  std::ostream &open_tmpdir_file(const std::string &fn_prefix,
485  const Codec c,
486  const ErrorCheck ec=ERRCHECK_AUTO);
487 
490  std::ostream &open_tmpdir_file(const std::string &fn_prefix,
491  const ErrorCheck ec=ERRCHECK_AUTO);
492 
494  std::ostream &open_pipe(const std::string &command,
495  const Codec c=CODEC_PLAIN,
496  const ErrorCheck ec=ERRCHECK_AUTO);
497 
499  std::ostream &push_back(std::ostream &os,
500  const std::string &name=std::string(),
501  const Codec c=CODEC_PLAIN,
502  const ErrorCheck ec=ERRCHECK_AUTO);
503 
505  void add_codec(const size_t index,const Codec c,
506  const ErrorCheck ec=ERRCHECK_AUTO);
507 
510  void write_error_check(const int index,const std::string &label=std::string());
511 
514  void close_all();
515 
517  void close_stream(const std::ostream*const s);
518 
520  void close_stream(const size_t i);
521 
523  void close_stream(const int i);
524 
526  size_t size() const;
527 
529  std::ostream &operator[](int n);
530 
532  std::ostream &front();
533 
535  std::ostream &back();
536 
538  const std::string &get_streamname(const size_t i) const;
539 };
540 
542 class ipipe
543 :public boost::iostreams::stream<boost::iostreams::file_descriptor_source>
544 {
545  private:
546 
547  typedef boost::iostreams::file_descriptor_source source_t;
548  typedef boost::iostreams::stream<source_t> base_t;
549 
550  FILE* m_pipe;
551 
552  const std::string m_command;
553 
554  const bool m_tolerate_errexit;
555 
556  public:
557 
558  explicit ipipe(const std::string& command,const bool tolerant=false);
559  ~ipipe();
560 };
561 
563 class opipe
564 :public boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
565 {
566  private:
567 
568  typedef boost::iostreams::file_descriptor_sink sink_t;
569  typedef boost::iostreams::stream<sink_t> base_t;
570 
571  FILE* m_pipe;
572 
573  const std::string m_command;
574 
575  public:
576 
577  explicit opipe(const std::string& command);
578  ~opipe();
579 };
580 
585 :public boost::iostreams::device<boost::iostreams::input_seekable>
586 {
587  private:
588 
589  static const std::streamsize m_mmapsize;
590  shore::mmapping m_mmpp;
591 
592  off_t m_pos;
593 
594  off_t m_blockofs;
595 
596  public:
597 
598  mmapping_source(const std::string &fn);
599 
601  std::streamsize read(char* s,std::streamsize n);
602 
603  std::streampos seek(boost::iostreams::stream_offset off,
604  std::ios_base::seekdir way);
605 };
606 
611 :public boost::iostreams::stream<mmapping_source>
612 {
613  public:
614 
615  mmapping_ifstream(const std::string &fn);
616 };
617 
618 } // namespace shore
619 
620 #endif // STREAMSET_HPP__
621 
622 // vim: sw=4:softtabstop=4:expandtab