filemem.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_CORE3_SEG
  12. #pragma code_seg(AFX_CORE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. ////////////////////////////////////////////////////////////////////////////
  20. // CMemFile implementation
  21. CMemFile::CMemFile(UINT nGrowBytes)
  22. {
  23. ASSERT(nGrowBytes <= UINT_MAX);
  24. m_nGrowBytes = nGrowBytes;
  25. m_nPosition = 0;
  26. m_nBufferSize = 0;
  27. m_nFileSize = 0;
  28. m_lpBuffer = NULL;
  29. m_bAutoDelete = TRUE;
  30. }
  31. CMemFile::CMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
  32. {
  33. ASSERT(nGrowBytes <= UINT_MAX);
  34. m_nGrowBytes = nGrowBytes;
  35. m_nPosition = 0;
  36. m_nBufferSize = nBufferSize;
  37. m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
  38. m_lpBuffer = lpBuffer;
  39. m_bAutoDelete = FALSE;
  40. }
  41. void CMemFile::Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
  42. {
  43. ASSERT(m_lpBuffer == NULL);
  44. m_nGrowBytes = nGrowBytes;
  45. m_nPosition = 0;
  46. m_nBufferSize = nBufferSize;
  47. m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
  48. m_lpBuffer = lpBuffer;
  49. m_bAutoDelete = FALSE;
  50. }
  51. BYTE* CMemFile::Detach()
  52. {
  53. BYTE* lpBuffer = m_lpBuffer;
  54. m_lpBuffer = NULL;
  55. m_nFileSize = 0;
  56. m_nBufferSize = 0;
  57. m_nPosition = 0;
  58. return lpBuffer;
  59. }
  60. CMemFile::~CMemFile()
  61. {
  62. // Close should have already been called, but we check anyway
  63. if (m_lpBuffer)
  64. Close();
  65. ASSERT(m_lpBuffer == NULL);
  66. m_nGrowBytes = 0;
  67. m_nPosition = 0;
  68. m_nBufferSize = 0;
  69. m_nFileSize = 0;
  70. }
  71. BYTE* CMemFile::Alloc(DWORD nBytes)
  72. {
  73. return (BYTE*)malloc((UINT)nBytes);
  74. }
  75. BYTE* CMemFile::Realloc(BYTE* lpMem, DWORD nBytes)
  76. {
  77. return (BYTE*)realloc(lpMem, (UINT)nBytes);
  78. }
  79. #pragma intrinsic(memcpy)
  80. BYTE* CMemFile::Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
  81. UINT nBytes)
  82. {
  83. ASSERT(lpMemTarget != NULL);
  84. ASSERT(lpMemSource != NULL);
  85. ASSERT(AfxIsValidAddress(lpMemTarget, nBytes));
  86. ASSERT(AfxIsValidAddress(lpMemSource, nBytes, FALSE));
  87. return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
  88. }
  89. #pragma function(memcpy)
  90. void CMemFile::Free(BYTE* lpMem)
  91. {
  92. ASSERT(lpMem != NULL);
  93. free(lpMem);
  94. }
  95. DWORD CMemFile::GetPosition() const
  96. {
  97. ASSERT_VALID(this);
  98. return m_nPosition;
  99. }
  100. void CMemFile::GrowFile(DWORD dwNewLen)
  101. {
  102. ASSERT_VALID(this);
  103. if (dwNewLen > m_nBufferSize)
  104. {
  105. // grow the buffer
  106. DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
  107. // watch out for buffers which cannot be grown!
  108. ASSERT(m_nGrowBytes != 0);
  109. if (m_nGrowBytes == 0)
  110. AfxThrowMemoryException();
  111. // determine new buffer size
  112. while (dwNewBufferSize < dwNewLen)
  113. dwNewBufferSize += m_nGrowBytes;
  114. // allocate new buffer
  115. BYTE* lpNew;
  116. if (m_lpBuffer == NULL)
  117. lpNew = Alloc(dwNewBufferSize);
  118. else
  119. lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
  120. if (lpNew == NULL)
  121. AfxThrowMemoryException();
  122. m_lpBuffer = lpNew;
  123. m_nBufferSize = dwNewBufferSize;
  124. }
  125. ASSERT_VALID(this);
  126. }
  127. void CMemFile::SetLength(DWORD dwNewLen)
  128. {
  129. ASSERT_VALID(this);
  130. if (dwNewLen > m_nBufferSize)
  131. GrowFile(dwNewLen);
  132. if (dwNewLen < m_nPosition)
  133. m_nPosition = dwNewLen;
  134. m_nFileSize = dwNewLen;
  135. ASSERT_VALID(this);
  136. }
  137. UINT CMemFile::Read(void* lpBuf, UINT nCount)
  138. {
  139. ASSERT_VALID(this);
  140. if (nCount == 0)
  141. return 0;
  142. ASSERT(lpBuf != NULL);
  143. ASSERT(AfxIsValidAddress(lpBuf, nCount));
  144. if (m_nPosition > m_nFileSize)
  145. return 0;
  146. UINT nRead;
  147. if (m_nPosition + nCount > m_nFileSize)
  148. nRead = (UINT)(m_nFileSize - m_nPosition);
  149. else
  150. nRead = nCount;
  151. Memcpy((BYTE*)lpBuf, (BYTE*)m_lpBuffer + m_nPosition, nRead);
  152. m_nPosition += nRead;
  153. ASSERT_VALID(this);
  154. return nRead;
  155. }
  156. void CMemFile::Write(const void* lpBuf, UINT nCount)
  157. {
  158. ASSERT_VALID(this);
  159. if (nCount == 0)
  160. return;
  161. ASSERT(lpBuf != NULL);
  162. ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  163. if (m_nPosition + nCount > m_nBufferSize)
  164. GrowFile(m_nPosition + nCount);
  165. ASSERT(m_nPosition + nCount <= m_nBufferSize);
  166. Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
  167. m_nPosition += nCount;
  168. if (m_nPosition > m_nFileSize)
  169. m_nFileSize = m_nPosition;
  170. ASSERT_VALID(this);
  171. }
  172. LONG CMemFile::Seek(LONG lOff, UINT nFrom)
  173. {
  174. ASSERT_VALID(this);
  175. ASSERT(nFrom == begin || nFrom == end || nFrom == current);
  176. LONG lNewPos = m_nPosition;
  177. if (nFrom == begin)
  178. lNewPos = lOff;
  179. else if (nFrom == current)
  180. lNewPos += lOff;
  181. else if (nFrom == end)
  182. lNewPos = m_nFileSize + lOff;
  183. else
  184. return -1;
  185. if (lNewPos < 0)
  186. AfxThrowFileException(CFileException::badSeek);
  187. m_nPosition = lNewPos;
  188. ASSERT_VALID(this);
  189. return m_nPosition;
  190. }
  191. void CMemFile::Flush()
  192. {
  193. ASSERT_VALID(this);
  194. }
  195. void CMemFile::Close()
  196. {
  197. ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
  198. !m_bAutoDelete || AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
  199. ASSERT(m_nFileSize <= m_nBufferSize);
  200. m_nGrowBytes = 0;
  201. m_nPosition = 0;
  202. m_nBufferSize = 0;
  203. m_nFileSize = 0;
  204. if (m_lpBuffer && m_bAutoDelete)
  205. Free(m_lpBuffer);
  206. m_lpBuffer = NULL;
  207. }
  208. void CMemFile::Abort()
  209. {
  210. ASSERT_VALID(this);
  211. Close();
  212. }
  213. void CMemFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  214. {
  215. ASSERT_VALID(this);
  216. AfxThrowNotSupportedException();
  217. }
  218. void CMemFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  219. {
  220. ASSERT_VALID(this);
  221. AfxThrowNotSupportedException();
  222. }
  223. CFile* CMemFile::Duplicate() const
  224. {
  225. ASSERT_VALID(this);
  226. AfxThrowNotSupportedException();
  227. return NULL;
  228. }
  229. // only CMemFile supports "direct buffering" interaction with CArchive
  230. UINT CMemFile::GetBufferPtr(UINT nCommand, UINT nCount,
  231. void** ppBufStart, void**ppBufMax)
  232. {
  233. ASSERT(nCommand == bufferCheck || nCommand == bufferCommit ||
  234. nCommand == bufferRead || nCommand == bufferWrite);
  235. if (nCommand == bufferCheck)
  236. return 1; // just a check for direct buffer support
  237. if (nCommand == bufferCommit)
  238. {
  239. // commit buffer
  240. ASSERT(ppBufStart == NULL);
  241. ASSERT(ppBufMax == NULL);
  242. m_nPosition += nCount;
  243. if (m_nPosition > m_nFileSize)
  244. m_nFileSize = m_nPosition;
  245. return 0;
  246. }
  247. ASSERT(nCommand == bufferWrite || nCommand == bufferRead);
  248. ASSERT(ppBufStart != NULL);
  249. ASSERT(ppBufMax != NULL);
  250. // when storing, grow file as necessary to satisfy buffer request
  251. if (nCommand == bufferWrite && m_nPosition + nCount > m_nBufferSize)
  252. GrowFile(m_nPosition + nCount);
  253. // store buffer max and min
  254. *ppBufStart = m_lpBuffer + m_nPosition;
  255. // end of buffer depends on whether you are reading or writing
  256. if (nCommand == bufferWrite)
  257. *ppBufMax = m_lpBuffer + min(m_nBufferSize, m_nPosition + nCount);
  258. else
  259. {
  260. if (nCount == (UINT)-1)
  261. nCount = m_nBufferSize - m_nPosition;
  262. *ppBufMax = m_lpBuffer + min(m_nFileSize, m_nPosition + nCount);
  263. m_nPosition += LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
  264. }
  265. // return number of bytes in returned buffer space (may be <= nCount)
  266. return LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. // CMemFile diagonstics
  270. #ifdef _DEBUG
  271. void CMemFile::Dump(CDumpContext& dc) const
  272. {
  273. CFile::Dump(dc);
  274. dc << "m_nFileSize = " << m_nFileSize;
  275. dc << "\nm_nBufferSize = " << m_nBufferSize;
  276. dc << "\nm_nPosition = " << m_nPosition;
  277. dc << "\nm_nGrowBytes = " << m_nGrowBytes;
  278. dc << "\n";
  279. }
  280. void CMemFile::AssertValid() const
  281. {
  282. CFile::AssertValid();
  283. ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
  284. AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
  285. ASSERT(m_nFileSize <= m_nBufferSize);
  286. // m_nPosition might be after the end of file, so we cannot ASSERT
  287. // its validity
  288. }
  289. #endif // _DEBUG
  290. #ifdef AFX_INIT_SEG
  291. #pragma code_seg(AFX_INIT_SEG)
  292. #endif
  293. IMPLEMENT_DYNAMIC(CMemFile, CFile)
  294. /////////////////////////////////////////////////////////////////////////////