aboutsummaryrefslogtreecommitdiff
path: root/butl/fdstream
blob: ac4500a43a874e331a3a0ffa4b4865ef01acc407 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// file      : butl/fdstream -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUTL_FDSTREAM
#define BUTL_FDSTREAM

#include <istream>
#include <ostream>

namespace butl
{
  // An iostream that is initialized with a file descriptor rather than
  // a file name.
  //
  // Notes and limitations:
  //
  // - char only
  // - input or output but not both
  // - no support for put back
  // - throws std::system_error in case of a read()/write() error
  // - not movable, though can be easily supported
  //
  class fdbuf: public std::basic_streambuf<char>
  {
  public:
    virtual
    ~fdbuf ();
    fdbuf () = default;
    fdbuf (int fd) {open (fd);}

    fdbuf (const fdbuf&) = delete;
    fdbuf& operator= (const fdbuf&) = delete;

    void
    close ();

    void
    open (int fd);

    bool
    is_open () const {return fd_ != -1;}

  public:
    using int_type = std::basic_streambuf<char>::int_type;
    using traits_type = std::basic_streambuf<char>::traits_type;

    // basic_streambuf input interface.
    //
  public:
    virtual std::streamsize
    showmanyc ();

    virtual int_type
    underflow ();

  private:
    bool
    load ();

    // basic_streambuf output interface.
    //
  public:
    virtual int_type
    overflow (int_type);

    virtual int
    sync ();

  private:
    bool
    save ();

  private:
    int fd_ = -1;
    char buf_[2048];
  };

  class fdstream_base
  {
  protected:
    fdstream_base () = default;
    fdstream_base (int fd): buf_ (fd) {}

  protected:
    fdbuf buf_;
  };

  class ifdstream: fdstream_base, public std::istream
  {
  public:
    ifdstream (): std::istream (&buf_) {}
    ifdstream (int fd): fdstream_base (fd), std::istream (&buf_) {}

    void close () {buf_.close ();}
    void open (int fd) {buf_.open (fd);}
    bool is_open () const {return buf_.is_open ();}
  };

  class ofdstream: fdstream_base, public std::ostream
  {
  public:
    ofdstream (): std::ostream (&buf_) {}
    ofdstream (int fd): fdstream_base (fd), std::ostream (&buf_) {}

    void close () {buf_.close ();}
    void open (int fd) {buf_.open (fd);}
    bool is_open () const {return buf_.is_open ();}
  };
}

#endif // BUTL_FDSTREAM