1 // Wrapper of C-language FILE struct -*- C++ -*- 2 3 // Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License along 17 // with this library; see the file COPYING. If not, write to the Free 18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 // USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 // 31 // ISO C++ 14882: 27.8 File-based streams 32 // 33 34 /** @file basic_file.h 35 * This is an internal header file, included by other library headers. 36 * You should not attempt to use it directly. 37 */ 38 39 #ifndef _CPP_BASIC_FILE 40 #define _CPP_BASIC_FILE 1 41 42 #pragma GCC system_header 43 44 #include <bits/c++config.h> 45 #include <ios> 46 #include <libioP.h> 47 48 namespace std 49 { 50 // Ulrich is going to make some detailed comment here, explaining 51 // all this unpleasantness, providing detailed performance analysis 52 // as to why we have to do all this lame vtable hacking instead of a 53 // sane, function-based approach. This verbiage will provide a clear 54 // and detailed description of the whole object-layout, 55 // vtable-swapping, sordid history of this hack. 56 template<typename _CharT> 57 struct __basic_file_base: public __c_file_type 58 { 59 virtual ~__basic_file_base__basic_file_base60 ~__basic_file_base() { }; 61 62 virtual int 63 overflow(int __c = EOF) = 0; 64 65 virtual int 66 underflow() = 0; 67 68 virtual int 69 uflow() = 0; 70 71 virtual int 72 pbackfail(int __c) = 0; 73 74 virtual streamsize 75 xsputn(const _CharT* __s, streamsize __n) = 0; 76 77 virtual streamsize 78 xsgetn(_CharT* __s, streamsize __n) = 0; 79 80 virtual streamoff 81 seekoff(streamoff __off, ios_base::seekdir __way, 82 ios_base::openmode __mode = ios_base::in | ios_base::out) = 0; 83 84 virtual streamoff 85 seekpos(streamoff __pos, 86 ios_base::openmode __mode = ios_base::in | ios_base::out) = 0; 87 88 virtual streambuf* 89 setbuf(_CharT* __b, int __len) = 0; 90 91 virtual int 92 sync() = 0; 93 94 virtual int 95 doallocate() = 0; 96 97 virtual streamsize 98 sys_read(_CharT* __s, streamsize __n) = 0; 99 100 virtual streamsize 101 sys_write(const _CharT* __s, streamsize __n) = 0; 102 103 virtual streamoff 104 sys_seek(streamoff __off, ios_base::seekdir __way) = 0; 105 106 virtual int 107 sys_close() = 0; 108 109 virtual int 110 sys_stat(void* __v) = 0; 111 112 virtual int 113 showmanyc() = 0; 114 115 virtual void 116 imbue(void* __v) = 0; 117 }; 118 119 // Some of these member functions are based on libio/filebuf.cc. 120 // Also note that the order and number of virtual functions has to precisely 121 // match the order and number in the _IO_jump_t struct defined in libioP.h. 122 template<typename _CharT> 123 class __basic_file: public __basic_file_base<_CharT> 124 { 125 # if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T) 126 __c_wfile_type _M_wfile; 127 # endif 128 129 public: 130 __basic_file(__c_lock* __lock = 0); 131 132 void 133 _M_open_mode(ios_base::openmode __mode, int& __p_mode, int& __rw_mode, 134 char* __c_mode); 135 136 // Equivalent to the normal fopen function. 137 __basic_file* 138 open(const char* __name, ios_base::openmode __mode, int __prot = 0664); 139 140 // Used for opening the standard streams, cin, cout, cerr, clog, 141 // and their wide-stream equivalents. Instead of calling open, it 142 // just sets 143 // - for libio: __c_file_type->_fileno and the respective _flags bits 144 // - for stdio: _M_cfile = __file and some internal flags 145 // and returns. 146 __basic_file* 147 sys_open(__c_file_type* __file, ios_base::openmode __mode); 148 149 _CharT 150 sys_getc(); 151 152 _CharT 153 sys_ungetc(_CharT); 154 155 __basic_file* 156 close(); 157 158 bool 159 is_open(); 160 161 int 162 fd(); 163 164 // NB: Must match FILE specific jump table starting here--this 165 // means all virtual functions starting with the dtor must match, 166 // slot by slot. For glibc-based dystems, this means the _IO_FILE 167 // as the FILE struct and _IO_jump_t as the jump table. 168 virtual 169 ~__basic_file(); // Takes the place of __finish. 170 171 virtual int 172 overflow(int __c = EOF); 173 174 virtual int 175 underflow(); 176 177 virtual int 178 uflow(); 179 180 virtual int 181 pbackfail(int __c); 182 183 // A complex "write" function that sets all of __c_file_type's 184 // pointers and associated data members correctly and manages its 185 // relation to the external byte sequence. 186 virtual streamsize 187 xsputn(const _CharT* __s, streamsize __n); 188 189 // A complex "read" function that sets all of __c_file_type's 190 // pointers and associated data members correctly and manages its 191 // relation to the external byte sequence. 192 virtual streamsize 193 xsgetn(_CharT* __s, streamsize __n); 194 195 // A complex "seekoff" function that sets all of __c_file_type's 196 // pointers and associated data members correctly and manages its 197 // relation to the external byte sequence. 198 virtual streamoff 199 seekoff(streamoff __off, ios_base::seekdir __way, 200 ios_base::openmode __mode = ios_base::in | ios_base::out); 201 202 // A complex "seekpos" function that sets all of __c_file_type's 203 // pointers and associated data members correctly and manages its 204 // relation to the external byte sequence. 205 virtual streamoff 206 seekpos(streamoff __pos, 207 ios_base::openmode __mode = ios_base::in | ios_base::out); 208 209 virtual streambuf* 210 setbuf(_CharT* __b, int __len); 211 212 virtual int 213 sync(); 214 215 virtual int 216 doallocate(); 217 218 // A simple read function for the external byte sequence, that 219 // does no mucking around with or setting of the pointers or flags 220 // in __c_file_type. 221 virtual streamsize 222 sys_read(_CharT* __s, streamsize __n); 223 224 // A simple write function for the external byte sequence, that 225 // does no mucking around with or setting of the pointers or flags 226 // in __c_file_type. 227 virtual streamsize 228 sys_write(const _CharT* __s, streamsize __n); 229 230 // A simple seek function for the external byte sequence, that 231 // does no mucking around with or setting of the pointers or flags 232 // in __c_file_type. 233 virtual streamoff 234 sys_seek(streamoff __off, ios_base::seekdir __way); 235 236 virtual int 237 sys_close(); 238 239 virtual int 240 sys_stat(void* __v); 241 242 virtual int 243 showmanyc(); 244 245 virtual void 246 imbue(void* __v); 247 }; 248 249 // __basic_file<char> specializations 250 template<> 251 __basic_file<char>::__basic_file(__c_lock* __lock); 252 253 template<> 254 int 255 __basic_file<char>::overflow(int __c); 256 257 template<> 258 int 259 __basic_file<char>::underflow(); 260 261 template<> 262 int 263 __basic_file<char>::uflow(); 264 265 template<> 266 int 267 __basic_file<char>::pbackfail(int __c); 268 269 template<> 270 streamsize 271 __basic_file<char>::xsputn(const char* __s, streamsize __n); 272 273 template<> 274 streamoff 275 __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way, 276 ios_base::openmode __mode); 277 278 template<> 279 streamoff 280 __basic_file<char>::seekpos(streamoff __pos, ios_base::openmode __mode); 281 282 template<> 283 streambuf* 284 __basic_file<char>::setbuf(char* __b, int __len); 285 286 template<> 287 int 288 __basic_file<char>::sync(); 289 290 template<> 291 int 292 __basic_file<char>::doallocate(); 293 294 // __basic_file<wchar_t> specializations 295 #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T) 296 template<> 297 __basic_file<wchar_t>::__basic_file(__c_lock* __lock); 298 299 template<> 300 int 301 __basic_file<wchar_t>::overflow(int __c); 302 303 template<> 304 int 305 __basic_file<wchar_t>::underflow(); 306 307 template<> 308 int 309 __basic_file<wchar_t>::uflow(); 310 311 template<> 312 int 313 __basic_file<wchar_t>::pbackfail(int __c); 314 315 template<> 316 streamsize 317 __basic_file<wchar_t>::xsputn(const wchar_t* __s, streamsize __n); 318 319 template<> 320 streamoff 321 __basic_file<wchar_t>::seekoff(streamoff __off, ios_base::seekdir __way, 322 ios_base::openmode __mode); 323 324 template<> 325 streamoff 326 __basic_file<wchar_t>::seekpos(streamoff __pos, ios_base::openmode __mode); 327 328 template<> 329 streambuf* 330 __basic_file<wchar_t>::setbuf(wchar_t* __b, int __len); 331 332 template<> 333 int 334 __basic_file<wchar_t>::sync(); 335 336 template<> 337 int 338 __basic_file<wchar_t>::doallocate(); 339 #endif 340 341 template<typename _CharT> ~__basic_file()342 __basic_file<_CharT>::~__basic_file() 343 { _IO_file_finish(this, 0); } 344 345 template<typename _CharT> 346 void _M_open_mode(ios_base::openmode __mode,int & __p_mode,int & __rw_mode,char *)347 __basic_file<_CharT>::_M_open_mode(ios_base::openmode __mode, 348 int& __p_mode, int& __rw_mode, 349 char* /*__c_mode*/) 350 { 351 #ifdef O_BINARY 352 bool __testb = __mode & ios_base::binary; 353 #endif 354 bool __testi = __mode & ios_base::in; 355 bool __testo = __mode & ios_base::out; 356 bool __testt = __mode & ios_base::trunc; 357 bool __testa = __mode & ios_base::app; 358 359 if (!__testi && __testo && !__testt && !__testa) 360 { 361 __p_mode = O_WRONLY | O_TRUNC | O_CREAT; 362 __rw_mode = _IO_NO_READS; 363 } 364 if (!__testi && __testo && !__testt && __testa) 365 { 366 __p_mode = O_WRONLY | O_APPEND | O_CREAT; 367 __rw_mode = _IO_NO_READS | _IO_IS_APPENDING; 368 } 369 if (!__testi && __testo && __testt && !__testa) 370 { 371 __p_mode = O_WRONLY | O_TRUNC | O_CREAT; 372 __rw_mode = _IO_NO_READS; 373 } 374 if (__testi && !__testo && !__testt && !__testa) 375 { 376 __p_mode = O_RDONLY; 377 __rw_mode = _IO_NO_WRITES; 378 } 379 if (__testi && __testo && !__testt && !__testa) 380 { 381 __p_mode = O_RDWR; 382 __rw_mode = 0; 383 } 384 if (__testi && __testo && __testt && !__testa) 385 { 386 __p_mode = O_RDWR | O_TRUNC | O_CREAT; 387 __rw_mode = 0; 388 } 389 #ifdef O_BINARY 390 if (__testb) 391 __p_mode |= O_BINARY; 392 #endif 393 } 394 395 template<typename _CharT> 396 __basic_file<_CharT>* sys_open(__c_file_type * __f,ios_base::openmode __mode)397 __basic_file<_CharT>::sys_open(__c_file_type* __f, 398 ios_base::openmode __mode) 399 { 400 __basic_file* __ret = NULL; 401 int __fd = fileno(__f); 402 int __p_mode = 0; 403 int __rw_mode = _IO_NO_READS + _IO_NO_WRITES; 404 char __c_mode[4]; 405 406 _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode); 407 408 if (!_IO_file_is_open(this)) 409 { 410 _fileno = __fd; 411 _flags &= ~(_IO_NO_READS + _IO_NO_WRITES); 412 _flags |= _IO_DELETE_DONT_CLOSE; 413 _offset = _IO_pos_BAD; 414 int __mask = _IO_NO_READS + _IO_NO_WRITES + _IO_IS_APPENDING; 415 _IO_mask_flags(this, __rw_mode, __mask); 416 } 417 418 return __ret; 419 } 420 421 template<typename _CharT> 422 __basic_file<_CharT>* open(const char * __name,ios_base::openmode __mode,int __prot)423 __basic_file<_CharT>::open(const char* __name, ios_base::openmode __mode, 424 int __prot) 425 { 426 __basic_file* __ret = NULL; 427 int __p_mode = 0; 428 int __rw_mode = _IO_NO_READS + _IO_NO_WRITES; 429 char __c_mode[4]; 430 431 _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode); 432 if (!_IO_file_is_open(this)) 433 { 434 __c_file_type* __f; 435 __f = _IO_file_open(this, __name, __p_mode, __prot, __rw_mode, 0); 436 __ret = __f ? this: NULL; 437 } 438 return __ret; 439 } 440 441 template<typename _CharT> 442 bool is_open()443 __basic_file<_CharT>::is_open() { return _fileno >= 0; } 444 445 template<typename _CharT> 446 __basic_file<_CharT>* close()447 __basic_file<_CharT>::close() 448 { 449 return _IO_file_close_it(this) ? static_cast<__basic_file*>(NULL) : this; 450 } 451 452 template<typename _CharT> 453 streamsize xsgetn(_CharT * __s,streamsize __n)454 __basic_file<_CharT>::xsgetn(_CharT* __s, streamsize __n) 455 { return _IO_file_xsgetn(this, __s, __n); } 456 457 // NB: Unused. 458 template<typename _CharT> 459 streamsize sys_read(_CharT * __s,streamsize __n)460 __basic_file<_CharT>::sys_read(_CharT* __s, streamsize __n) 461 { return _IO_file_read(this, __s, __n); } 462 463 // NB: Unused. 464 template<typename _CharT> 465 streamsize sys_write(const _CharT * __s,streamsize __n)466 __basic_file<_CharT>::sys_write(const _CharT* __s, streamsize __n) 467 { return _IO_file_write(this, __s, __n); } 468 469 // NB: Unused. 470 template<typename _CharT> 471 streamoff sys_seek(streamoff __pos,ios_base::seekdir __way)472 __basic_file<_CharT>::sys_seek(streamoff __pos, ios_base::seekdir __way) 473 { return _IO_file_seek(this, __pos, __way); } 474 475 // NB: Unused. 476 template<typename _CharT> 477 int sys_close()478 __basic_file<_CharT>::sys_close() 479 { return _IO_file_close(this); } 480 481 // NB: Unused. 482 template<typename _CharT> 483 int sys_stat(void * __v)484 __basic_file<_CharT>::sys_stat(void* __v) 485 { return _IO_file_stat(this, __v); } 486 487 // NB: Unused. 488 template<typename _CharT> 489 int showmanyc()490 __basic_file<_CharT>::showmanyc() { return EOF; } 491 492 // NB: Unused. 493 template<typename _CharT> 494 void imbue(void *)495 __basic_file<_CharT>::imbue(void* /*__v*/) { } 496 } // namespace std 497 498 #endif // _CPP_BASIC_FILE 499