Initial commit.
[pdfium.git] / core / src / fxcrt / fx_basic_buffer.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../include/fxcrt/fx_basic.h"\r
8 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_LPSTR buf);\r
9 CFX_BinaryBuf::CFX_BinaryBuf(IFX_Allocator* pAllocator)\r
10     : m_pAllocator(pAllocator)\r
11     , m_AllocStep(0)\r
12     , m_pBuffer(NULL)\r
13     , m_DataSize(0)\r
14     , m_AllocSize(0)\r
15 {\r
16 }\r
17 CFX_BinaryBuf::CFX_BinaryBuf(FX_STRSIZE size, IFX_Allocator* pAllocator)\r
18     : m_pAllocator(pAllocator)\r
19     , m_AllocStep(0)\r
20     , m_DataSize(size)\r
21     , m_AllocSize(size)\r
22 {\r
23     m_pBuffer = FX_Allocator_Alloc(m_pAllocator, FX_BYTE, size);\r
24 }\r
25 CFX_BinaryBuf::~CFX_BinaryBuf()\r
26 {\r
27     if (m_pBuffer) {\r
28         FX_Allocator_Free(m_pAllocator, m_pBuffer);\r
29     }\r
30 }\r
31 void CFX_BinaryBuf::Delete(int start_index, int count)\r
32 {\r
33     if (!m_pBuffer || start_index < 0 || start_index + count > m_DataSize) {\r
34         return;\r
35     }\r
36     FXSYS_memmove32(m_pBuffer + start_index, m_pBuffer + start_index + count, m_DataSize - start_index - count);\r
37     m_DataSize -= count;\r
38 }\r
39 void CFX_BinaryBuf::Clear()\r
40 {\r
41     m_DataSize = 0;\r
42 }\r
43 void CFX_BinaryBuf::DetachBuffer()\r
44 {\r
45     m_DataSize = 0;\r
46     m_pBuffer = NULL;\r
47     m_AllocSize = 0;\r
48 }\r
49 void CFX_BinaryBuf::AttachData(void* buffer, FX_STRSIZE size)\r
50 {\r
51     if (m_pBuffer) {\r
52         FX_Allocator_Free(m_pAllocator, m_pBuffer);\r
53     }\r
54     m_DataSize = size;\r
55     m_pBuffer = (FX_LPBYTE)buffer;\r
56     m_AllocSize = size;\r
57 }\r
58 void CFX_BinaryBuf::TakeOver(CFX_BinaryBuf& other)\r
59 {\r
60     AttachData(other.GetBuffer(), other.GetSize());\r
61     other.DetachBuffer();\r
62 }\r
63 void CFX_BinaryBuf::EstimateSize(FX_STRSIZE size, FX_STRSIZE step)\r
64 {\r
65     m_AllocStep = step;\r
66     if (m_AllocSize >= size) {\r
67         return;\r
68     }\r
69     ExpandBuf(size - m_DataSize);\r
70 }\r
71 void CFX_BinaryBuf::ExpandBuf(FX_STRSIZE add_size)\r
72 {\r
73     FX_STRSIZE new_size = add_size + m_DataSize;\r
74     if (m_AllocSize >= new_size) {\r
75         return;\r
76     }\r
77     int alloc_step;\r
78     if (m_AllocStep == 0) {\r
79         alloc_step = m_AllocSize / 4;\r
80         if (alloc_step < 128 ) {\r
81             alloc_step = 128;\r
82         }\r
83     } else {\r
84         alloc_step = m_AllocStep;\r
85     }\r
86     new_size = (new_size + alloc_step - 1) / alloc_step * alloc_step;\r
87     FX_LPBYTE pNewBuffer = m_pBuffer;\r
88     if (pNewBuffer) {\r
89         pNewBuffer = FX_Allocator_Realloc(m_pAllocator, FX_BYTE, m_pBuffer, new_size);\r
90     } else {\r
91         pNewBuffer = FX_Allocator_Alloc(m_pAllocator, FX_BYTE, new_size);\r
92     }\r
93     if (pNewBuffer) {\r
94         m_pBuffer = pNewBuffer;\r
95         m_AllocSize = new_size;\r
96     }\r
97 }\r
98 void CFX_BinaryBuf::CopyData(const void* pStr, FX_STRSIZE size)\r
99 {\r
100     if (size == 0) {\r
101         m_DataSize = 0;\r
102         return;\r
103     }\r
104     if (m_AllocSize < size) {\r
105         ExpandBuf(size - m_DataSize);\r
106     }\r
107     if (!m_pBuffer) {\r
108         return;\r
109     }\r
110     FXSYS_memcpy32(m_pBuffer, pStr, size);\r
111     m_DataSize = size;\r
112 }\r
113 void CFX_BinaryBuf::AppendBlock(const void* pBuf, FX_STRSIZE size)\r
114 {\r
115     ExpandBuf(size);\r
116     if (pBuf && m_pBuffer) {\r
117         FXSYS_memcpy32(m_pBuffer + m_DataSize, pBuf, size);\r
118     }\r
119     m_DataSize += size;\r
120 }\r
121 void CFX_BinaryBuf::InsertBlock(FX_STRSIZE pos, const void* pBuf, FX_STRSIZE size)\r
122 {\r
123     ExpandBuf(size);\r
124     if (!m_pBuffer) {\r
125         return;\r
126     }\r
127     FXSYS_memmove32(m_pBuffer + pos + size, m_pBuffer + pos, m_DataSize - pos);\r
128     if (pBuf) {\r
129         FXSYS_memcpy32(m_pBuffer + pos, pBuf, size);\r
130     }\r
131     m_DataSize += size;\r
132 }\r
133 void CFX_BinaryBuf::AppendFill(FX_BYTE byte, FX_STRSIZE count)\r
134 {\r
135     ExpandBuf(count);\r
136     if (!m_pBuffer) {\r
137         return;\r
138     }\r
139     FXSYS_memset8(m_pBuffer + m_DataSize, byte, count);\r
140     m_DataSize += count;\r
141 }\r
142 CFX_ByteStringC CFX_BinaryBuf::GetByteString() const\r
143 {\r
144     return CFX_ByteStringC(m_pBuffer, m_DataSize);\r
145 }\r
146 void CFX_BinaryBuf::GetByteStringL(CFX_ByteStringL &str) const\r
147 {\r
148     str.Set(CFX_ByteStringC(m_pBuffer, m_DataSize), m_pAllocator);\r
149 }\r
150 CFX_ByteTextBuf& CFX_ByteTextBuf::operator << (FX_BSTR lpsz)\r
151 {\r
152     AppendBlock((FX_LPCBYTE)lpsz, lpsz.GetLength());\r
153     return *this;\r
154 }\r
155 CFX_ByteTextBuf& CFX_ByteTextBuf::operator << (int i)\r
156 {\r
157     char buf[32];\r
158     FXSYS_itoa(i, buf, 10);\r
159     AppendBlock(buf, (FX_STRSIZE)FXSYS_strlen(buf));\r
160     return *this;\r
161 }\r
162 CFX_ByteTextBuf& CFX_ByteTextBuf::operator << (FX_DWORD i)\r
163 {\r
164     char buf[32];\r
165     FXSYS_itoa(i, buf, 10);\r
166     AppendBlock(buf, (FX_STRSIZE)FXSYS_strlen(buf));\r
167     return *this;\r
168 }\r
169 CFX_ByteTextBuf& CFX_ByteTextBuf::operator << (double f)\r
170 {\r
171     char buf[32];\r
172     FX_STRSIZE len = FX_ftoa((FX_FLOAT)f, buf);\r
173     AppendBlock(buf, len);\r
174     return *this;\r
175 }\r
176 CFX_ByteTextBuf& CFX_ByteTextBuf::operator << (const CFX_ByteTextBuf& buf)\r
177 {\r
178     AppendBlock(buf.m_pBuffer, buf.m_DataSize);\r
179     return *this;\r
180 }\r
181 void CFX_ByteTextBuf::operator =(const CFX_ByteStringC& str)\r
182 {\r
183     CopyData((FX_LPCBYTE)str, str.GetLength());\r
184 }\r
185 void CFX_WideTextBuf::AppendChar(FX_WCHAR ch)\r
186 {\r
187     if (m_AllocSize < m_DataSize + (FX_STRSIZE)sizeof(FX_WCHAR)) {\r
188         ExpandBuf(sizeof(FX_WCHAR));\r
189     }\r
190     ASSERT(m_pBuffer != NULL);\r
191     *(FX_WCHAR*)(m_pBuffer + m_DataSize) = ch;\r
192     m_DataSize += sizeof(FX_WCHAR);\r
193 }\r
194 CFX_WideTextBuf& CFX_WideTextBuf::operator << (FX_WSTR str)\r
195 {\r
196     AppendBlock(str.GetPtr(), str.GetLength() * sizeof(FX_WCHAR));\r
197     return *this;\r
198 }\r
199 CFX_WideTextBuf& CFX_WideTextBuf::operator << (const CFX_WideString &str)\r
200 {\r
201     AppendBlock((FX_LPCWSTR)str, str.GetLength() * sizeof(FX_WCHAR));\r
202     return *this;\r
203 }\r
204 CFX_WideTextBuf& CFX_WideTextBuf::operator << (int i)\r
205 {\r
206     char buf[32];\r
207     FXSYS_itoa(i, buf, 10);\r
208     FX_STRSIZE len = (FX_STRSIZE)FXSYS_strlen(buf);\r
209     if (m_AllocSize < m_DataSize + (FX_STRSIZE)(len * sizeof(FX_WCHAR))) {\r
210         ExpandBuf(len * sizeof(FX_WCHAR));\r
211     }\r
212     ASSERT(m_pBuffer != NULL);\r
213     FX_LPWSTR str = (FX_WCHAR*)(m_pBuffer + m_DataSize);\r
214     for (FX_STRSIZE j = 0; j < len; j ++) {\r
215         *str ++ = buf[j];\r
216     }\r
217     m_DataSize += len * sizeof(FX_WCHAR);\r
218     return *this;\r
219 }\r
220 CFX_WideTextBuf& CFX_WideTextBuf::operator << (double f)\r
221 {\r
222     char buf[32];\r
223     FX_STRSIZE len = FX_ftoa((FX_FLOAT)f, buf);\r
224     if (m_AllocSize < m_DataSize + (FX_STRSIZE)(len * sizeof(FX_WCHAR))) {\r
225         ExpandBuf(len * sizeof(FX_WCHAR));\r
226     }\r
227     ASSERT(m_pBuffer != NULL);\r
228     FX_LPWSTR str = (FX_WCHAR*)(m_pBuffer + m_DataSize);\r
229     for (FX_STRSIZE i = 0; i < len; i ++) {\r
230         *str ++ = buf[i];\r
231     }\r
232     m_DataSize += len * sizeof(FX_WCHAR);\r
233     return *this;\r
234 }\r
235 CFX_WideTextBuf& CFX_WideTextBuf::operator << (FX_LPCWSTR lpsz)\r
236 {\r
237     AppendBlock(lpsz, (FX_STRSIZE)FXSYS_wcslen(lpsz)*sizeof(FX_WCHAR));\r
238     return *this;\r
239 }\r
240 CFX_WideTextBuf& CFX_WideTextBuf::operator << (const CFX_WideTextBuf& buf)\r
241 {\r
242     AppendBlock(buf.m_pBuffer, buf.m_DataSize);\r
243     return *this;\r
244 }\r
245 void CFX_WideTextBuf::operator =(FX_WSTR str)\r
246 {\r
247     CopyData(str.GetPtr(), str.GetLength() * sizeof(FX_WCHAR));\r
248 }\r
249 CFX_WideStringC CFX_WideTextBuf::GetWideString() const\r
250 {\r
251     return CFX_WideStringC((FX_LPCWSTR)m_pBuffer, m_DataSize / sizeof(FX_WCHAR));\r
252 }\r
253 void CFX_WideTextBuf::GetWideStringL(CFX_WideStringL& wideText) const\r
254 {\r
255     wideText.Set(CFX_WideStringC((FX_LPCWSTR)m_pBuffer, m_DataSize / sizeof(FX_WCHAR)), m_pAllocator);\r
256 }\r
257 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (FX_BYTE i)\r
258 {\r
259     if (m_pStream) {\r
260         m_pStream->WriteBlock(&i, 1);\r
261     } else {\r
262         m_SavingBuf.AppendByte(i);\r
263     }\r
264     return *this;\r
265 }\r
266 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (int i)\r
267 {\r
268     if (m_pStream) {\r
269         m_pStream->WriteBlock(&i, sizeof(int));\r
270     } else {\r
271         m_SavingBuf.AppendBlock(&i, sizeof(int));\r
272     }\r
273     return *this;\r
274 }\r
275 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (FX_DWORD i)\r
276 {\r
277     if (m_pStream) {\r
278         m_pStream->WriteBlock(&i, sizeof(FX_DWORD));\r
279     } else {\r
280         m_SavingBuf.AppendBlock(&i, sizeof(FX_DWORD));\r
281     }\r
282     return *this;\r
283 }\r
284 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (FX_FLOAT f)\r
285 {\r
286     if (m_pStream) {\r
287         m_pStream->WriteBlock(&f, sizeof(FX_FLOAT));\r
288     } else {\r
289         m_SavingBuf.AppendBlock(&f, sizeof(FX_FLOAT));\r
290     }\r
291     return *this;\r
292 }\r
293 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (FX_BSTR bstr)\r
294 {\r
295     int len = bstr.GetLength();\r
296     if (m_pStream) {\r
297         m_pStream->WriteBlock(&len, sizeof(int));\r
298         m_pStream->WriteBlock(bstr, len);\r
299     } else {\r
300         m_SavingBuf.AppendBlock(&len, sizeof(int));\r
301         m_SavingBuf.AppendBlock(bstr, len);\r
302     }\r
303     return *this;\r
304 }\r
305 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (FX_LPCWSTR wstr)\r
306 {\r
307     FX_STRSIZE len = (FX_STRSIZE)FXSYS_wcslen(wstr);\r
308     if (m_pStream) {\r
309         m_pStream->WriteBlock(&len, sizeof(int));\r
310         m_pStream->WriteBlock(wstr, len);\r
311     } else {\r
312         m_SavingBuf.AppendBlock(&len, sizeof(int));\r
313         m_SavingBuf.AppendBlock(wstr, len);\r
314     }\r
315     return *this;\r
316 }\r
317 CFX_ArchiveSaver& CFX_ArchiveSaver::operator << (const CFX_WideString& wstr)\r
318 {\r
319     CFX_ByteString encoded = wstr.UTF16LE_Encode();\r
320     return operator << (encoded);\r
321 }\r
322 void CFX_ArchiveSaver::Write(const void* pData, FX_STRSIZE dwSize)\r
323 {\r
324     if (m_pStream) {\r
325         m_pStream->WriteBlock(pData, dwSize);\r
326     } else {\r
327         m_SavingBuf.AppendBlock(pData, dwSize);\r
328     }\r
329 }\r
330 CFX_ArchiveLoader::CFX_ArchiveLoader(FX_LPCBYTE pData, FX_DWORD dwSize)\r
331 {\r
332     m_pLoadingBuf = pData;\r
333     m_LoadingPos = 0;\r
334     m_LoadingSize = dwSize;\r
335 }\r
336 FX_BOOL CFX_ArchiveLoader::IsEOF()\r
337 {\r
338     return m_LoadingPos >= m_LoadingSize;\r
339 }\r
340 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (FX_BYTE& i)\r
341 {\r
342     if (m_LoadingPos >= m_LoadingSize) {\r
343         return *this;\r
344     }\r
345     i = m_pLoadingBuf[m_LoadingPos++];\r
346     return *this;\r
347 }\r
348 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (int& i)\r
349 {\r
350     Read(&i, sizeof(int));\r
351     return *this;\r
352 }\r
353 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (FX_DWORD& i)\r
354 {\r
355     Read(&i, sizeof(FX_DWORD));\r
356     return *this;\r
357 }\r
358 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (FX_FLOAT& i)\r
359 {\r
360     Read(&i, sizeof(FX_FLOAT));\r
361     return *this;\r
362 }\r
363 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (CFX_ByteString& str)\r
364 {\r
365     if (m_LoadingPos + 4 > m_LoadingSize) {\r
366         return *this;\r
367     }\r
368     int len;\r
369     operator >> (len);\r
370     str.Empty();\r
371     if (len <= 0 || m_LoadingPos + len > m_LoadingSize) {\r
372         return *this;\r
373     }\r
374     FX_LPSTR buffer = str.GetBuffer(len);\r
375     FXSYS_memcpy32(buffer, m_pLoadingBuf + m_LoadingPos, len);\r
376     str.ReleaseBuffer(len);\r
377     m_LoadingPos += len;\r
378     return *this;\r
379 }\r
380 CFX_ArchiveLoader& CFX_ArchiveLoader::operator >> (CFX_WideString& str)\r
381 {\r
382     CFX_ByteString encoded;\r
383     operator >> (encoded);\r
384     str = CFX_WideString::FromUTF16LE((const unsigned short*)(FX_LPCSTR)encoded, encoded.GetLength());\r
385     return *this;\r
386 }\r
387 FX_BOOL CFX_ArchiveLoader::Read(void* pBuf, FX_DWORD dwSize)\r
388 {\r
389     if (m_LoadingPos + dwSize > m_LoadingSize) {\r
390         return FALSE;\r
391     }\r
392     FXSYS_memcpy32(pBuf, m_pLoadingBuf + m_LoadingPos, dwSize);\r
393     m_LoadingPos += dwSize;\r
394     return TRUE;\r
395 }\r
396 void CFX_BitStream::Init(FX_LPCBYTE pData, FX_DWORD dwSize)\r
397 {\r
398     m_pData = pData;\r
399     m_BitSize = dwSize * 8;\r
400     m_BitPos = 0;\r
401 }\r
402 void CFX_BitStream::ByteAlign()\r
403 {\r
404     int mod = m_BitPos % 8;\r
405     if (mod == 0) {\r
406         return;\r
407     }\r
408     m_BitPos += 8 - mod;\r
409 }\r
410 FX_DWORD CFX_BitStream::GetBits(FX_DWORD nBits)\r
411 {\r
412     if (nBits > m_BitSize || m_BitPos + nBits > m_BitSize) {\r
413         return 0;\r
414     }\r
415     if (nBits == 1) {\r
416         int bit = (m_pData[m_BitPos / 8] & (1 << (7 - m_BitPos % 8))) ? 1 : 0;\r
417         m_BitPos ++;\r
418         return bit;\r
419     }\r
420     FX_DWORD byte_pos = m_BitPos / 8;\r
421     FX_DWORD bit_pos = m_BitPos % 8, bit_left = nBits;\r
422     FX_DWORD result = 0;\r
423     if (bit_pos) {\r
424         if (8 - bit_pos >= bit_left) {\r
425             result = (m_pData[byte_pos] & (0xff >> bit_pos)) >> (8 - bit_pos - bit_left);\r
426             m_BitPos += bit_left;\r
427             return result;\r
428         }\r
429         bit_left -= 8 - bit_pos;\r
430         result = (m_pData[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left;\r
431     }\r
432     while (bit_left >= 8) {\r
433         bit_left -= 8;\r
434         result |= m_pData[byte_pos++] << bit_left;\r
435     }\r
436     if (bit_left) {\r
437         result |= m_pData[byte_pos] >> (8 - bit_left);\r
438     }\r
439     m_BitPos += nBits;\r
440     return result;\r
441 }\r
442 IFX_BufferArchive::IFX_BufferArchive(FX_STRSIZE size, IFX_Allocator* pAllocator)\r
443     : m_pAllocator(pAllocator)\r
444     , m_BufSize(size)\r
445     , m_pBuffer(NULL)\r
446     , m_Length(0)\r
447 {\r
448 }\r
449 void IFX_BufferArchive::Clear()\r
450 {\r
451     m_Length = 0;\r
452     if (m_pBuffer) {\r
453         FX_Allocator_Free(m_pAllocator, m_pBuffer);\r
454         m_pBuffer = NULL;\r
455     }\r
456 }\r
457 FX_BOOL IFX_BufferArchive::Flush()\r
458 {\r
459     FX_BOOL bRet = DoWork(m_pBuffer, m_Length);\r
460     m_Length = 0;\r
461     return bRet;\r
462 }\r
463 FX_INT32 IFX_BufferArchive::AppendBlock(const void* pBuf, size_t size)\r
464 {\r
465     if (!pBuf || size < 1) {\r
466         return 0;\r
467     }\r
468     if (!m_pBuffer) {\r
469         m_pBuffer = FX_Allocator_Alloc(m_pAllocator, FX_BYTE, m_BufSize);\r
470         if (!m_pBuffer) {\r
471             return -1;\r
472         }\r
473     }\r
474     FX_LPBYTE buffer = (FX_LPBYTE)pBuf;\r
475     FX_STRSIZE temp_size = (FX_STRSIZE)size;\r
476     while (temp_size > 0) {\r
477         FX_STRSIZE buf_size = FX_MIN(m_BufSize - m_Length, (FX_STRSIZE)temp_size);\r
478         FXSYS_memcpy32(m_pBuffer + m_Length, buffer, buf_size);\r
479         m_Length += buf_size;\r
480         if (m_Length == m_BufSize) {\r
481             if (!Flush()) {\r
482                 return -1;\r
483             }\r
484         }\r
485         temp_size -= buf_size;\r
486         buffer += buf_size;\r
487     }\r
488     return (FX_INT32)size;\r
489 }\r
490 FX_INT32 IFX_BufferArchive::AppendByte(FX_BYTE byte)\r
491 {\r
492     return AppendBlock(&byte, 1);\r
493 }\r
494 FX_INT32 IFX_BufferArchive::AppendDWord(FX_DWORD i)\r
495 {\r
496     char buf[32];\r
497     FXSYS_itoa(i, buf, 10);\r
498     return AppendBlock(buf, (size_t)FXSYS_strlen(buf));\r
499 }\r
500 FX_INT32 IFX_BufferArchive::AppendString(FX_BSTR lpsz)\r
501 {\r
502     return AppendBlock((FX_LPCBYTE)lpsz, lpsz.GetLength());\r
503 }\r
504 CFX_FileBufferArchive::CFX_FileBufferArchive(FX_STRSIZE size, IFX_Allocator* pAllocator)\r
505     : IFX_BufferArchive(size, pAllocator)\r
506     , m_pFile(NULL)\r
507     , m_bTakeover(FALSE)\r
508 {\r
509 }\r
510 CFX_FileBufferArchive::~CFX_FileBufferArchive()\r
511 {\r
512     Clear();\r
513 }\r
514 void CFX_FileBufferArchive::Clear()\r
515 {\r
516     if (m_pFile && m_bTakeover) {\r
517         m_pFile->Release();\r
518     }\r
519     m_pFile = NULL;\r
520     m_bTakeover = FALSE;\r
521     IFX_BufferArchive::Clear();\r
522 }\r
523 FX_BOOL CFX_FileBufferArchive::AttachFile(IFX_StreamWrite *pFile, FX_BOOL bTakeover )\r
524 {\r
525     if (!pFile) {\r
526         return FALSE;\r
527     }\r
528     if (m_pFile && m_bTakeover) {\r
529         m_pFile->Release();\r
530     }\r
531     m_pFile = pFile;\r
532     m_bTakeover = bTakeover;\r
533     return TRUE;\r
534 }\r
535 FX_BOOL CFX_FileBufferArchive::AttachFile(FX_LPCWSTR filename)\r
536 {\r
537     if (!filename) {\r
538         return FALSE;\r
539     }\r
540     if (m_pFile && m_bTakeover) {\r
541         m_pFile->Release();\r
542     }\r
543     m_pFile = FX_CreateFileWrite(filename);\r
544     if (!m_pFile) {\r
545         return FALSE;\r
546     }\r
547     m_bTakeover = TRUE;\r
548     return TRUE;\r
549 }\r
550 FX_BOOL CFX_FileBufferArchive::AttachFile(FX_LPCSTR filename)\r
551 {\r
552     if (!filename) {\r
553         return FALSE;\r
554     }\r
555     if (m_pFile && m_bTakeover) {\r
556         m_pFile->Release();\r
557     }\r
558     m_pFile = FX_CreateFileWrite(filename);\r
559     if (!m_pFile) {\r
560         return FALSE;\r
561     }\r
562     m_bTakeover = TRUE;\r
563     return TRUE;\r
564 }\r
565 FX_BOOL CFX_FileBufferArchive::DoWork(const void* pBuf, size_t size)\r
566 {\r
567     if (!m_pFile) {\r
568         return FALSE;\r
569     }\r
570     if (!pBuf || size < 1) {\r
571         return TRUE;\r
572     }\r
573     return m_pFile->WriteBlock(pBuf, size);\r
574 }\r