|
1 /* |
|
2 * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
3 * |
|
4 * Copyright (c) 1999 |
|
5 * Silicon Graphics Computer Systems, Inc. |
|
6 * |
|
7 * Copyright (c) 1999 |
|
8 * Boris Fomitchev |
|
9 * |
|
10 * This material is provided "as is", with absolutely no warranty expressed |
|
11 * or implied. Any use is at your own risk. |
|
12 * |
|
13 * Permission to use or copy this software for any purpose is hereby granted |
|
14 * without fee, provided the above notices are retained on all copies. |
|
15 * Permission to modify the code and to distribute modified code is granted, |
|
16 * provided the above notices are retained, and a notice that the code was |
|
17 * modified is included with the above copyright notice. |
|
18 * |
|
19 */ |
|
20 |
|
21 #include "stlport_prefix.h" |
|
22 #include "stdio_streambuf.h" |
|
23 // #include "file_streambuf.h" |
|
24 |
|
25 #ifdef _STLP_UNIX |
|
26 # include <sys/types.h> |
|
27 # include <sys/stat.h> |
|
28 #endif /* __unix */ |
|
29 |
|
30 #include <fstream> |
|
31 #include <limits> |
|
32 #include "fstream_impl.h" |
|
33 |
|
34 #if defined (_STLP_USE_WIN32_IO) && !defined(_STLP_WCE) |
|
35 # if defined (__BORLANDC__) |
|
36 // # include <cio.h> |
|
37 # include <cfcntl.h> |
|
38 # else |
|
39 # include <io.h> |
|
40 # include <fcntl.h> |
|
41 # endif |
|
42 # include <sys/stat.h> |
|
43 #endif |
|
44 |
|
45 _STLP_BEGIN_NAMESPACE |
|
46 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
47 |
|
48 // Compare with streamoff definition in stl/char_traits.h! |
|
49 |
|
50 #ifdef _STLP_USE_DEFAULT_FILE_OFFSET |
|
51 # define FSEEK fseek |
|
52 # define FTELL ftell |
|
53 # define FSTAT fstat |
|
54 # define STAT stat |
|
55 # define FSETPOS fsetpos |
|
56 # define FGETPOS fgetpos |
|
57 # define FPOS_T fpos_t |
|
58 #elif defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE) /* || defined(__USE_FILE_OFFSET64) */ \ |
|
59 /* || (defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)) */ /* || defined(__sgi) */ |
|
60 # define FSEEK fseeko64 |
|
61 # define FTELL ftello64 |
|
62 # define FSTAT fstat64 |
|
63 # define STAT stat64 |
|
64 # define FSETPOS fsetpos64 |
|
65 # define FGETPOS fgetpos64 |
|
66 # define FPOS_T fpos64_t |
|
67 #else |
|
68 # define FSEEK fseek |
|
69 # define FTELL ftell |
|
70 # define FSTAT fstat |
|
71 # define STAT stat |
|
72 # define FSETPOS fsetpos |
|
73 # define FGETPOS fgetpos |
|
74 # define FPOS_T fpos_t |
|
75 #endif |
|
76 |
|
77 //---------------------------------------------------------------------- |
|
78 // Class stdio_streambuf_base |
|
79 |
|
80 stdio_streambuf_base::stdio_streambuf_base(FILE* file) |
|
81 : /* _STLP_STD::FILE_basic_streambuf(file, 0), */ |
|
82 _M_file(file) |
|
83 {} |
|
84 |
|
85 stdio_streambuf_base::~stdio_streambuf_base() { |
|
86 _STLP_VENDOR_CSTD::fflush(_M_file); |
|
87 } |
|
88 |
|
89 _STLP_STD::streambuf* stdio_streambuf_base::setbuf(char* s, streamsize n) { |
|
90 #ifdef _STLP_WCE |
|
91 // no buffering in windows ce .NET |
|
92 #else |
|
93 size_t __n_size_t = (sizeof(streamsize) > sizeof(size_t)) ? __STATIC_CAST(size_t, (min)(__STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()), n)) |
|
94 : __STATIC_CAST(size_t, n); |
|
95 _STLP_VENDOR_CSTD::setvbuf(_M_file, s, (s == 0 && n == 0) ? _IONBF : _IOFBF, __n_size_t); |
|
96 #endif |
|
97 return this; |
|
98 } |
|
99 |
|
100 stdio_streambuf_base::pos_type |
|
101 stdio_streambuf_base::seekoff(off_type off, ios_base::seekdir dir, |
|
102 ios_base::openmode /* mode */) { |
|
103 int whence; |
|
104 switch (dir) { |
|
105 case ios_base::beg: |
|
106 whence = SEEK_SET; |
|
107 break; |
|
108 case ios_base::cur: |
|
109 whence = SEEK_CUR; |
|
110 break; |
|
111 case ios_base::end: |
|
112 whence = SEEK_END; |
|
113 break; |
|
114 default: |
|
115 return pos_type(-1); |
|
116 } |
|
117 |
|
118 if (off <= numeric_limits<off_type>::max() && FSEEK(_M_file, off, whence) == 0) { |
|
119 FPOS_T pos; |
|
120 FGETPOS(_M_file, &pos); |
|
121 // added 21 june 00 mdb,rjf,wjs: glibc 2.2 changed fpos_t to be a struct instead |
|
122 // of a primitive type |
|
123 #if (defined (__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)))) |
|
124 return pos_type((streamoff)pos.__pos); |
|
125 #elif defined (__ISCPP__) || defined (__MVS__) || defined (__OS400__) |
|
126 return pos_type(pos.__fpos_elem[ 0 ]); |
|
127 #elif defined (__EMX__) |
|
128 return pos_type((streamoff)pos._pos); |
|
129 #else |
|
130 return pos_type(pos); |
|
131 #endif |
|
132 } |
|
133 else |
|
134 return pos_type(-1); |
|
135 } |
|
136 |
|
137 |
|
138 stdio_streambuf_base::pos_type |
|
139 stdio_streambuf_base::seekpos(pos_type pos, ios_base::openmode /* mode */) { |
|
140 // added 21 june 00 mdb,rjf,wjs: glibc 2.2 changed fpos_t to be a struct instead |
|
141 // of a primitive type |
|
142 #if (defined(__GLIBC__) && ( (__GLIBC__ > 2) || ( (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2) ) ) ) |
|
143 FPOS_T p; |
|
144 p.__pos = pos; |
|
145 # ifdef _STLP_USE_UCLIBC |
|
146 # ifdef __STDIO_MBSTATE |
|
147 memset( &(p.__mbstate), 0, sizeof(p.__mbstate) ); |
|
148 # endif |
|
149 # ifdef __STDIO_WIDE |
|
150 p.mblen_pending = 0; |
|
151 # endif |
|
152 # else |
|
153 memset( &(p.__state), 0, sizeof(p.__state) ); |
|
154 # endif |
|
155 #elif defined (__MVS__) || defined (__OS400__) |
|
156 FPOS_T p; |
|
157 p.__fpos_elem[0] = pos; |
|
158 #elif defined(__EMX__) |
|
159 FPOS_T p; |
|
160 p._pos = pos; |
|
161 memset( &(p._mbstate), 0, sizeof(p._mbstate) ); |
|
162 #else |
|
163 FPOS_T p(pos); |
|
164 #endif |
|
165 |
|
166 return FSETPOS(_M_file, &p) == 0 ? pos : pos_type(-1); |
|
167 } |
|
168 |
|
169 int stdio_streambuf_base::sync() { |
|
170 return _STLP_VENDOR_CSTD::fflush(_M_file) == 0 ? 0 : -1; |
|
171 } |
|
172 |
|
173 //---------------------------------------------------------------------- |
|
174 // Class stdio_istreambuf |
|
175 |
|
176 stdio_istreambuf::~stdio_istreambuf() {} |
|
177 |
|
178 streamsize stdio_istreambuf::showmanyc() { |
|
179 if (feof(_M_file)) |
|
180 return -1; |
|
181 else { |
|
182 #ifdef __SYMBIAN32__ |
|
183 int fd = fileno(_M_file); |
|
184 #else |
|
185 int fd = _FILE_fd(_M_file); |
|
186 #endif |
|
187 #ifdef _STLP_WCE |
|
188 (fd); // prevent warning about unused variable |
|
189 // not sure if i can mix win32 io mode with ftell but time will show |
|
190 // cannot use WIN32_IO implementation since missing stat |
|
191 streamsize tmp = FTELL(_M_file); |
|
192 FSEEK(_M_file, 0, SEEK_END); |
|
193 streamoff size= FTELL(_M_file)-tmp; |
|
194 FSEEK(_M_file, tmp, SEEK_SET); |
|
195 #elif defined (_STLP_USE_WIN32_IO) |
|
196 // in this case, __file_size works with Win32 fh , not libc one |
|
197 streamoff size; |
|
198 struct stat buf; |
|
199 if(FSTAT(fd, &buf) == 0 && ( _S_IFREG & buf.st_mode ) ) |
|
200 size = ( buf.st_size > 0 ? buf.st_size : 0); |
|
201 else |
|
202 size = 0; |
|
203 #else |
|
204 streamoff size = __file_size(fd); |
|
205 #endif |
|
206 // fbp : we can use ftell as this flavour always use stdio. |
|
207 streamsize pos = FTELL(_M_file); |
|
208 return pos >= 0 && size > pos ? size - pos : 0; |
|
209 } |
|
210 } |
|
211 |
|
212 stdio_istreambuf::int_type stdio_istreambuf::underflow() |
|
213 { |
|
214 #ifdef _STLP_WCE |
|
215 int c = fgetc(_M_file); |
|
216 #else |
|
217 int c = getc(_M_file); |
|
218 #endif |
|
219 if (c != EOF) { |
|
220 _STLP_VENDOR_CSTD::ungetc(c, _M_file); |
|
221 return c; |
|
222 } |
|
223 else |
|
224 return traits_type::eof(); |
|
225 } |
|
226 |
|
227 stdio_istreambuf::int_type stdio_istreambuf::uflow() { |
|
228 #ifdef _STLP_WCE |
|
229 int c = fgetc(_M_file); |
|
230 #else |
|
231 int c = getc(_M_file); |
|
232 #endif |
|
233 return c != EOF ? c : traits_type::eof(); |
|
234 } |
|
235 |
|
236 stdio_istreambuf::int_type stdio_istreambuf::pbackfail(int_type c) { |
|
237 if (c != traits_type::eof()) { |
|
238 int result = _STLP_VENDOR_CSTD::ungetc(c, _M_file); |
|
239 return result != EOF ? result : traits_type::eof(); |
|
240 } |
|
241 else{ |
|
242 if (this->eback() < this->gptr()) { |
|
243 this->gbump(-1); |
|
244 return traits_type::not_eof(c); |
|
245 } |
|
246 else |
|
247 return traits_type::eof(); |
|
248 } |
|
249 } |
|
250 |
|
251 //---------------------------------------------------------------------- |
|
252 // Class stdio_ostreambuf |
|
253 |
|
254 stdio_ostreambuf::~stdio_ostreambuf() {} |
|
255 |
|
256 streamsize stdio_ostreambuf::showmanyc() { |
|
257 return -1; |
|
258 } |
|
259 |
|
260 stdio_ostreambuf::int_type stdio_ostreambuf::overflow(int_type c) { |
|
261 // Write the existing buffer, without writing any additional character. |
|
262 if (c == traits_type::eof()) { |
|
263 // Do we have a buffer to write? |
|
264 ptrdiff_t unwritten = this->pptr() - this->pbase(); |
|
265 if (unwritten != 0) { |
|
266 _STLP_VENDOR_CSTD::fflush(_M_file); |
|
267 // Test if the write succeeded. |
|
268 if (this->pptr() - this->pbase() < unwritten) |
|
269 return traits_type::not_eof(c); |
|
270 else |
|
271 return traits_type::eof(); |
|
272 } |
|
273 |
|
274 // We always succeed if we don't have to do anything. |
|
275 else |
|
276 return traits_type::not_eof(c); |
|
277 } |
|
278 |
|
279 // Write the character c, and whatever else might be in the buffer. |
|
280 else { |
|
281 #ifdef _STLP_WCE |
|
282 int result = fputc(c, _M_file); |
|
283 #else |
|
284 int result = putc(c, _M_file); |
|
285 #endif |
|
286 return result != EOF ? result : traits_type::eof(); |
|
287 } |
|
288 } |
|
289 |
|
290 _STLP_MOVE_TO_STD_NAMESPACE |
|
291 _STLP_END_NAMESPACE |
|
292 |
|
293 // Local Variables: |
|
294 // mode:C++ |
|
295 // End: |
|
296 |