fx_basic.h revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
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#ifndef CORE_FXCRT_FX_BASIC_H_
8#define CORE_FXCRT_FX_BASIC_H_
9
10#include <algorithm>
11#include <memory>
12
13#include "core/fxcrt/cfx_retain_ptr.h"
14#include "core/fxcrt/fx_memory.h"
15#include "core/fxcrt/fx_stream.h"
16#include "core/fxcrt/fx_string.h"
17#include "core/fxcrt/fx_system.h"
18
19#ifdef PDF_ENABLE_XFA
20#define FX_IsOdd(a) ((a)&1)
21#endif  // PDF_ENABLE_XFA
22
23class CFX_BinaryBuf {
24 public:
25  CFX_BinaryBuf();
26  explicit CFX_BinaryBuf(FX_STRSIZE size);
27  ~CFX_BinaryBuf();
28
29  uint8_t* GetBuffer() const { return m_pBuffer.get(); }
30  FX_STRSIZE GetSize() const { return m_DataSize; }
31
32  void Clear();
33  void EstimateSize(FX_STRSIZE size, FX_STRSIZE alloc_step = 0);
34  void AppendBlock(const void* pBuf, FX_STRSIZE size);
35  void AppendString(const CFX_ByteString& str) {
36    AppendBlock(str.c_str(), str.GetLength());
37  }
38
39  void AppendByte(uint8_t byte) {
40    ExpandBuf(1);
41    m_pBuffer.get()[m_DataSize++] = byte;
42  }
43
44  void InsertBlock(FX_STRSIZE pos, const void* pBuf, FX_STRSIZE size);
45  void Delete(int start_index, int count);
46
47  // Releases ownership of |m_pBuffer| and returns it.
48  std::unique_ptr<uint8_t, FxFreeDeleter> DetachBuffer();
49
50 protected:
51  void ExpandBuf(FX_STRSIZE size);
52
53  FX_STRSIZE m_AllocStep;
54  FX_STRSIZE m_AllocSize;
55  FX_STRSIZE m_DataSize;
56  std::unique_ptr<uint8_t, FxFreeDeleter> m_pBuffer;
57};
58
59class CFX_ByteTextBuf : public CFX_BinaryBuf {
60 public:
61  FX_STRSIZE GetLength() const { return m_DataSize; }
62  CFX_ByteString MakeString() const {
63    return CFX_ByteString(m_pBuffer.get(), m_DataSize);
64  }
65  CFX_ByteStringC AsStringC() const {
66    return CFX_ByteStringC(m_pBuffer.get(), m_DataSize);
67  }
68
69  void AppendChar(int ch) { AppendByte(static_cast<uint8_t>(ch)); }
70  CFX_ByteTextBuf& operator<<(int i);
71  CFX_ByteTextBuf& operator<<(uint32_t i);
72  CFX_ByteTextBuf& operator<<(double f);
73  CFX_ByteTextBuf& operator<<(const FX_CHAR* pStr) {
74    return *this << CFX_ByteStringC(pStr);
75  }
76  CFX_ByteTextBuf& operator<<(const CFX_ByteString& str) {
77    return *this << str.AsStringC();
78  }
79  CFX_ByteTextBuf& operator<<(const CFX_ByteStringC& lpsz);
80  CFX_ByteTextBuf& operator<<(const CFX_ByteTextBuf& buf);
81};
82
83class CFX_WideTextBuf : public CFX_BinaryBuf {
84 public:
85  void AppendChar(FX_WCHAR wch);
86  FX_STRSIZE GetLength() const { return m_DataSize / sizeof(FX_WCHAR); }
87  FX_WCHAR* GetBuffer() const {
88    return reinterpret_cast<FX_WCHAR*>(m_pBuffer.get());
89  }
90
91  CFX_WideStringC AsStringC() const {
92    return CFX_WideStringC(reinterpret_cast<const FX_WCHAR*>(m_pBuffer.get()),
93                           m_DataSize / sizeof(FX_WCHAR));
94  }
95  CFX_WideString MakeString() const {
96    return CFX_WideString(reinterpret_cast<const FX_WCHAR*>(m_pBuffer.get()),
97                          m_DataSize / sizeof(FX_WCHAR));
98  }
99
100  void Delete(int start_index, int count) {
101    CFX_BinaryBuf::Delete(start_index * sizeof(FX_WCHAR),
102                          count * sizeof(FX_WCHAR));
103  }
104
105  CFX_WideTextBuf& operator<<(int i);
106  CFX_WideTextBuf& operator<<(double f);
107  CFX_WideTextBuf& operator<<(const FX_WCHAR* lpsz);
108  CFX_WideTextBuf& operator<<(const CFX_WideStringC& str);
109  CFX_WideTextBuf& operator<<(const CFX_WideString& str);
110  CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf);
111};
112
113class CFX_FileBufferArchive {
114 public:
115  CFX_FileBufferArchive();
116  ~CFX_FileBufferArchive();
117
118  void Clear();
119  bool Flush();
120  int32_t AppendBlock(const void* pBuf, size_t size);
121  int32_t AppendByte(uint8_t byte);
122  int32_t AppendDWord(uint32_t i);
123  int32_t AppendString(const CFX_ByteStringC& lpsz);
124  void AttachFile(const CFX_RetainPtr<IFX_WriteStream>& pFile);
125
126 private:
127  static const size_t kBufSize = 32768;
128
129  size_t m_Length;
130  std::unique_ptr<uint8_t, FxFreeDeleter> m_pBuffer;
131  CFX_RetainPtr<IFX_WriteStream> m_pFile;
132};
133
134class CFX_CharMap {
135 public:
136  static CFX_ByteString GetByteString(uint16_t codepage,
137                                      const CFX_WideStringC& wstr);
138
139  static CFX_WideString GetWideString(uint16_t codepage,
140                                      const CFX_ByteStringC& bstr);
141
142  CFX_CharMap() = delete;
143};
144
145class CFX_UTF8Decoder {
146 public:
147  CFX_UTF8Decoder() { m_PendingBytes = 0; }
148
149  void Clear();
150
151  void Input(uint8_t byte);
152
153  void AppendChar(uint32_t ch);
154
155  void ClearStatus() { m_PendingBytes = 0; }
156
157  CFX_WideStringC GetResult() const { return m_Buffer.AsStringC(); }
158
159 protected:
160  int m_PendingBytes;
161
162  uint32_t m_PendingChar;
163
164  CFX_WideTextBuf m_Buffer;
165};
166
167class CFX_UTF8Encoder {
168 public:
169  CFX_UTF8Encoder() {}
170
171  void Input(FX_WCHAR unicode);
172  void AppendStr(const CFX_ByteStringC& str) { m_Buffer << str; }
173  CFX_ByteStringC GetResult() const { return m_Buffer.AsStringC(); }
174
175 protected:
176  CFX_ByteTextBuf m_Buffer;
177};
178
179class CFX_BasicArray {
180 protected:
181  explicit CFX_BasicArray(int unit_size);
182  CFX_BasicArray(const CFX_BasicArray&) = delete;
183  ~CFX_BasicArray();
184
185  bool SetSize(int nNewSize);
186  bool Append(const CFX_BasicArray& src);
187  bool Copy(const CFX_BasicArray& src);
188  uint8_t* InsertSpaceAt(int nIndex, int nCount);
189  bool RemoveAt(int nIndex, int nCount);
190  bool InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray);
191  const void* GetDataPtr(int index) const;
192
193 protected:
194  uint8_t* m_pData;
195  int m_nSize;
196  int m_nMaxSize;
197  int m_nUnitSize;
198};
199
200template <class TYPE>
201class CFX_ArrayTemplate : public CFX_BasicArray {
202 public:
203  CFX_ArrayTemplate() : CFX_BasicArray(sizeof(TYPE)) {}
204
205  int GetSize() const { return m_nSize; }
206
207  int GetUpperBound() const { return m_nSize - 1; }
208
209  bool SetSize(int nNewSize) { return CFX_BasicArray::SetSize(nNewSize); }
210
211  void RemoveAll() { SetSize(0); }
212
213  const TYPE GetAt(int nIndex) const {
214    if (nIndex < 0 || nIndex >= m_nSize) {
215      PDFIUM_IMMEDIATE_CRASH();
216    }
217    return ((const TYPE*)m_pData)[nIndex];
218  }
219
220  bool SetAt(int nIndex, TYPE newElement) {
221    if (nIndex < 0 || nIndex >= m_nSize) {
222      return false;
223    }
224    ((TYPE*)m_pData)[nIndex] = newElement;
225    return true;
226  }
227
228  TYPE& ElementAt(int nIndex) {
229    if (nIndex < 0 || nIndex >= m_nSize) {
230      PDFIUM_IMMEDIATE_CRASH();
231    }
232    return ((TYPE*)m_pData)[nIndex];
233  }
234
235  const TYPE* GetData() const { return (const TYPE*)m_pData; }
236
237  TYPE* GetData() { return (TYPE*)m_pData; }
238
239  bool SetAtGrow(int nIndex, TYPE newElement) {
240    if (nIndex < 0)
241      return false;
242
243    if (nIndex >= m_nSize && !SetSize(nIndex + 1))
244      return false;
245
246    ((TYPE*)m_pData)[nIndex] = newElement;
247    return true;
248  }
249
250  bool Add(TYPE newElement) {
251    if (m_nSize < m_nMaxSize) {
252      m_nSize++;
253    } else if (!SetSize(m_nSize + 1)) {
254      return false;
255    }
256    ((TYPE*)m_pData)[m_nSize - 1] = newElement;
257    return true;
258  }
259
260  bool Append(const CFX_ArrayTemplate& src) {
261    return CFX_BasicArray::Append(src);
262  }
263
264  bool Copy(const CFX_ArrayTemplate& src) { return CFX_BasicArray::Copy(src); }
265
266  TYPE* GetDataPtr(int index) {
267    return (TYPE*)CFX_BasicArray::GetDataPtr(index);
268  }
269
270  TYPE* AddSpace() { return (TYPE*)CFX_BasicArray::InsertSpaceAt(m_nSize, 1); }
271
272  TYPE* InsertSpaceAt(int nIndex, int nCount) {
273    return (TYPE*)CFX_BasicArray::InsertSpaceAt(nIndex, nCount);
274  }
275
276  const TYPE operator[](int nIndex) const {
277    if (nIndex < 0 || nIndex >= m_nSize) {
278      *(volatile char*)0 = '\0';
279    }
280    return ((const TYPE*)m_pData)[nIndex];
281  }
282
283  TYPE& operator[](int nIndex) {
284    if (nIndex < 0 || nIndex >= m_nSize) {
285      *(volatile char*)0 = '\0';
286    }
287    return ((TYPE*)m_pData)[nIndex];
288  }
289
290  bool InsertAt(int nIndex, TYPE newElement, int nCount = 1) {
291    if (!InsertSpaceAt(nIndex, nCount)) {
292      return false;
293    }
294    while (nCount--) {
295      ((TYPE*)m_pData)[nIndex++] = newElement;
296    }
297    return true;
298  }
299
300  bool RemoveAt(int nIndex, int nCount = 1) {
301    return CFX_BasicArray::RemoveAt(nIndex, nCount);
302  }
303
304  bool InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray) {
305    return CFX_BasicArray::InsertAt(nStartIndex, pNewArray);
306  }
307
308  int Find(TYPE data, int iStart = 0) const {
309    if (iStart < 0) {
310      return -1;
311    }
312    for (; iStart < (int)m_nSize; iStart++)
313      if (((TYPE*)m_pData)[iStart] == data) {
314        return iStart;
315      }
316    return -1;
317  }
318};
319
320template <class DataType, int FixedSize>
321class CFX_FixedBufGrow {
322 public:
323  explicit CFX_FixedBufGrow(int data_size) {
324    if (data_size > FixedSize) {
325      m_pGrowData.reset(FX_Alloc(DataType, data_size));
326      return;
327    }
328    FXSYS_memset(m_FixedData, 0, sizeof(DataType) * FixedSize);
329  }
330  operator DataType*() { return m_pGrowData ? m_pGrowData.get() : m_FixedData; }
331
332 private:
333  DataType m_FixedData[FixedSize];
334  std::unique_ptr<DataType, FxFreeDeleter> m_pGrowData;
335};
336
337class CFX_BitStream {
338 public:
339  void Init(const uint8_t* pData, uint32_t dwSize);
340
341  uint32_t GetBits(uint32_t nBits);
342
343  void ByteAlign();
344
345  bool IsEOF() { return m_BitPos >= m_BitSize; }
346
347  void SkipBits(uint32_t nBits) { m_BitPos += nBits; }
348
349  void Rewind() { m_BitPos = 0; }
350
351  uint32_t GetPos() const { return m_BitPos; }
352
353  uint32_t BitsRemaining() const {
354    return m_BitSize >= m_BitPos ? m_BitSize - m_BitPos : 0;
355  }
356
357 protected:
358  uint32_t m_BitPos;
359  uint32_t m_BitSize;
360  const uint8_t* m_pData;
361};
362
363class IFX_Pause {
364 public:
365  virtual ~IFX_Pause() {}
366  virtual bool NeedToPauseNow() = 0;
367};
368
369template <typename T>
370class CFX_AutoRestorer {
371 public:
372  explicit CFX_AutoRestorer(T* location)
373      : m_Location(location), m_OldValue(*location) {}
374  ~CFX_AutoRestorer() { *m_Location = m_OldValue; }
375
376 private:
377  T* const m_Location;
378  const T m_OldValue;
379};
380
381#define FX_DATALIST_LENGTH 1024
382template <size_t unit>
383class CFX_SortListArray {
384 protected:
385  struct DataList {
386    int32_t start;
387
388    int32_t count;
389    uint8_t* data;
390  };
391
392 public:
393  CFX_SortListArray() : m_CurList(0) {}
394
395  ~CFX_SortListArray() { Clear(); }
396
397  void Clear() {
398    for (int32_t i = m_DataLists.GetUpperBound(); i >= 0; i--) {
399      DataList list = m_DataLists.ElementAt(i);
400      FX_Free(list.data);
401    }
402    m_DataLists.RemoveAll();
403    m_CurList = 0;
404  }
405
406  void Append(int32_t nStart, int32_t nCount) {
407    if (nStart < 0) {
408      return;
409    }
410    while (nCount > 0) {
411      int32_t temp_count = std::min(nCount, FX_DATALIST_LENGTH);
412      DataList list;
413      list.data = FX_Alloc2D(uint8_t, temp_count, unit);
414      list.start = nStart;
415      list.count = temp_count;
416      Append(list);
417      nCount -= temp_count;
418      nStart += temp_count;
419    }
420  }
421
422  uint8_t* GetAt(int32_t nIndex) {
423    if (nIndex < 0) {
424      return nullptr;
425    }
426    if (m_CurList < 0 || m_CurList >= m_DataLists.GetSize()) {
427      return nullptr;
428    }
429    DataList* pCurList = m_DataLists.GetDataPtr(m_CurList);
430    if (!pCurList || nIndex < pCurList->start ||
431        nIndex >= pCurList->start + pCurList->count) {
432      pCurList = nullptr;
433      int32_t iStart = 0;
434      int32_t iEnd = m_DataLists.GetUpperBound();
435      int32_t iMid = 0;
436      while (iStart <= iEnd) {
437        iMid = (iStart + iEnd) / 2;
438        DataList* list = m_DataLists.GetDataPtr(iMid);
439        if (nIndex < list->start) {
440          iEnd = iMid - 1;
441        } else if (nIndex >= list->start + list->count) {
442          iStart = iMid + 1;
443        } else {
444          pCurList = list;
445          m_CurList = iMid;
446          break;
447        }
448      }
449    }
450    return pCurList ? pCurList->data + (nIndex - pCurList->start) * unit
451                    : nullptr;
452  }
453
454 protected:
455  void Append(const DataList& list) {
456    int32_t iStart = 0;
457    int32_t iEnd = m_DataLists.GetUpperBound();
458    int32_t iFind = 0;
459    while (iStart <= iEnd) {
460      int32_t iMid = (iStart + iEnd) / 2;
461      DataList* cur_list = m_DataLists.GetDataPtr(iMid);
462      if (list.start < cur_list->start + cur_list->count) {
463        iEnd = iMid - 1;
464      } else {
465        if (iMid == iEnd) {
466          iFind = iMid + 1;
467          break;
468        }
469        DataList* next_list = m_DataLists.GetDataPtr(iMid + 1);
470        if (list.start < next_list->start) {
471          iFind = iMid + 1;
472          break;
473        } else {
474          iStart = iMid + 1;
475        }
476      }
477    }
478    m_DataLists.InsertAt(iFind, list);
479  }
480  int32_t m_CurList;
481  CFX_ArrayTemplate<DataList> m_DataLists;
482};
483template <typename T1, typename T2>
484class CFX_ListArrayTemplate {
485 public:
486  void Clear() { m_Data.Clear(); }
487
488  void Add(int32_t nStart, int32_t nCount) { m_Data.Append(nStart, nCount); }
489
490  T2& operator[](int32_t nIndex) {
491    uint8_t* data = m_Data.GetAt(nIndex);
492    ASSERT(data);
493    return (T2&)(*(volatile T2*)data);
494  }
495
496  T2* GetPtrAt(int32_t nIndex) { return (T2*)m_Data.GetAt(nIndex); }
497
498 protected:
499  T1 m_Data;
500};
501typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_FILESIZE)>,
502                              FX_FILESIZE>
503    CFX_FileSizeListArray;
504
505class CFX_Vector_3by1 {
506 public:
507  CFX_Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {}
508
509  CFX_Vector_3by1(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1)
510      : a(a1), b(b1), c(c1) {}
511
512  FX_FLOAT a;
513  FX_FLOAT b;
514  FX_FLOAT c;
515};
516class CFX_Matrix_3by3 {
517 public:
518  CFX_Matrix_3by3()
519      : a(0.0f),
520        b(0.0f),
521        c(0.0f),
522        d(0.0f),
523        e(0.0f),
524        f(0.0f),
525        g(0.0f),
526        h(0.0f),
527        i(0.0f) {}
528
529  CFX_Matrix_3by3(FX_FLOAT a1,
530                  FX_FLOAT b1,
531                  FX_FLOAT c1,
532                  FX_FLOAT d1,
533                  FX_FLOAT e1,
534                  FX_FLOAT f1,
535                  FX_FLOAT g1,
536                  FX_FLOAT h1,
537                  FX_FLOAT i1)
538      : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {}
539
540  CFX_Matrix_3by3 Inverse();
541
542  CFX_Matrix_3by3 Multiply(const CFX_Matrix_3by3& m);
543
544  CFX_Vector_3by1 TransformVector(const CFX_Vector_3by1& v);
545
546  FX_FLOAT a;
547  FX_FLOAT b;
548  FX_FLOAT c;
549  FX_FLOAT d;
550  FX_FLOAT e;
551  FX_FLOAT f;
552  FX_FLOAT g;
553  FX_FLOAT h;
554  FX_FLOAT i;
555};
556
557uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits);
558
559#endif  // CORE_FXCRT_FX_BASIC_H_
560