1/*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkTestStreamEOF.cxx.in 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14=========================================================================*/ 15 16// Many C++ streams libraries have buggy conditions when reading 17// reaches the end of a file. When an ifstream attempts to read past 18// the end of the file, the "eof" and "fail" bits are set. Clearing 19// the fail bit should be enough to allow seekg() to work and tellg() 20// to report the file position. Some stream libraries have bugs in 21// this case. This source file tests the severity of the eof 22// conditions for a compiler. 23// 24// Severity levels are reported in terms of the extent of the 25// work-around required: 26// 27// 0 - No bug exists. 28// 1 - User must clear eof bit. 29// 2 - User must clear eof bit and re-seek to end. 30// 3 - User must clear eof bit and call _M_seek_return on the filebuf. 31// 126 - Could not open sample input file. 32// 127 - Unknown severity level. 33// 34// Severity level 3 is only known to exist for -LANG:std streams on 35// the SGI MIPSpro 7.30 - 7.3.1.1 compiler versions. The cause of the 36// bug is a code pattern like this: 37// 38// _M_in_error_mode = true; 39// while(!_M_in_error_mode) { _M_in_error_mode = false; } 40// 41// It requires directly calling a non-public member function in the 42// filebuf instance on the stream to escape the bad state. 43// Unfortunately there is no way to detect the patch level of the 44// compiler from the preprocessor, so we need to actually try the 45// call. 46 47#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION) 48# if _COMPILER_VERSION == 730 49# define VTK_SGI_730 50# endif 51#endif 52 53#if defined(_MSC_VER) 54# pragma warning (push, 1) 55#endif 56 57// Include the streams library. Hack access to SGI stream 58// implementation for MIPSpro 7.3 compiler. 59#if defined(VTK_SGI_730) 60# define protected public 61# define private public 62#endif 63#include <fstream> 64 using std::ifstream; 65 using std::ios; 66#if defined(VTK_SGI_730) 67# undef protected 68# undef private 69#endif 70 71#if defined(_MSC_VER) 72# pragma warning (pop) 73#endif 74 75int main() 76{ 77 const char* fname = "@VTK_TEST_STREAM_EOF_CXX@"; 78 79 // Open the file. 80#if defined(_WIN32) 81 ifstream fin(fname, ios::binary | ios::in); 82#else 83 ifstream fin(fname, ios::in); 84#endif 85 86 // Make sure we opened the file. 87 if(!fin) 88 { 89 return 126; 90 } 91 92 // Go to eof in a way that exposes the bug everywhere. 93 char c = 0; 94 fin.seekg(-1, ios::end); 95 while(fin.get(c)); 96 97 // Clear the fail bit so tellg() is supposed to return something 98 // other than -1. 99 fin.clear(fin.rdstate() & ~ios::failbit); 100 if(fin.tellg() >= 0) 101 { 102 // Nothing is wrong with eof for this streams library. 103 return 0; 104 } 105 106 // Some streams return -1 from tellg() if eof is set. 107 fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); 108 if(fin.tellg() >= 0) 109 { 110 return 1; 111 } 112 113 // Some streams still return -1 from tellg. Try seeking to get it 114 // out of this strange state. 115 fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); 116 fin.seekg(0, ios::end); 117 if(fin.tellg() >= 0) 118 { 119 return 2; 120 } 121 122 // Only SGI 7.30 to 7.3.1.1 is known to get this far. Try to escape 123 // the bad state. 124#if defined(VTK_SGI_730) 125 fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); 126 fin.rdbuf()->_M_seek_return(0, 0); 127 if(fin.tellg() >= 0) 128 { 129 return 3; 130 } 131#endif 132 133 return 127; 134} 135