00001 // Filename: streamWrapper.cxx 00002 // Created by: drose (11Nov08) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "streamWrapper.h" 00016 00017 //////////////////////////////////////////////////////////////////// 00018 // Function: IStreamWrapper::Destructor 00019 // Access: Published 00020 // Description: 00021 //////////////////////////////////////////////////////////////////// 00022 IStreamWrapper:: 00023 ~IStreamWrapper() { 00024 if (_owns_pointer) { 00025 // For some reason--compiler bug in gcc 3.2?--explicitly deleting 00026 // the stream pointer does not call the appropriate global delete 00027 // function; instead apparently calling the system delete 00028 // function. So we call the delete function by hand instead. 00029 #if !defined(WIN32_VC) && !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) 00030 _istream->~istream(); 00031 (*global_operator_delete)(_istream); 00032 #else 00033 delete _istream; 00034 #endif 00035 } 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: IStreamWrapper::read 00040 // Access: Public 00041 // Description: Atomically reads a number of bytes from the stream, 00042 // without error detection. If fewer bytes than 00043 // requested are read, quietly fills the remaining bytes 00044 // with 0. 00045 //////////////////////////////////////////////////////////////////// 00046 void IStreamWrapper:: 00047 read(char *buffer, streamsize num_bytes) { 00048 acquire(); 00049 _istream->clear(); 00050 _istream->read(buffer, num_bytes); 00051 streamsize read_bytes = _istream->gcount(); 00052 while (read_bytes < num_bytes) { 00053 // Fewer bytes than expected were read. Maybe more will be 00054 // coming later. 00055 release(); 00056 thread_yield(); 00057 acquire(); 00058 00059 _istream->read(buffer + read_bytes, num_bytes - read_bytes); 00060 streamsize this_read_bytes = _istream->gcount(); 00061 assert(this_read_bytes <= num_bytes - read_bytes); 00062 read_bytes += this_read_bytes; 00063 00064 if (this_read_bytes == 0) { 00065 // No, don't expect any more. 00066 memset(buffer + read_bytes, 0, num_bytes - read_bytes); 00067 break; 00068 } 00069 } 00070 assert(read_bytes <= num_bytes); 00071 release(); 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: IStreamWrapper::read 00076 // Access: Public 00077 // Description: Atomically reads a number of bytes from the stream. 00078 // Returns the number of bytes actually read. 00079 //////////////////////////////////////////////////////////////////// 00080 void IStreamWrapper:: 00081 read(char *buffer, streamsize num_bytes, streamsize &read_bytes) { 00082 acquire(); 00083 _istream->clear(); 00084 _istream->read(buffer, num_bytes); 00085 read_bytes = _istream->gcount(); 00086 assert(read_bytes <= num_bytes); 00087 release(); 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: IStreamWrapper::read 00092 // Access: Public 00093 // Description: Atomically reads a number of bytes from the stream. 00094 // Returns the number of bytes actually read, and 00095 // whether an eof condition was detected by the 00096 // operation. 00097 //////////////////////////////////////////////////////////////////// 00098 void IStreamWrapper:: 00099 read(char *buffer, streamsize num_bytes, streamsize &read_bytes, bool &eof) { 00100 acquire(); 00101 _istream->clear(); 00102 _istream->read(buffer, num_bytes); 00103 read_bytes = _istream->gcount(); 00104 assert(read_bytes <= num_bytes); 00105 eof = _istream->eof() || _istream->fail(); 00106 release(); 00107 } 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: IStreamWrapper::seek_read 00111 // Access: Public 00112 // Description: Atomically seeks to a particular offset from the 00113 // beginning of the file, and reads a number of bytes 00114 // from the stream. Returns the number of bytes 00115 // actually read, and whether an eof condition was 00116 // detected by the operation. 00117 //////////////////////////////////////////////////////////////////// 00118 void IStreamWrapper:: 00119 seek_read(streamsize pos, char *buffer, streamsize num_bytes, 00120 streamsize &read_bytes, bool &eof) { 00121 acquire(); 00122 _istream->clear(); 00123 _istream->seekg(pos); 00124 _istream->read(buffer, num_bytes); 00125 read_bytes = _istream->gcount(); 00126 assert(read_bytes <= num_bytes); 00127 eof = _istream->eof() || _istream->fail(); 00128 release(); 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: IStreamWrapper::seek_gpos_eof 00133 // Access: Public 00134 // Description: Atomically seeks to EOF and returns the gpos there; 00135 // that is, returns the file size. Note that the EOF 00136 // might have been moved in another thread by the time 00137 // this method returns. 00138 //////////////////////////////////////////////////////////////////// 00139 streamsize IStreamWrapper:: 00140 seek_gpos_eof() { 00141 streamsize pos; 00142 acquire(); 00143 _istream->seekg(0, ios::end); 00144 pos = _istream->tellg(); 00145 release(); 00146 00147 return pos; 00148 } 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: OStreamWrapper::Destructor 00152 // Access: Published 00153 // Description: 00154 //////////////////////////////////////////////////////////////////// 00155 OStreamWrapper:: 00156 ~OStreamWrapper() { 00157 if (_owns_pointer) { 00158 // For some reason--compiler bug in gcc 3.2?--explicitly deleting 00159 // the stream pointer does not call the appropriate global delete 00160 // function; instead apparently calling the system delete 00161 // function. So we call the delete function by hand instead. 00162 #if !defined(WIN32_VC) && !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) 00163 _ostream->~ostream(); 00164 (*global_operator_delete)(_ostream); 00165 #else 00166 delete _ostream; 00167 #endif 00168 } 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: OStreamWrapper::write 00173 // Access: Public 00174 // Description: Atomically writes a number of bytes to the stream, 00175 // without error detection. 00176 //////////////////////////////////////////////////////////////////// 00177 void OStreamWrapper:: 00178 write(const char *buffer, streamsize num_bytes) { 00179 acquire(); 00180 _ostream->write(buffer, num_bytes); 00181 release(); 00182 } 00183 00184 //////////////////////////////////////////////////////////////////// 00185 // Function: OStreamWrapper::read 00186 // Access: Public 00187 // Description: Atomically writes a number of bytes to the stream. 00188 // Returns whether a failure condition was detected by 00189 // the operation. 00190 //////////////////////////////////////////////////////////////////// 00191 void OStreamWrapper:: 00192 write(const char *buffer, streamsize num_bytes, bool &fail) { 00193 acquire(); 00194 _ostream->clear(); 00195 _ostream->write(buffer, num_bytes); 00196 fail = _ostream->fail(); 00197 release(); 00198 } 00199 00200 //////////////////////////////////////////////////////////////////// 00201 // Function: OStreamWrapper::seek_write 00202 // Access: Public 00203 // Description: Atomically seeks to a particular offset from the 00204 // beginning of the file, and writes a number of bytes 00205 // to the stream. Returns whether a failure condition 00206 // was detected by the operation. 00207 //////////////////////////////////////////////////////////////////// 00208 void OStreamWrapper:: 00209 seek_write(streamsize pos, const char *buffer, streamsize num_bytes, 00210 bool &fail) { 00211 acquire(); 00212 _ostream->clear(); 00213 _ostream->seekp(pos); 00214 00215 #ifdef WIN32_VC 00216 if (_ostream->fail() && _stringstream_hack && pos == 0) { 00217 // Ignore an unsuccessful attempt to seekp(0) if 00218 // _stringstream_hack is true. 00219 _ostream->clear(); 00220 } 00221 #endif // WIN32_VC 00222 00223 _ostream->write(buffer, num_bytes); 00224 fail = _ostream->fail(); 00225 release(); 00226 } 00227 00228 //////////////////////////////////////////////////////////////////// 00229 // Function: OStreamWrapper::seek_eof_write 00230 // Access: Public 00231 // Description: Atomically seeks to the end of the file, and writes a 00232 // number of bytes to the stream. Returns whether a 00233 // failure condition was detected by the operation. 00234 //////////////////////////////////////////////////////////////////// 00235 void OStreamWrapper:: 00236 seek_eof_write(const char *buffer, streamsize num_bytes, bool &fail) { 00237 acquire(); 00238 _ostream->clear(); 00239 _ostream->seekp(0, ios::end); 00240 00241 #ifdef WIN32_VC 00242 if (_ostream->fail() && _stringstream_hack) { 00243 // Ignore an unsuccessful attempt to seekp(0) if 00244 // _stringstream_hack is true. 00245 _ostream->clear(); 00246 } 00247 #endif // WIN32_VC 00248 00249 _ostream->write(buffer, num_bytes); 00250 fail = _ostream->fail(); 00251 release(); 00252 } 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function: OStreamWrapper::seek_ppos_eof 00256 // Access: Public 00257 // Description: Atomically seeks to EOF and returns the ppos there; 00258 // that is, returns the file size. Note that the EOF 00259 // might have been moved in another thread by the time 00260 // this method returns. 00261 //////////////////////////////////////////////////////////////////// 00262 streamsize OStreamWrapper:: 00263 seek_ppos_eof() { 00264 streamsize pos; 00265 acquire(); 00266 _ostream->seekp(0, ios::end); 00267 00268 #ifdef WIN32_VC 00269 if (_ostream->fail() && _stringstream_hack) { 00270 // Ignore an unsuccessful attempt to seekp(0) if 00271 // _stringstream_hack is true. 00272 _ostream->clear(); 00273 release(); 00274 return 0; 00275 } 00276 #endif // WIN32_VC 00277 00278 pos = _ostream->tellp(); 00279 release(); 00280 00281 return pos; 00282 } 00283 00284 //////////////////////////////////////////////////////////////////// 00285 // Function: StreamWrapper::Destructor 00286 // Access: Published 00287 // Description: 00288 //////////////////////////////////////////////////////////////////// 00289 StreamWrapper:: 00290 ~StreamWrapper() { 00291 if (_owns_pointer) { 00292 // For some reason--compiler bug in gcc 3.2?--explicitly deleting 00293 // the stream pointer does not call the appropriate global delete 00294 // function; instead apparently calling the system delete 00295 // function. So we call the delete function by hand instead. 00296 #if !defined(WIN32_VC) && !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) 00297 _iostream->~iostream(); 00298 (*global_operator_delete)(_iostream); 00299 #else 00300 delete _iostream; 00301 #endif 00302 } 00303 }