Commit | Line | Data |
---|---|---|
e93545dd GE |
1 | /*************************************************************************** |
2 | inpipestream.hxx - C++ streambuffer wrapper | |
3 | ------------------- | |
4 | begin : Thu Dec 27 2001 | |
5 | copyright : (C) 2001 by Intra2net AG | |
6 | email : intranator@intra2net.com | |
7 | ***************************************************************************/ | |
8 | ||
9 | #ifndef _PIPESTREAM | |
10 | #define _PIPESTREAM | |
11 | ||
12 | #include <string> | |
13 | #include <streambuf> | |
14 | #include <cstdio> | |
15 | ||
16 | #include "exception.hxx" | |
17 | ||
18 | // ATTENTION: A lot of mysterious STL bugs occured | |
19 | // with a "real" buffer (buffer larger than 1 byte and up to 100 bytes) | |
20 | // -> Keep it slow and working! | |
21 | ||
22 | class inpipebuf : public std::streambuf | |
23 | { | |
24 | protected: | |
25 | char buffer; | |
26 | FILE *pipe; | |
27 | ||
28 | public: | |
29 | inpipebuf(const std::string& command) | |
30 | { | |
31 | pipe = popen (command.c_str(), "r"); | |
32 | if (pipe == NULL) | |
33 | throw EXCEPTION (pipestream_error, "can't open program or permission denied"); | |
34 | ||
35 | // force underflow | |
36 | setg (&buffer, &buffer, &buffer); | |
37 | } | |
38 | ||
39 | ~inpipebuf() | |
40 | { | |
41 | if (pipe != NULL) | |
42 | pclose (pipe); | |
43 | ||
44 | pipe = NULL; | |
45 | } | |
46 | ||
47 | protected: | |
48 | virtual int_type underflow() | |
49 | { | |
50 | if (gptr() < egptr()) | |
51 | return traits_type::to_int_type(*gptr()); | |
52 | ||
53 | buffer = fgetc (pipe); | |
54 | if (feof (pipe)) | |
55 | { | |
56 | // ERROR or EOF | |
57 | return EOF; | |
58 | } | |
59 | ||
60 | setg (&buffer, &buffer, &buffer+sizeof(char)); | |
61 | ||
62 | return traits_type::to_int_type(*gptr()); | |
63 | } | |
64 | }; | |
65 | ||
66 | class inpipestream : public std::istream | |
67 | { | |
68 | protected: | |
69 | inpipebuf buf; | |
70 | public: | |
71 | inpipestream(const std::string& command) | |
72 | : buf(command), std::istream(&buf) | |
73 | {} | |
74 | }; | |
75 | ||
76 | class outpipebuf : public std::streambuf | |
77 | { | |
78 | protected: | |
79 | FILE *pipe; | |
80 | ||
81 | public: | |
82 | outpipebuf(const std::string& command) | |
83 | { | |
84 | pipe = popen (command.c_str(), "w"); | |
85 | if (pipe == NULL) | |
86 | throw EXCEPTION (pipestream_error, "can't open program or permission denied"); | |
87 | } | |
88 | ||
89 | ~outpipebuf() | |
90 | { | |
91 | if (pipe != NULL) | |
92 | pclose (pipe); | |
93 | ||
94 | pipe = NULL; | |
95 | } | |
96 | ||
97 | protected: | |
98 | virtual int_type overflow(int_type c) | |
99 | { | |
100 | if (c != EOF) | |
101 | { | |
102 | if (fputc(c,pipe)==EOF) | |
103 | return EOF; | |
104 | } | |
105 | return c; | |
106 | } | |
107 | ||
108 | virtual std::streamsize xsputn(const char* s, std::streamsize num) | |
109 | { | |
110 | return fwrite(s,num,1,pipe); | |
111 | } | |
112 | }; | |
113 | ||
114 | class outpipestream : public std::ostream | |
115 | { | |
116 | protected: | |
117 | outpipebuf buf; | |
118 | public: | |
119 | outpipestream(const std::string& command) | |
120 | : buf(command), std::ostream(&buf) | |
121 | {} | |
122 | }; | |
123 | ||
124 | #endif |