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 23 class 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 59 class 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 83 class 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 113 class 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 134 class 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 145 class 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 167 class 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 179 class 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 200 template <class TYPE> 201 class 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 320 template <class DataType, int FixedSize> 321 class 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 337 class 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 363 class IFX_Pause { 364 public: 365 virtual ~IFX_Pause() {} 366 virtual bool NeedToPauseNow() = 0; 367 }; 368 369 template <typename T> 370 class 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 382 template <size_t unit> 383 class 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 }; 483 template <typename T1, typename T2> 484 class 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 }; 501 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_FILESIZE)>, 502 FX_FILESIZE> 503 CFX_FileSizeListArray; 504 505 class 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 }; 516 class 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 557 uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits); 558 559 #endif // CORE_FXCRT_FX_BASIC_H_ 560