Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
8.1 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1992.
  5. //
  6. // File: FSTREAM.CXX
  7. //
  8. // Contents: Stream for accessing files with run-time libs.
  9. //
  10. // Classes: CStreamFile
  11. //
  12. // History: 16-Dec-92 AmyA Created from fstream.hxx
  13. //
  14. // Notes: _pCur always points to the current file position (within the
  15. // buffer) EXCEPT when _pCur == _pEnd. In this case, _fp
  16. // ALWAYS points to the current file position.
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <pch.cxx>
  20. #pragma hdrstop
  21. #include <fstream.hxx>
  22. IMPLEMENT_UNWIND ( CStreamFile );
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Member: CStreamFile::CStreamFile, public
  26. //
  27. // Synopsis: opens file for reading/writing
  28. //
  29. // Arguments: [filename] - ascii name of file on disk
  30. // [type] - new file/existing file
  31. //
  32. // History: 31-Jul-92 MikeHew Created
  33. //
  34. // Notes: FileType NewFile will open/destroy specified file
  35. // FileType ExistingFile will open file for reading/appending
  36. //
  37. //----------------------------------------------------------------------------
  38. EXPORTIMP
  39. CStreamFile::CStreamFile( const char * filename, FileType type )
  40. {
  41. switch( type )
  42. {
  43. case NewFile:
  44. _fp = fopen( filename, "wb+" );
  45. break;
  46. case NewOrExistingFile:
  47. _fp = fopen( filename, "rb+" );
  48. if ( !_fp )
  49. _fp = fopen( filename, "wb+" );
  50. break;
  51. case ExistingFile:
  52. _fp = fopen( filename, "rb" );
  53. break;
  54. }
  55. if ( _fp )
  56. {
  57. _pBuf = new BYTE [ defaultBufSize ];
  58. Win4Assert ( _pCur == _pEnd );
  59. // buffer will be filled when first character is read.
  60. }
  61. else
  62. _eof = TRUE;
  63. END_CONSTRUCTION ( CStreamFile );
  64. }
  65. //+-------------------------------------------------------------------------
  66. //
  67. // Member: CStreamFile::~CStreamFile, public
  68. //
  69. // Synopsis: Closes stream.
  70. //
  71. // History: 04-Aug-92 MikeHew Created
  72. //
  73. //--------------------------------------------------------------------------
  74. EXPORTIMP
  75. CStreamFile::~CStreamFile()
  76. {
  77. if ( _fp )
  78. {
  79. fclose( _fp );
  80. delete [] _pBuf;
  81. }
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Member: CStreamFile::Read, public
  86. //
  87. // Synopsis: Read data from file to destination
  88. //
  89. // Arguments: [dest] - pointer to destination
  90. // [size] - bytes to be read
  91. //
  92. // History: 31-Jul-92 MikeHew Created
  93. //
  94. // Notes:
  95. //
  96. //----------------------------------------------------------------------------
  97. EXPORTIMP unsigned APINOT
  98. CStreamFile::Read( void *dest, unsigned size )
  99. {
  100. BYTE *pBuf = (BYTE *)dest;
  101. ULONG unread = size;
  102. ULONG cb = (ULONG)(_pEnd - _pCur);
  103. ULONG cbRead = min ( size, cb );
  104. memcpy ( pBuf, _pCur, cbRead );
  105. pBuf += cbRead;
  106. _pCur += cbRead;
  107. unread -= cbRead;
  108. if ( unread > 0 )
  109. {
  110. Win4Assert ( _pCur == _pEnd ); // buffer should be "empty"
  111. // read more
  112. LONG cBuf = unread / defaultBufSize;
  113. if ( cBuf != 0 )
  114. {
  115. cbRead = fread ( pBuf, sizeof(BYTE), cBuf*defaultBufSize, _fp );
  116. pBuf += cbRead;
  117. unread -= cbRead;
  118. }
  119. if ( unread > 0 )
  120. {
  121. if ( FillBuf() )
  122. {
  123. cb = (ULONG)(_pEnd - _pCur);
  124. cbRead = min ( unread, cb );
  125. memcpy ( pBuf, _pCur, cbRead );
  126. _pCur += cbRead;
  127. unread -= cbRead;
  128. }
  129. }
  130. }
  131. return ( size - unread );
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // Member: CStreamFile::Write, public
  136. //
  137. // Synopsis: Write data to file from source buffer
  138. //
  139. // Arguments: [source] - pointer to source
  140. // [size] - bytes to be written
  141. //
  142. // History: 31-Jul-92 MikeHew Created
  143. //
  144. //----------------------------------------------------------------------------
  145. EXPORTIMP unsigned APINOT
  146. CStreamFile::Write( const void *source, unsigned size )
  147. {
  148. //
  149. // The seeks are to guarantee seeks between read and write.
  150. //
  151. fseek( _fp, -((long)( _pEnd - _pCur )), SEEK_CUR ); // Seek to current position
  152. // in stream
  153. unsigned cbWritten = fwrite( source, 1, size, _fp );
  154. fseek( _fp, 0, SEEK_CUR );
  155. _pCur = _pEnd; // This guarantees a FillBuf() for the next buffer read
  156. return cbWritten;
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Member: CStreamFile::Seek, public
  161. //
  162. // Synopsis: Move pointer to specified offset in file
  163. //
  164. // Arguments: [offset] - signed offset from origin
  165. // [origin] - one of the following options:
  166. //
  167. // CUR => offset from current position
  168. // END => offset from end of file
  169. // (default) SET => offset from beginning of file
  170. //
  171. // History: 04-Aug-92 MikeHew Created
  172. //
  173. //----------------------------------------------------------------------------
  174. EXPORTIMP int APINOT
  175. CStreamFile::Seek( LONG offset, CStream::SEEK origin )
  176. {
  177. _eof = FALSE;
  178. if ( _pCur == _pEnd ) // the buffer is out-of-date anyway
  179. {
  180. return fseek( _fp, offset, origin );
  181. }
  182. LONG newBufOffset;
  183. LONG oldBufOffset = (LONG)(_pCur - _pBuf);
  184. LONG curFilePos = ftell ( _fp ) - (LONG)( _pEnd - _pCur );
  185. // figure out the offset relative to the beginning of the buffer
  186. switch ( origin )
  187. {
  188. case CStream::SET:
  189. // test for seeking before beginning of file
  190. if ( offset < 0 )
  191. return FALSE;
  192. newBufOffset = offset - curFilePos + oldBufOffset;
  193. break;
  194. case CStream::END:
  195. {
  196. int fileSize = Size();
  197. // test for seeking before beginning of file
  198. if ( offset < -fileSize )
  199. return FALSE;
  200. newBufOffset = offset + fileSize - curFilePos + oldBufOffset;
  201. break;
  202. }
  203. case CStream::CUR:
  204. // test for seeking before beginning of file
  205. if ( curFilePos + offset < 0 )
  206. return FALSE;
  207. newBufOffset = offset + oldBufOffset;
  208. break;
  209. }
  210. _eof = FALSE;
  211. // Check to see if newOffset is within current buffer
  212. if ( ( newBufOffset >= 0 ) && ( newBufOffset < ( _pEnd - _pBuf ) ) )
  213. {
  214. _pCur = _pBuf + newBufOffset;
  215. return TRUE;
  216. }
  217. // Seek to new location
  218. if ( origin == CStream::CUR )
  219. offset -= (LONG)(_pEnd - _pCur); // _fp pos is not current pos, so adjust
  220. // offset
  221. _pCur = _pEnd; // This guarantees a FillBuf() for the next buffer read
  222. return fseek( _fp, offset, origin );
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // Member: CStreamFile::Size, public
  227. //
  228. // Returns Current size of stream.
  229. //
  230. // History: 03-Sep-92 KyleP Created
  231. //
  232. //----------------------------------------------------------------------------
  233. ULONG
  234. CStreamFile::Size()
  235. {
  236. fpos_t pos;
  237. ULONG size;
  238. fgetpos( _fp, &pos );
  239. fseek( _fp, 0, SEEK_END );
  240. size = ftell( _fp );
  241. fsetpos( _fp, &pos );
  242. return( size );
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Member: CStreamFile::FillBuf, public
  247. //
  248. // Synopsis: Fills the stream buffer from the file indicated by _fp and
  249. // sets all pointers and variables accordingly.
  250. //
  251. // Returns: TRUE if new information was put into the buffer, FALSE
  252. // if not.
  253. //
  254. // History: 23-Nov-92 AmyA Created
  255. //
  256. //----------------------------------------------------------------------------
  257. BOOL
  258. CStreamFile::FillBuf()
  259. {
  260. unsigned size = fread( _pBuf, sizeof(char), defaultBufSize, _fp );
  261. _pEnd = _pBuf + size;
  262. _pCur = _pBuf;
  263. if ( size == 0 )
  264. {
  265. _eof = TRUE;
  266. return FALSE;
  267. }
  268. return TRUE;
  269. }