Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_object_walker.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "core/fpdfapi/parser/cpdf_object_walker.h"
6
7#include <utility>
8
9#include "core/fpdfapi/parser/cpdf_array.h"
10#include "core/fpdfapi/parser/cpdf_dictionary.h"
11#include "core/fpdfapi/parser/cpdf_stream.h"
12#include "third_party/base/check.h"
13
14namespace {
15
16class StreamIterator final : public CPDF_ObjectWalker::SubobjectIterator {
17 public:
18 explicit StreamIterator(RetainPtr<const CPDF_Stream> stream)
19 : SubobjectIterator(std::move(stream)) {}
20
21 ~StreamIterator() override = default;
22
23 bool IsFinished() const override { return IsStarted() && is_finished_; }
24
25 RetainPtr<const CPDF_Object> IncrementImpl() override {
26 DCHECK(IsStarted());
27 DCHECK(!IsFinished());
28 is_finished_ = true;
29 return object()->GetDict();
30 }
31
32 void Start() override {}
33
34 private:
35 bool is_finished_ = false;
36};
37
38class DictionaryIterator final : public CPDF_ObjectWalker::SubobjectIterator {
39 public:
40 explicit DictionaryIterator(RetainPtr<const CPDF_Dictionary> dictionary)
41 : SubobjectIterator(dictionary), locker_(dictionary) {}
42
43 ~DictionaryIterator() override = default;
44
45 bool IsFinished() const override {
46 return IsStarted() && dict_iterator_ == locker_.end();
47 }
48
49 RetainPtr<const CPDF_Object> IncrementImpl() override {
50 DCHECK(IsStarted());
51 DCHECK(!IsFinished());
52 RetainPtr<const CPDF_Object> result = dict_iterator_->second;
53 dict_key_ = dict_iterator_->first;
54 ++dict_iterator_;
55 return result;
56 }
57
58 void Start() override {
59 DCHECK(!IsStarted());
60 dict_iterator_ = locker_.begin();
61 }
62
63 ByteString dict_key() const { return dict_key_; }
64
65 private:
66 CPDF_Dictionary::const_iterator dict_iterator_;
68 ByteString dict_key_;
69};
70
71class ArrayIterator final : public CPDF_ObjectWalker::SubobjectIterator {
72 public:
73 explicit ArrayIterator(RetainPtr<const CPDF_Array> array)
74 : SubobjectIterator(array), locker_(array) {}
75
76 ~ArrayIterator() override = default;
77
78 bool IsFinished() const override {
79 return IsStarted() && arr_iterator_ == locker_.end();
80 }
81
82 RetainPtr<const CPDF_Object> IncrementImpl() override {
83 DCHECK(IsStarted());
84 DCHECK(!IsFinished());
85 RetainPtr<const CPDF_Object> result = *arr_iterator_;
86 ++arr_iterator_;
87 return result;
88 }
89
90 void Start() override { arr_iterator_ = locker_.begin(); }
91
92 public:
93 CPDF_Array::const_iterator arr_iterator_;
94 CPDF_ArrayLocker locker_;
95};
96
97} // namespace
98
100
102 if (!IsStarted()) {
103 Start();
104 is_started_ = true;
105 }
106 while (!IsFinished()) {
107 RetainPtr<const CPDF_Object> result = IncrementImpl();
108 if (result)
109 return result;
110 }
111 return nullptr;
112}
113
115 RetainPtr<const CPDF_Object> object)
116 : object_(std::move(object)) {
117 DCHECK(object_);
118}
119
120// static
121std::unique_ptr<CPDF_ObjectWalker::SubobjectIterator>
122CPDF_ObjectWalker::MakeIterator(RetainPtr<const CPDF_Object> object) {
123 if (object->IsStream())
124 return std::make_unique<StreamIterator>(ToStream(object));
125 if (object->IsDictionary())
126 return std::make_unique<DictionaryIterator>(ToDictionary(object));
127 if (object->IsArray())
128 return std::make_unique<ArrayIterator>(ToArray(object));
129 return nullptr;
130}
131
134
136
138 while (!stack_.empty() || next_object_) {
139 if (next_object_) {
140 auto new_iterator = MakeIterator(next_object_);
141 if (new_iterator) {
142 // Schedule walk within composite objects.
143 stack_.push(std::move(new_iterator));
144 }
145 return std::move(next_object_); // next_object_ is NULL after move.
146 }
147
148 SubobjectIterator* it = stack_.top().get();
149 if (it->IsFinished()) {
150 stack_.pop();
151 } else {
152 next_object_ = it->Increment();
153 parent_object_.Reset(it->object());
154 dict_key_ = parent_object_->IsDictionary()
155 ? static_cast<DictionaryIterator*>(it)->dict_key()
156 : ByteString();
157 current_depth_ = stack_.size();
158 }
159 }
160 dict_key_ = ByteString();
161 current_depth_ = 0;
162 return nullptr;
163}
164
166 if (stack_.empty() || stack_.top()->IsStarted())
167 return;
168 stack_.pop();
169}
170
171CPDF_NonConstObjectWalker::CPDF_NonConstObjectWalker(
173 : CPDF_ObjectWalker(std::move(root)) {}
174
175RetainPtr<CPDF_Object> CPDF_NonConstObjectWalker::GetNext() {
176 return pdfium::WrapRetain(
177 const_cast<CPDF_Object*>(CPDF_ObjectWalker::GetNext().Get()));
178}
RetainPtr< CPDF_Object > GetNext()
CPDF_NonConstObjectWalker(RetainPtr< CPDF_Object > root)
virtual bool IsFinished() const =0
const CPDF_Object * object() const
SubobjectIterator(RetainPtr< const CPDF_Object > object)
RetainPtr< const CPDF_Object > Increment()
CPDF_ObjectWalker(RetainPtr< const CPDF_Object > root)
RetainPtr< const CPDF_Object > GetNext()