text: // Copyright 2016 PDFium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
  
  #ifndef CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_
  #define CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_
  
  #include <stdint.h>
  
  #include <memory>
  #include <vector>
  
  #include "core/fpdfapi/parser/cpdf_stream.h"
  #include "core/fxcrt/fx_memory_wrappers.h"
  #include "core/fxcrt/fx_types.h"
  #include "core/fxcrt/retain_ptr.h"
  #include "core/fxcrt/string_pool_template.h"
  #include "core/fxcrt/unowned_ptr.h"
  #include "core/fxcrt/weak_ptr.h"
  
  class CPDF_Dictionary;
  class CPDF_IndirectObjectHolder;
  class CPDF_Object;
  class CPDF_ReadValidator;
  class CPDF_Stream;
  class IFX_SeekableReadStream;
  
  class CPDF_SyntaxParser {
   public:
    enum class ParseType { kStrict, kLoose };
  
    static std::unique_ptr<CPDF_SyntaxParser> CreateForTesting(
        const RetainPtr<IFX_SeekableReadStream>& pFileAccess,
        FX_FILESIZE HeaderOffset);
  
    explicit CPDF_SyntaxParser(
        const RetainPtr<IFX_SeekableReadStream>& pFileAccess);
    CPDF_SyntaxParser(const RetainPtr<CPDF_ReadValidator>& pValidator,
                      FX_FILESIZE HeaderOffset);
    ~CPDF_SyntaxParser();
  
    void SetReadBufferSize(uint32_t read_buffer_size) {
      m_ReadBufferSize = read_buffer_size;
    }
  
    FX_FILESIZE GetPos() const { return m_Pos; }
    void SetPos(FX_FILESIZE pos);
  
    RetainPtr<CPDF_Object> GetObjectBody(CPDF_IndirectObjectHolder* pObjList);
  
    RetainPtr<CPDF_Object> GetIndirectObject(CPDF_IndirectObjectHolder* pObjList,
                                             ParseType parse_type);
  
    ByteString GetKeyword();
    void ToNextLine();
    void ToNextWord();
    void RecordingToNextWord();
    bool BackwardsSearchToWord(ByteStringView word, FX_FILESIZE limit);
    FX_FILESIZE FindTag(ByteStringView tag);
    bool ReadBlock(uint8_t* pBuf, uint32_t size);
    bool GetCharAt(FX_FILESIZE pos, uint8_t& ch);
    ByteString GetNextWord(bool* bIsNumber);
    ByteString PeekNextWord(bool* bIsNumber);
  
    const RetainPtr<CPDF_ReadValidator>& GetValidator() const {
      return m_pFileAccess;
    }
    uint32_t GetDirectNum();
    bool GetNextChar(uint8_t& ch);
  
    // The document size may be smaller than the file size.
    // The syntax parser use position relative to document
    // offset (|m_HeaderOffset|).
    // The document size will be FileSize - "Header offset".
    // All offsets was readed from document, should not be great than document
    // size. Use it for checks instead of real file size.
    FX_FILESIZE GetDocumentSize() const;
  
    ByteString ReadString();
    ByteString ReadHexString();
  
    void SetTrailerEnds(std::vector<unsigned int>* trailer_ends) {
      m_TrailerEnds = trailer_ends;
    }
  
   private:
    friend class CPDF_DataAvail;
    friend class cpdf_syntax_parser_ReadHexString_Test;
  
    static constexpr int kParserMaxRecursionDepth = 64;
    static int s_CurrentRecursionDepth;
  
    bool ReadBlockAt(FX_FILESIZE read_pos);
    bool GetCharAtBackward(FX_FILESIZE pos, uint8_t* ch);
    void GetNextWordInternal(bool* bIsNumber);
    bool IsWholeWord(FX_FILESIZE startpos,
                     FX_FILESIZE limit,
                     ByteStringView tag,
                     bool checkKeyword);
  
    unsigned int ReadEOLMarkers(FX_FILESIZE pos);
    FX_FILESIZE FindWordPos(ByteStringView word);
    FX_FILESIZE FindStreamEndPos();
    RetainPtr<CPDF_Stream> ReadStream(RetainPtr<CPDF_Dictionary> pDict);
  
    bool IsPositionRead(FX_FILESIZE pos) const;
  
    RetainPtr<CPDF_Object> GetObjectBodyInternal(
        CPDF_IndirectObjectHolder* pObjList,
        ParseType parse_type);
  
    RetainPtr<CPDF_ReadValidator> m_pFileAccess;
    // The syntax parser use position relative to header offset.
    // The header contains at file start, and can follow after some stuff. We
    // ignore this stuff.
    const FX_FILESIZE m_HeaderOffset;
    const FX_FILESIZE m_FileLen;
    FX_FILESIZE m_Pos = 0;
    WeakPtr<ByteStringPool> m_pPool;
    std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_pFileBuf;
    FX_FILESIZE m_BufOffset = 0;
    uint32_t m_WordSize = 0;
    uint8_t m_WordBuffer[257];
    uint32_t m_ReadBufferSize = CPDF_Stream::kFileBufSize;
  
    // The syntax parser records traversed trailer end byte offsets here.
    UnownedPtr<std::vector<unsigned int>> m_TrailerEnds;
  };
  
  #endif  // CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_
  