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