Cleanup some numeric code.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_parser.cpp
index d486cfe..fa114f9 100644 (file)
@@ -9,9 +9,11 @@
 #include <vector>
 
 #include "../../../../third_party/base/nonstd_unique_ptr.h"
+#include "../../../../third_party/base/stl_util.h"
 #include "../../../include/fpdfapi/fpdf_module.h"
 #include "../../../include/fpdfapi/fpdf_page.h"
 #include "../../../include/fpdfapi/fpdf_parser.h"
+#include "../../../include/fxcrt/fx_ext.h"
 #include "../../../include/fxcrt/fx_safe_types.h"
 #include "../fpdf_page/pageint.h"
 
@@ -161,85 +163,83 @@ FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess,
   m_bXRefStream = FALSE;
   m_LastXRefOffset = 0;
   m_bOwnFileRead = bOwnFileRead;
+
   int32_t offset = GetHeaderOffset(pFileAccess);
   if (offset == -1) {
-    if (bOwnFileRead && pFileAccess) {
+    if (bOwnFileRead && pFileAccess)
       pFileAccess->Release();
-    }
     return PDFPARSE_ERROR_FORMAT;
   }
   m_Syntax.InitParser(pFileAccess, offset);
+
   uint8_t ch;
-  if (!m_Syntax.GetCharAt(5, ch)) {
+  if (!m_Syntax.GetCharAt(5, ch))
     return PDFPARSE_ERROR_FORMAT;
-  }
-  if (ch >= '0' && ch <= '9') {
+  if (std::isdigit(ch))
     m_FileVersion = (ch - '0') * 10;
-  }
-  if (!m_Syntax.GetCharAt(7, ch)) {
+
+  if (!m_Syntax.GetCharAt(7, ch))
     return PDFPARSE_ERROR_FORMAT;
-  }
-  if (ch >= '0' && ch <= '9') {
+  if (std::isdigit(ch))
     m_FileVersion += ch - '0';
-  }
-  if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9) {
+
+  if (m_Syntax.m_FileLen < m_Syntax.m_HeaderOffset + 9)
     return PDFPARSE_ERROR_FORMAT;
-  }
+
   m_Syntax.RestorePos(m_Syntax.m_FileLen - m_Syntax.m_HeaderOffset - 9);
-  if (!bReParse) {
+  if (!bReParse)
     m_pDocument = new CPDF_Document(this);
-  }
+
   FX_BOOL bXRefRebuilt = FALSE;
   if (m_Syntax.SearchWord(FX_BSTRC("startxref"), TRUE, FALSE, 4096)) {
     FX_FILESIZE startxref_offset = m_Syntax.SavePos();
     void* pResult = FXSYS_bsearch(&startxref_offset, m_SortedOffset.GetData(),
                                   m_SortedOffset.GetSize(), sizeof(FX_FILESIZE),
                                   CompareFileSize);
-    if (pResult == NULL) {
+    if (!pResult)
       m_SortedOffset.Add(startxref_offset);
-    }
+
     m_Syntax.GetKeyword();
     FX_BOOL bNumber;
     CFX_ByteString xrefpos_str = m_Syntax.GetNextWord(bNumber);
-    if (!bNumber) {
+    if (!bNumber)
       return PDFPARSE_ERROR_FORMAT;
-    }
+
     m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str);
     if (!LoadAllCrossRefV4(m_LastXRefOffset) &&
         !LoadAllCrossRefV5(m_LastXRefOffset)) {
-      if (!RebuildCrossRef()) {
+      if (!RebuildCrossRef())
         return PDFPARSE_ERROR_FORMAT;
-      }
+
       bXRefRebuilt = TRUE;
       m_LastXRefOffset = 0;
     }
   } else {
-    if (!RebuildCrossRef()) {
+    if (!RebuildCrossRef())
       return PDFPARSE_ERROR_FORMAT;
-    }
+
     bXRefRebuilt = TRUE;
   }
   FX_DWORD dwRet = SetEncryptHandler();
-  if (dwRet != PDFPARSE_ERROR_SUCCESS) {
+  if (dwRet != PDFPARSE_ERROR_SUCCESS)
     return dwRet;
-  }
+
   m_pDocument->LoadDoc();
-  if (m_pDocument->GetRoot() == NULL || m_pDocument->GetPageCount() == 0) {
-    if (bXRefRebuilt) {
+  if (!m_pDocument->GetRoot() || m_pDocument->GetPageCount() == 0) {
+    if (bXRefRebuilt)
       return PDFPARSE_ERROR_FORMAT;
-    }
+
     ReleaseEncryptHandler();
-    if (!RebuildCrossRef()) {
+    if (!RebuildCrossRef())
       return PDFPARSE_ERROR_FORMAT;
-    }
+
     dwRet = SetEncryptHandler();
-    if (dwRet != PDFPARSE_ERROR_SUCCESS) {
+    if (dwRet != PDFPARSE_ERROR_SUCCESS)
       return dwRet;
-    }
+
     m_pDocument->LoadDoc();
-    if (m_pDocument->GetRoot() == NULL) {
+    if (!m_pDocument->GetRoot())
       return PDFPARSE_ERROR_FORMAT;
-    }
   }
   FXSYS_qsort(m_SortedOffset.GetData(), m_SortedOffset.GetSize(),
               sizeof(FX_FILESIZE), CompareFileSize);
@@ -248,13 +248,12 @@ FX_DWORD CPDF_Parser::StartParse(IFX_FileRead* pFileAccess,
     ReleaseEncryptHandler();
     RebuildCrossRef();
     RootObjNum = GetRootObjNum();
-    if (RootObjNum == 0) {
+    if (RootObjNum == 0)
       return PDFPARSE_ERROR_FORMAT;
-    }
+
     dwRet = SetEncryptHandler();
-    if (dwRet != PDFPARSE_ERROR_SUCCESS) {
+    if (dwRet != PDFPARSE_ERROR_SUCCESS)
       return dwRet;
-    }
   }
   if (m_pSecurityHandler && !m_pSecurityHandler->IsMetadataEncrypted()) {
     CPDF_Reference* pMetadata =
@@ -436,7 +435,8 @@ FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
   FX_FILESIZE SavedPos = m_Syntax.SavePos();
   const int32_t recordsize = 20;
   std::vector<char> buf(1024 * recordsize + 1);
-  buf[1024 * recordsize] = '\0';
+  char* pBuf = pdfium::vector_as_array(&buf);
+  pBuf[1024 * recordsize] = '\0';
   int32_t nBlocks = count / 1024 + 1;
   for (int32_t block = 0; block < nBlocks; block++) {
     int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
@@ -444,12 +444,12 @@ FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
     if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_Syntax.m_FileLen) {
       return FALSE;
     }
-    if (!m_Syntax.ReadBlock((uint8_t*)buf.data(), dwReadSize)) {
+    if (!m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(pBuf), dwReadSize)) {
       return FALSE;
     }
     for (int32_t i = 0; i < block_size; i++) {
       FX_DWORD objnum = start_objnum + block * 1024 + i;
-      char* pEntry = buf.data() + i * recordsize;
+      char* pEntry = pBuf + i * recordsize;
       if (pEntry[17] == 'f') {
         m_CrossRef.SetAtGrow(objnum, 0);
         m_V5Type.SetAtGrow(objnum, 0);
@@ -457,9 +457,8 @@ FX_BOOL CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos,
         int32_t offset = FXSYS_atoi(pEntry);
         if (offset == 0) {
           for (int32_t c = 0; c < 10; c++) {
-            if (pEntry[c] < '0' || pEntry[c] > '9') {
+            if (!std::isdigit(pEntry[c]))
               return FALSE;
-            }
           }
         }
         m_CrossRef.SetAtGrow(objnum, offset);
@@ -528,15 +527,17 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
     m_dwXrefStartObjNum = start_objnum;
     if (!bSkip) {
       std::vector<char> buf(1024 * recordsize + 1);
-      buf[1024 * recordsize] = '\0';
+      char* pBuf = pdfium::vector_as_array(&buf);
+      pBuf[1024 * recordsize] = '\0';
       int32_t nBlocks = count / 1024 + 1;
       FX_BOOL bFirstBlock = TRUE;
       for (int32_t block = 0; block < nBlocks; block++) {
         int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024;
-        m_Syntax.ReadBlock((uint8_t*)buf.data(), block_size * recordsize);
+        m_Syntax.ReadBlock(reinterpret_cast<uint8_t*>(pBuf),
+                           block_size * recordsize);
         for (int32_t i = 0; i < block_size; i++) {
           FX_DWORD objnum = start_objnum + block * 1024 + i;
-          char* pEntry = buf.data() + i * recordsize;
+          char* pEntry = pBuf + i * recordsize;
           if (pEntry[17] == 'f') {
             if (bFirstItem) {
               objnum = 0;
@@ -556,9 +557,8 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos,
             FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry);
             if (offset == 0) {
               for (int32_t c = 0; c < 10; c++) {
-                if (pEntry[c] < '0' || pEntry[c] > '9') {
+                if (!std::isdigit(pEntry[c]))
                   return false;
-                }
               }
             }
             m_CrossRef.SetAtGrow(objnum, offset);
@@ -626,37 +626,41 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
       uint8_t byte = buffer[i];
       switch (status) {
         case 0:
-          if (PDF_CharType[byte] == 'W') {
+          if (PDFCharIsWhitespace(byte))
             status = 1;
-          }
-          if (byte <= '9' && byte >= '0') {
+
+          if (std::isdigit(byte)) {
             --i;
             status = 1;
           }
+
           if (byte == '%') {
             inside_index = 0;
             status = 9;
           }
+
           if (byte == '(') {
             status = 10;
             depth = 1;
           }
+
           if (byte == '<') {
             inside_index = 1;
             status = 11;
           }
-          if (byte == '\\') {
+
+          if (byte == '\\')
             status = 13;
-          }
+
           if (byte == 't') {
             status = 7;
             inside_index = 1;
           }
           break;
         case 1:
-          if (PDF_CharType[byte] == 'W') {
+          if (PDFCharIsWhitespace(byte)) {
             break;
-          } else if (byte <= '9' && byte >= '0') {
+          } else if (std::isdigit(byte)) {
             start_pos = pos + i;
             status = 2;
             objnum = byte - '0';
@@ -672,10 +676,10 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           }
           break;
         case 2:
-          if (byte <= '9' && byte >= '0') {
+          if (std::isdigit(byte)) {
             objnum = objnum * 10 + byte - '0';
             break;
-          } else if (PDF_CharType[byte] == 'W') {
+          } else if (PDFCharIsWhitespace(byte)) {
             status = 3;
           } else {
             --i;
@@ -684,11 +688,11 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           }
           break;
         case 3:
-          if (byte <= '9' && byte >= '0') {
+          if (std::isdigit(byte)) {
             start_pos1 = pos + i;
             status = 4;
             gennum = byte - '0';
-          } else if (PDF_CharType[byte] == 'W') {
+          } else if (PDFCharIsWhitespace(byte)) {
             break;
           } else if (byte == 't') {
             status = 7;
@@ -699,10 +703,10 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           }
           break;
         case 4:
-          if (byte <= '9' && byte >= '0') {
+          if (std::isdigit(byte)) {
             gennum = gennum * 10 + byte - '0';
             break;
-          } else if (PDF_CharType[byte] == 'W') {
+          } else if (PDFCharIsWhitespace(byte)) {
             status = 5;
           } else {
             --i;
@@ -713,9 +717,9 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           if (byte == 'o') {
             status = 6;
             inside_index = 1;
-          } else if (PDF_CharType[byte] == 'W') {
+          } else if (PDFCharIsWhitespace(byte)) {
             break;
-          } else if (byte <= '9' && byte >= '0') {
+          } else if (std::isdigit(byte)) {
             objnum = gennum;
             gennum = byte - '0';
             start_pos = start_pos1;
@@ -748,7 +752,7 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
               }
               break;
             case 3:
-              if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
+              if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) {
                 if (objnum > 0x1000000) {
                   status = 0;
                   break;
@@ -822,7 +826,7 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           break;
         case 7:
           if (inside_index == 7) {
-            if (PDF_CharType[byte] == 'W' || PDF_CharType[byte] == 'D') {
+            if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) {
               last_trailer = pos + i - 7;
               m_Syntax.RestorePos(pos + i - m_Syntax.m_HeaderOffset);
               CPDF_Object* pObj = m_Syntax.GetObject(m_pDocument, 0, 0, 0);
@@ -845,9 +849,15 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
                         FX_POSITION pos = pTrailer->GetStartPos();
                         while (pos) {
                           CFX_ByteString key;
-                          CPDF_Object* pObj =
+                          CPDF_Object* pElement =
                               pTrailer->GetNextElement(pos, key);
-                          m_pTrailer->SetAt(key, pObj->Clone(), m_pDocument);
+                          FX_DWORD dwObjNum = pElement->GetObjNum();
+                          if (dwObjNum) {
+                            m_pTrailer->SetAtReference(key, m_pDocument,
+                                                       dwObjNum);
+                          } else {
+                            m_pTrailer->SetAt(key, pElement->Clone());
+                          }
                         }
                         pObj->Release();
                       } else {
@@ -927,13 +937,13 @@ FX_BOOL CPDF_Parser::RebuildCrossRef() {
           status = 0;
           break;
         case 13:
-          if (PDF_CharType[byte] == 'D' || PDF_CharType[byte] == 'W') {
+          if (PDFCharIsDelimiter(byte) || PDFCharIsWhitespace(byte)) {
             --i;
             status = 0;
           }
           break;
         case 14:
-          if (PDF_CharType[byte] == 'W') {
+          if (PDFCharIsWhitespace(byte)) {
             status = 0;
           } else if (byte == '%' || byte == '(' || byte == '<' ||
                      byte == '\\') {
@@ -1636,15 +1646,13 @@ FX_DWORD CPDF_Parser::LoadLinearizedMainXRefTable() {
   uint8_t ch = 0;
   FX_DWORD dwCount = 0;
   m_Syntax.GetNextChar(ch);
-  int32_t type = PDF_CharType[ch];
-  while (type == 'W') {
+  while (PDFCharIsWhitespace(ch)) {
     ++dwCount;
     if (m_Syntax.m_FileLen >=
         (FX_FILESIZE)(m_Syntax.SavePos() + m_Syntax.m_HeaderOffset)) {
       break;
     }
     m_Syntax.GetNextChar(ch);
-    type = PDF_CharType[ch];
   }
   m_LastXRefOffset += dwCount;
   FX_POSITION pos = m_ObjectStreamMap.GetStartPosition();
@@ -1761,77 +1769,66 @@ void CPDF_SyntaxParser::GetNextWord() {
   if (!GetNextChar(ch)) {
     return;
   }
-  uint8_t type = PDF_CharType[ch];
   while (1) {
-    while (type == 'W') {
-      if (!GetNextChar(ch)) {
+    while (PDFCharIsWhitespace(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      type = PDF_CharType[ch];
     }
-    if (ch != '%') {
+    if (ch != '%')
       break;
-    }
+
     while (1) {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      if (ch == '\r' || ch == '\n') {
+      if (PDFCharIsLineEnding(ch))
         break;
-      }
     }
-    type = PDF_CharType[ch];
   }
-  if (type == 'D') {
+
+  if (PDFCharIsDelimiter(ch)) {
     m_bIsNumber = FALSE;
     m_WordBuffer[m_WordSize++] = ch;
     if (ch == '/') {
       while (1) {
-        if (!GetNextChar(ch)) {
+        if (!GetNextChar(ch))
           return;
-        }
-        type = PDF_CharType[ch];
-        if (type != 'R' && type != 'N') {
+
+        if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
           m_Pos--;
           return;
         }
-        if (m_WordSize < MAX_WORD_BUFFER) {
+
+        if (m_WordSize < MAX_WORD_BUFFER)
           m_WordBuffer[m_WordSize++] = ch;
-        }
       }
     } else if (ch == '<') {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      if (ch == '<') {
+      if (ch == '<')
         m_WordBuffer[m_WordSize++] = ch;
-      } else {
+      else
         m_Pos--;
-      }
     } else if (ch == '>') {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      if (ch == '>') {
+      if (ch == '>')
         m_WordBuffer[m_WordSize++] = ch;
-      } else {
+      else
         m_Pos--;
-      }
     }
     return;
   }
+
   while (1) {
-    if (m_WordSize < MAX_WORD_BUFFER) {
+    if (m_WordSize < MAX_WORD_BUFFER)
       m_WordBuffer[m_WordSize++] = ch;
-    }
-    if (type != 'N') {
+
+    if (!PDFCharIsNumeric(ch))
       m_bIsNumber = FALSE;
-    }
-    if (!GetNextChar(ch)) {
+    if (!GetNextChar(ch))
       return;
-    }
-    type = PDF_CharType[ch];
-    if (type == 'D' || type == 'W') {
+
+    if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
       m_Pos--;
       break;
     }
@@ -1925,48 +1922,33 @@ CFX_ByteString CPDF_SyntaxParser::ReadString() {
 }
 CFX_ByteString CPDF_SyntaxParser::ReadHexString() {
   uint8_t ch;
-  if (!GetNextChar(ch)) {
+  if (!GetNextChar(ch))
     return CFX_ByteString();
-  }
+
   CFX_BinaryBuf buf;
   FX_BOOL bFirst = TRUE;
   uint8_t code = 0;
   while (1) {
-    if (ch == '>') {
+    if (ch == '>')
       break;
-    }
-    if (ch >= '0' && ch <= '9') {
-      if (bFirst) {
-        code = (ch - '0') * 16;
-      } else {
-        code += ch - '0';
-        buf.AppendByte((uint8_t)code);
-      }
-      bFirst = !bFirst;
-    } else if (ch >= 'A' && ch <= 'F') {
-      if (bFirst) {
-        code = (ch - 'A' + 10) * 16;
-      } else {
-        code += ch - 'A' + 10;
-        buf.AppendByte((uint8_t)code);
-      }
-      bFirst = !bFirst;
-    } else if (ch >= 'a' && ch <= 'f') {
+
+    if (std::isxdigit(ch)) {
+      int val = HexCharToDigit(ch);
       if (bFirst) {
-        code = (ch - 'a' + 10) * 16;
+        code = val * 16;
       } else {
-        code += ch - 'a' + 10;
+        code += val;
         buf.AppendByte((uint8_t)code);
       }
       bFirst = !bFirst;
     }
-    if (!GetNextChar(ch)) {
+
+    if (!GetNextChar(ch))
       break;
-    }
   }
-  if (!bFirst) {
+  if (!bFirst)
     buf.AppendByte((uint8_t)code);
-  }
+
   return buf.GetByteString();
 }
 void CPDF_SyntaxParser::ToNextLine() {
@@ -1986,33 +1968,29 @@ void CPDF_SyntaxParser::ToNextLine() {
 }
 void CPDF_SyntaxParser::ToNextWord() {
   uint8_t ch;
-  if (!GetNextChar(ch)) {
+  if (!GetNextChar(ch))
     return;
-  }
-  uint8_t type = PDF_CharType[ch];
+
   while (1) {
-    while (type == 'W') {
+    while (PDFCharIsWhitespace(ch)) {
       m_dwWordPos = m_Pos;
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      type = PDF_CharType[ch];
     }
-    if (ch != '%') {
+
+    if (ch != '%')
       break;
-    }
+
     while (1) {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return;
-      }
-      if (ch == '\r' || ch == '\n') {
+      if (PDFCharIsLineEnding(ch))
         break;
-      }
     }
-    type = PDF_CharType[ch];
   }
   m_Pos--;
 }
+
 CFX_ByteString CPDF_SyntaxParser::GetNextWord(FX_BOOL& bIsNumber) {
   GetNextWord();
   bIsNumber = m_bIsNumber;
@@ -2036,9 +2014,8 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
   FX_BOOL bIsNumber;
   CFX_ByteString word = GetNextWord(bIsNumber);
   if (word.GetLength() == 0) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_INVALID;
-    }
     return NULL;
   }
   if (bIsNumber) {
@@ -2048,34 +2025,29 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
       CFX_ByteString nextword2 = GetNextWord(bIsNumber);
       if (nextword2 == FX_BSTRC("R")) {
         FX_DWORD objnum = FXSYS_atoi(word);
-        if (bTypeOnly) {
+        if (bTypeOnly)
           return (CPDF_Object*)PDFOBJ_REFERENCE;
-        }
         return new CPDF_Reference(pObjList, objnum);
       }
     }
     m_Pos = SavedPos;
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NUMBER;
-    }
     return CPDF_Number::Create(word);
   }
   if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_BOOLEAN;
-    }
     return CPDF_Boolean::Create(word == FX_BSTRC("true"));
   }
   if (word == FX_BSTRC("null")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NULL;
-    }
     return CPDF_Null::Create();
   }
   if (word == FX_BSTRC("(")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_STRING;
-    }
     CFX_ByteString str = ReadString();
     if (m_pCryptoHandler && bDecrypt) {
       m_pCryptoHandler->Decrypt(objnum, gennum, str);
@@ -2083,9 +2055,8 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
     return CPDF_String::Create(str, FALSE);
   }
   if (word == FX_BSTRC("<")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_STRING;
-    }
     CFX_ByteString str = ReadHexString();
     if (m_pCryptoHandler && bDecrypt) {
       m_pCryptoHandler->Decrypt(objnum, gennum, str);
@@ -2093,9 +2064,8 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
     return CPDF_String::Create(str, TRUE);
   }
   if (word == FX_BSTRC("[")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_ARRAY;
-    }
     CPDF_Array* pArray = CPDF_Array::Create();
     while (CPDF_Object* pObj = GetObject(pObjList, objnum, gennum))
       pArray->Add(pObj);
@@ -2103,9 +2073,8 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
     return pArray;
   }
   if (word[0] == '/') {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NAME;
-    }
     return CPDF_Name::Create(
         PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
   }
@@ -2139,6 +2108,13 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
 
       ++nKeys;
       key = PDF_NameDecode(key);
+      if (key.IsEmpty())
+        continue;
+
+      CFX_ByteStringC keyNoSlash(key.c_str() + 1, key.GetLength() - 1);
+      if (keyNoSlash.IsEmpty())
+        continue;
+
       if (key == FX_BSTRC("/Contents"))
         dwSignValuePos = m_Pos;
 
@@ -2146,14 +2122,12 @@ CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
       if (!pObj)
         continue;
 
-      if (key.GetLength() >= 1) {
-        if (nKeys < 32) {
-          pDict->SetAt(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1),
-                       pObj);
-        } else {
-          pDict->AddValue(CFX_ByteStringC(key.c_str() + 1, key.GetLength() - 1),
-                          pObj);
-        }
+      // TODO(thestig): Remove this conditional once CPDF_Dictionary has a
+      // better underlying map implementation.
+      if (nKeys < 32) {
+        pDict->SetAt(keyNoSlash, pObj);
+      } else {
+        pDict->AddValue(keyNoSlash, pObj);
       }
     }
 
@@ -2204,10 +2178,9 @@ CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
   FX_BOOL bIsNumber;
   CFX_ByteString word = GetNextWord(bIsNumber);
   if (word.GetLength() == 0) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_INVALID;
-    }
-    return NULL;
+    return nullptr;
   }
   if (bIsNumber) {
     FX_FILESIZE SavedPos = m_Pos;
@@ -2215,55 +2188,46 @@ CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
     if (bIsNumber) {
       CFX_ByteString nextword2 = GetNextWord(bIsNumber);
       if (nextword2 == FX_BSTRC("R")) {
-        if (bTypeOnly) {
+        if (bTypeOnly)
           return (CPDF_Object*)PDFOBJ_REFERENCE;
-        }
         FX_DWORD objnum = FXSYS_atoi(word);
         return new CPDF_Reference(pObjList, objnum);
       }
     }
     m_Pos = SavedPos;
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NUMBER;
-    }
     return CPDF_Number::Create(word);
   }
   if (word == FX_BSTRC("true") || word == FX_BSTRC("false")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_BOOLEAN;
-    }
     return CPDF_Boolean::Create(word == FX_BSTRC("true"));
   }
   if (word == FX_BSTRC("null")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NULL;
-    }
     return CPDF_Null::Create();
   }
   if (word == FX_BSTRC("(")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_STRING;
-    }
     CFX_ByteString str = ReadString();
-    if (m_pCryptoHandler) {
+    if (m_pCryptoHandler)
       m_pCryptoHandler->Decrypt(objnum, gennum, str);
-    }
     return CPDF_String::Create(str, FALSE);
   }
   if (word == FX_BSTRC("<")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_STRING;
-    }
     CFX_ByteString str = ReadHexString();
-    if (m_pCryptoHandler) {
+    if (m_pCryptoHandler)
       m_pCryptoHandler->Decrypt(objnum, gennum, str);
-    }
     return CPDF_String::Create(str, TRUE);
   }
   if (word == FX_BSTRC("[")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_ARRAY;
-    }
     nonstd::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>> pArray(
         CPDF_Array::Create());
     while (CPDF_Object* pObj = GetObject(pObjList, objnum, gennum))
@@ -2271,19 +2235,17 @@ CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
     return m_WordBuffer[0] == ']' ? pArray.release() : nullptr;
   }
   if (word[0] == '/') {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_NAME;
-    }
     return CPDF_Name::Create(
         PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
   }
   if (word == FX_BSTRC("<<")) {
-    if (bTypeOnly) {
+    if (bTypeOnly)
       return (CPDF_Object*)PDFOBJ_DICTIONARY;
-    }
-    if (pContext) {
+    if (pContext)
       pContext->m_DictStart = SavedPos;
-    }
+
     nonstd::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>> pDict(
         CPDF_Dictionary::Create());
     while (1) {
@@ -2339,7 +2301,6 @@ CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
   }
   if (bTypeOnly)
     return (CPDF_Object*)PDFOBJ_INVALID;
-
   return nullptr;
 }
 
@@ -2518,21 +2479,21 @@ FX_BOOL CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos,
                                        const uint8_t* tag,
                                        FX_DWORD taglen,
                                        FX_BOOL checkKeyword) {
-  uint8_t type = PDF_CharType[tag[0]];
-  FX_BOOL bCheckLeft = type != 'D' && type != 'W';
-  type = PDF_CharType[tag[taglen - 1]];
-  FX_BOOL bCheckRight = type != 'D' && type != 'W';
+  bool bCheckLeft = !PDFCharIsDelimiter(tag[0]) && !PDFCharIsWhitespace(tag[0]);
+  bool bCheckRight = !PDFCharIsDelimiter(tag[taglen - 1]) &&
+                     !PDFCharIsWhitespace(tag[taglen - 1]);
   uint8_t ch;
   if (bCheckRight && startpos + (int32_t)taglen <= limit &&
       GetCharAt(startpos + (int32_t)taglen, ch)) {
-    uint8_t type = PDF_CharType[ch];
-    if (type == 'N' || type == 'R' || (checkKeyword && type == 'D')) {
+    if (PDFCharIsNumeric(ch) || PDFCharIsOther(ch) ||
+        (checkKeyword && PDFCharIsDelimiter(ch))) {
       return FALSE;
     }
   }
+
   if (bCheckLeft && startpos > 0 && GetCharAt(startpos - 1, ch)) {
-    uint8_t type = PDF_CharType[ch];
-    if (type == 'N' || type == 'R' || (checkKeyword && type == 'D')) {
+    if (PDFCharIsNumeric(ch) || PDFCharIsOther(ch) ||
+        (checkKeyword && PDFCharIsDelimiter(ch))) {
       return FALSE;
     }
   }
@@ -2976,7 +2937,7 @@ CPDF_DataAvail::~CPDF_DataAvail() {
   int32_t i = 0;
   int32_t iSize = m_arrayAcroforms.GetSize();
   for (i = 0; i < iSize; ++i) {
-    ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
+    static_cast<CPDF_Object*>(m_arrayAcroforms.GetAt(i))->Release();
   }
 }
 void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) {
@@ -3024,10 +2985,10 @@ FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
   CFX_PtrArray new_obj_array;
   int32_t i = 0;
   for (i = 0; i < obj_array.GetSize(); i++) {
-    CPDF_Object* pObj = (CPDF_Object*)obj_array[i];
-    if (!pObj) {
+    CPDF_Object* pObj = static_cast<CPDF_Object*>(obj_array[i]);
+    if (!pObj)
       continue;
-    }
+
     int32_t type = pObj->GetType();
     switch (type) {
       case PDFOBJ_ARRAY: {
@@ -3095,7 +3056,7 @@ FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
   if (count > 0) {
     int32_t iSize = new_obj_array.GetSize();
     for (i = 0; i < iSize; ++i) {
-      CPDF_Object* pObj = (CPDF_Object*)new_obj_array[i];
+      CPDF_Object* pObj = static_cast<CPDF_Object*>(new_obj_array[i]);
       if (CPDF_Reference* pRef = pObj->AsReference()) {
         FX_DWORD dwNum = pRef->GetRefObjNum();
         if (!m_objnum_array.Find(dwNum))
@@ -3141,7 +3102,7 @@ FX_BOOL CPDF_DataAvail::CheckAcroFormSubObject(IFX_DownloadHints* pHints) {
   if (bRet) {
     int32_t iSize = m_arrayAcroforms.GetSize();
     for (int32_t i = 0; i < iSize; ++i) {
-      ((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
+      static_cast<CPDF_Object*>(m_arrayAcroforms.GetAt(i))->Release();
     }
     m_arrayAcroforms.RemoveAll();
   } else {
@@ -3454,14 +3415,14 @@ FX_BOOL CPDF_DataAvail::CheckPage(IFX_DownloadHints* pHints) {
   }
   FX_DWORD iPages = m_PagesArray.GetSize();
   for (FX_DWORD i = 0; i < iPages; i++) {
-    CPDF_Object* pPages = (CPDF_Object*)m_PagesArray.GetAt(i);
-    if (!pPages) {
+    CPDF_Object* pPages = static_cast<CPDF_Object*>(m_PagesArray.GetAt(i));
+    if (!pPages)
       continue;
-    }
+
     if (!GetPageKids(m_pCurrentParser, pPages)) {
       pPages->Release();
       while (++i < iPages) {
-        pPages = (CPDF_Object*)m_PagesArray.GetAt(i);
+        pPages = static_cast<CPDF_Object*>(m_PagesArray.GetAt(i));
         pPages->Release();
       }
       m_PagesArray.RemoveAll();
@@ -3776,84 +3737,79 @@ inline void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) {
 FX_BOOL CPDF_DataAvail::GetNextToken(CFX_ByteString& token) {
   m_WordSize = 0;
   uint8_t ch;
-  if (!GetNextChar(ch)) {
+  if (!GetNextChar(ch))
     return FALSE;
-  }
-  uint8_t type = PDF_CharType[ch];
+
   while (1) {
-    while (type == 'W') {
-      if (!GetNextChar(ch)) {
+    while (PDFCharIsWhitespace(ch)) {
+      if (!GetNextChar(ch))
         return FALSE;
-      }
-      type = PDF_CharType[ch];
     }
-    if (ch != '%') {
+
+    if (ch != '%')
       break;
-    }
+
     while (1) {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return FALSE;
-      }
-      if (ch == '\r' || ch == '\n') {
+      if (PDFCharIsLineEnding(ch))
         break;
-      }
     }
-    type = PDF_CharType[ch];
   }
-  if (type == 'D') {
+
+  if (PDFCharIsDelimiter(ch)) {
     m_WordBuffer[m_WordSize++] = ch;
     if (ch == '/') {
       while (1) {
-        if (!GetNextChar(ch)) {
+        if (!GetNextChar(ch))
           return FALSE;
-        }
-        type = PDF_CharType[ch];
-        if (type != 'R' && type != 'N') {
+
+        if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
           m_Pos--;
           CFX_ByteString ret(m_WordBuffer, m_WordSize);
           token = ret;
           return TRUE;
         }
-        if (m_WordSize < MAX_WORD_BUFFER) {
+
+        if (m_WordSize < MAX_WORD_BUFFER)
           m_WordBuffer[m_WordSize++] = ch;
-        }
       }
     } else if (ch == '<') {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return FALSE;
-      }
-      if (ch == '<') {
+
+      if (ch == '<')
         m_WordBuffer[m_WordSize++] = ch;
-      } else {
+      else
         m_Pos--;
-      }
     } else if (ch == '>') {
-      if (!GetNextChar(ch)) {
+      if (!GetNextChar(ch))
         return FALSE;
-      }
-      if (ch == '>') {
+
+      if (ch == '>')
         m_WordBuffer[m_WordSize++] = ch;
-      } else {
+      else
         m_Pos--;
-      }
     }
+
     CFX_ByteString ret(m_WordBuffer, m_WordSize);
     token = ret;
     return TRUE;
   }
+
   while (1) {
-    if (m_WordSize < MAX_WORD_BUFFER) {
+    if (m_WordSize < MAX_WORD_BUFFER)
       m_WordBuffer[m_WordSize++] = ch;
-    }
-    if (!GetNextChar(ch)) {
+
+    if (!GetNextChar(ch))
       return FALSE;
-    }
-    type = PDF_CharType[ch];
-    if (type == 'D' || type == 'W') {
+
+    if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
       m_Pos--;
       break;
     }
   }
+
   CFX_ByteString ret(m_WordBuffer, m_WordSize);
   token = ret;
   return TRUE;