Btk
popen.hpp
1 #if !defined(_BTK_POPEN_HPP_)
2 #define _BTK_POPEN_HPP_
3 
4 #include <cstdio>
5 #include <cerrno>
6 #include <cstring>
7 
8 #include <string>
9 #include <string_view>
10 
11 #ifdef _WIN32
12  #include <process.h>
13  #include <io.h>
14  #define BTK_POPEN ::_popen
15  #define BTK_PCLOSE ::_pclose
16 #else
17  #include <unistd.h>
18  #define BTK_POPEN ::popen
19  #define BTK_PCLOSE ::pclose
20 #endif
21 
22 #include "../exception.hpp"
23 #include "../defs.hpp"
24 namespace Btk{
29  class PStream{
30  public:
31  PStream() = default;
38  PStream(const char *cmd,const char *modes);
39  PStream(const PStream &) = delete;
40  PStream(PStream &&);
41  ~PStream();
46  void close();
53  void open(const char *cmd,const char *modes);
54  void open(std::string_view cmd,std::string_view modes){
55  open(cmd.data(),modes.data());
56  }
65  bool try_open(const char *cmd,const char *modes);
66  bool try_open(std::string_view cmd,std::string_view modes){
67  return try_open(cmd.data(),modes.data());
68  }
75  bool bad();
82  bool eof();
89  FILE *operator *() const noexcept{
90  return fptr;
91  }
92  operator bool(){
93  return not bad();
94  }
102  friend PStream &operator >>(PStream &,std::string &);
108  friend PStream &operator <<(PStream &,std::string_view);
109  private:
110  FILE *fptr = nullptr;
111  };
112 
113  inline PStream::PStream(const char *cmd,const char *modes){
114  fptr = BTK_POPEN(cmd,modes);
115  if(fptr == nullptr){
116  throwRuntimeError(strerror(errno));
117  }
118  }
119  inline PStream::PStream(PStream &&pstream){
120  fptr = pstream.fptr;
121  pstream.fptr = nullptr;
122  }
123  inline PStream::~PStream(){
124  close();
125  }
126  //Close stream
127  inline void PStream::close(){
128  if(fptr != nullptr){
129  BTK_PCLOSE(fptr);
130  fptr = nullptr;
131  }
132  }
133  //Check it
134  inline bool PStream::bad(){
135  return std::ferror(fptr);
136  }
137  inline bool PStream::eof(){
138  return std::feof(fptr);
139  }
140  //Stream open
141  inline void PStream::open(const char *cmd,const char *modes){
142  FILE *fp = BTK_POPEN(cmd,modes);
143  if(fp == nullptr){
144  throwRuntimeError(strerror(errno));
145  }
146  close();
147  fptr = fp;
148  }
149  inline bool PStream::try_open(const char *cmd,const char *modes){
150  FILE *fp = BTK_POPEN(cmd,modes);
151  if(fp == nullptr){
152  return false;
153  }
154  close();
155  fptr = fp;
156  return true;
157  }
158  //Readline
159  inline PStream &operator >>(PStream &stream,std::string &str){
160  int ch;
161  while(not std::feof(*stream)){
162  ch = std::fgetc(*stream);
163  if(ch == EOF){
164  break;
165  }
166  else if(ch == '\n'){
167  break;
168  }
169  str += char(ch);
170  }
171  return stream;
172  }
173  //Write
174  inline PStream &operator <<(PStream &stream,std::string_view data){
175  std::fwrite(data.data(),sizeof(char),data.length(),*stream);
176  return stream;
177  }
178  //Assign
179  inline PStream &PStream::operator =(PStream &&pstream){
180  if(&pstream != this){
181  close();
182  fptr = pstream.fptr;
183  pstream.fptr = nullptr;
184  }
185  return *this;
186  }
187 };
188 
189 #endif // _BTK_POPEN_HPP_
bool bad()
Check the stream status.
Definition: popen.hpp:134
This header include many useful containers.
Definition: async.hpp:7
bool eof()
Check the stream at eof.
Definition: popen.hpp:137
Pipe stream to or from a process.
Definition: popen.hpp:29
friend PStream & operator<<(PStream &, std::string_view)
Write String to stream It w.
Definition: popen.hpp:174
friend PStream & operator>>(PStream &, std::string &)
Read a line to string.
Definition: popen.hpp:159
void close()
Close the stream.
Definition: popen.hpp:127
PStream & operator=(PStream &&)
Assign from a lval stream.
Definition: popen.hpp:179
void open(const char *cmd, const char *modes)
Open a new stream.
Definition: popen.hpp:141
bool try_open(const char *cmd, const char *modes)
Trt open a new stream.
Definition: popen.hpp:149