]>
Commit | Line | Data |
---|---|---|
0209cce5 JF |
1 | /* The following code declares classes to read from and write to |
2 | * file descriptore or file handles. | |
3 | * | |
4 | * See | |
5 | * http://www.josuttis.com/cppcode | |
6 | * for details and the latest version. | |
7 | * | |
8 | * - open: | |
9 | * - integrating BUFSIZ on some systems? | |
10 | * - optimized reading of multiple characters | |
11 | * - stream for reading AND writing | |
12 | * - i18n | |
13 | * | |
14 | * (C) Copyright Nicolai M. Josuttis 2001. | |
15 | * Permission to copy, use, modify, sell and distribute this software | |
16 | * is granted provided this copyright notice appears in all copies. | |
17 | * This software is provided "as is" without express or implied | |
18 | * warranty, and with no claim as to its suitability for any purpose. | |
19 | * | |
20 | * Version: Jul 28, 2002 | |
21 | * History: | |
22 | * Jul 28, 2002: bugfix memcpy() => memmove() | |
23 | * fdinbuf::underflow(): cast for return statements | |
24 | * Aug 05, 2001: first public version | |
25 | */ | |
26 | #ifndef BOOST_FDSTREAM_HPP | |
27 | #define BOOST_FDSTREAM_HPP | |
28 | ||
29 | #include <istream> | |
30 | #include <ostream> | |
31 | #include <streambuf> | |
32 | // for EOF: | |
33 | #include <cstdio> | |
34 | // for memmove(): | |
35 | #include <cstring> | |
36 | ||
37 | ||
38 | // low-level read and write functions | |
39 | #ifdef _MSC_VER | |
40 | # include <io.h> | |
41 | #else | |
42 | # include <unistd.h> | |
43 | //extern "C" { | |
44 | // int write (int fd, const char* buf, int num); | |
45 | // int read (int fd, char* buf, int num); | |
46 | //} | |
47 | #endif | |
48 | ||
49 | ||
50 | // BEGIN namespace BOOST | |
51 | namespace boost { | |
52 | ||
53 | ||
54 | /************************************************************ | |
55 | * fdostream | |
56 | * - a stream that writes on a file descriptor | |
57 | ************************************************************/ | |
58 | ||
59 | ||
60 | class fdoutbuf : public std::streambuf { | |
61 | protected: | |
62 | int fd; // file descriptor | |
63 | public: | |
64 | // constructor | |
65 | fdoutbuf (int _fd) : fd(_fd) { | |
66 | } | |
67 | protected: | |
68 | // write one character | |
69 | virtual int_type overflow (int_type c) { | |
70 | if (c != EOF) { | |
71 | char z = c; | |
72 | if (write (fd, &z, 1) != 1) { | |
73 | return EOF; | |
74 | } | |
75 | } | |
76 | return c; | |
77 | } | |
78 | // write multiple characters | |
79 | virtual | |
80 | std::streamsize xsputn (const char* s, | |
81 | std::streamsize num) { | |
82 | return write(fd,s,num); | |
83 | } | |
84 | }; | |
85 | ||
86 | class fdostream : public std::ostream { | |
87 | protected: | |
88 | fdoutbuf buf; | |
89 | public: | |
90 | fdostream (int fd) : std::ostream(0), buf(fd) { | |
91 | rdbuf(&buf); | |
92 | } | |
93 | }; | |
94 | ||
95 | ||
96 | /************************************************************ | |
97 | * fdistream | |
98 | * - a stream that reads on a file descriptor | |
99 | ************************************************************/ | |
100 | ||
101 | class fdinbuf : public std::streambuf { | |
102 | protected: | |
103 | int fd; // file descriptor | |
104 | protected: | |
105 | /* data buffer: | |
106 | * - at most, pbSize characters in putback area plus | |
107 | * - at most, bufSize characters in ordinary read buffer | |
108 | */ | |
109 | static const int pbSize = 4; // size of putback area | |
110 | static const int bufSize = 1024; // size of the data buffer | |
111 | char buffer[bufSize+pbSize]; // data buffer | |
112 | ||
113 | public: | |
114 | /* constructor | |
115 | * - initialize file descriptor | |
116 | * - initialize empty data buffer | |
117 | * - no putback area | |
118 | * => force underflow() | |
119 | */ | |
120 | fdinbuf (int _fd) : fd(_fd) { | |
121 | setg (buffer+pbSize, // beginning of putback area | |
122 | buffer+pbSize, // read position | |
123 | buffer+pbSize); // end position | |
124 | } | |
125 | ||
126 | protected: | |
127 | // insert new characters into the buffer | |
128 | virtual int_type underflow () { | |
129 | #ifndef _MSC_VER | |
130 | using std::memmove; | |
131 | #endif | |
132 | ||
133 | // is read position before end of buffer? | |
134 | if (gptr() < egptr()) { | |
135 | return traits_type::to_int_type(*gptr()); | |
136 | } | |
137 | ||
138 | /* process size of putback area | |
139 | * - use number of characters read | |
140 | * - but at most size of putback area | |
141 | */ | |
142 | int numPutback; | |
143 | numPutback = gptr() - eback(); | |
144 | if (numPutback > pbSize) { | |
145 | numPutback = pbSize; | |
146 | } | |
147 | ||
148 | /* copy up to pbSize characters previously read into | |
149 | * the putback area | |
150 | */ | |
151 | memmove (buffer+(pbSize-numPutback), gptr()-numPutback, | |
152 | numPutback); | |
153 | ||
154 | // read at most bufSize new characters | |
155 | int num; | |
156 | num = read (fd, buffer+pbSize, bufSize); | |
157 | if (num <= 0) { | |
158 | // ERROR or EOF | |
159 | return EOF; | |
160 | } | |
161 | ||
162 | // reset buffer pointers | |
163 | setg (buffer+(pbSize-numPutback), // beginning of putback area | |
164 | buffer+pbSize, // read position | |
165 | buffer+pbSize+num); // end of buffer | |
166 | ||
167 | // return next character | |
168 | return traits_type::to_int_type(*gptr()); | |
169 | } | |
170 | }; | |
171 | ||
172 | class fdistream : public std::istream { | |
173 | protected: | |
174 | fdinbuf buf; | |
175 | public: | |
176 | fdistream (int fd) : std::istream(0), buf(fd) { | |
177 | rdbuf(&buf); | |
178 | } | |
179 | }; | |
180 | ||
181 | ||
182 | } // END namespace boost | |
183 | ||
184 | #endif /*BOOST_FDSTREAM_HPP*/ |