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