/src/poppler/poppler/Object.h
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // Object.h |
4 | | // |
5 | | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | //======================================================================== |
10 | | // |
11 | | // Modified under the Poppler project - http://poppler.freedesktop.org |
12 | | // |
13 | | // All changes made under the Poppler project to this file are licensed |
14 | | // under GPL version 2 or later |
15 | | // |
16 | | // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org> |
17 | | // Copyright (C) 2008 Kees Cook <kees@outflux.net> |
18 | | // Copyright (C) 2008, 2010, 2017-2021, 2023, 2024 Albert Astals Cid <aacid@kde.org> |
19 | | // Copyright (C) 2009 Jakub Wilk <jwilk@jwilk.net> |
20 | | // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it> |
21 | | // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de> |
22 | | // Copyright (C) 2013, 2017, 2018 Adrian Johnson <ajohnson@redneon.com> |
23 | | // Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com> |
24 | | // Copyright (C) 2016, 2020 Jakub Alba <jakubalba@gmail.com> |
25 | | // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich |
26 | | // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> |
27 | | // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden |
28 | | // Copyright (C) 2023 Oliver Sander <oliver.sander@tu-dresden.de> |
29 | | // Copyright (C) 2024, 2025 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk> |
30 | | // |
31 | | // To see a description of the changes please see the Changelog file that |
32 | | // came with your tarball or type make ChangeLog if you are building from git |
33 | | // |
34 | | //======================================================================== |
35 | | |
36 | | #ifndef OBJECT_H |
37 | | #define OBJECT_H |
38 | | |
39 | | #include <cassert> |
40 | | #include <set> |
41 | | #include <cstdio> |
42 | | #include <cstring> |
43 | | #include <climits> |
44 | | #include "goo/gmem.h" |
45 | | #include "goo/GooString.h" |
46 | | #include "goo/GooLikely.h" |
47 | | #include "Error.h" |
48 | | #include "poppler_private_export.h" |
49 | | |
50 | | #define OBJECT_TYPE_CHECK(wanted_type) \ |
51 | 15.0G | if (unlikely(type != (wanted_type))) { \ |
52 | 0 | ::error(errInternal, 0, \ |
53 | 0 | "Call to Object where the object was type {0:d}, " \ |
54 | 0 | "not the expected type {1:d}", \ |
55 | 0 | type, wanted_type); \ |
56 | 0 | abort(); \ |
57 | 0 | } |
58 | | |
59 | | #define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2) \ |
60 | 0 | if (unlikely(type != (wanted_type1)) && unlikely(type != (wanted_type2))) { \ |
61 | 0 | ::error(errInternal, 0, \ |
62 | 0 | "Call to Object where the object was type {0:d}, " \ |
63 | 0 | "not the expected type {1:d} or {2:d}", \ |
64 | 0 | type, wanted_type1, wanted_type2); \ |
65 | 0 | abort(); \ |
66 | 0 | } |
67 | | |
68 | | #define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \ |
69 | 328M | if (unlikely(type != (wanted_type1)) && unlikely(type != (wanted_type2)) && unlikely(type != (wanted_type3))) { \ |
70 | 0 | ::error(errInternal, 0, \ |
71 | 0 | "Call to Object where the object was type {0:d}, " \ |
72 | 0 | "not the expected type {1:d}, {2:d} or {3:d}", \ |
73 | 0 | type, wanted_type1, wanted_type2, wanted_type3); \ |
74 | 0 | abort(); \ |
75 | 0 | } |
76 | | |
77 | | #define CHECK_NOT_DEAD \ |
78 | 17.1G | if (unlikely(type == objDead)) { \ |
79 | 0 | ::error(errInternal, 0, "Call to dead object"); \ |
80 | 0 | abort(); \ |
81 | 0 | } |
82 | | |
83 | | class XRef; |
84 | | class Array; |
85 | | class Dict; |
86 | | class Stream; |
87 | | |
88 | | //------------------------------------------------------------------------ |
89 | | // Ref |
90 | | //------------------------------------------------------------------------ |
91 | | |
92 | | struct Ref |
93 | | { |
94 | | int num; // object number |
95 | | int gen; // generation number |
96 | | |
97 | 22.8M | static constexpr Ref INVALID() { return { -1, -1 }; }; |
98 | | }; |
99 | | |
100 | | inline bool operator==(const Ref lhs, const Ref rhs) noexcept |
101 | 45.7M | { |
102 | 45.7M | return lhs.num == rhs.num && lhs.gen == rhs.gen; |
103 | 45.7M | } |
104 | | |
105 | | inline bool operator!=(const Ref lhs, const Ref rhs) noexcept |
106 | 2.56M | { |
107 | 2.56M | return lhs.num != rhs.num || lhs.gen != rhs.gen; |
108 | 2.56M | } |
109 | | |
110 | | inline bool operator<(const Ref lhs, const Ref rhs) noexcept |
111 | 150k | { |
112 | 150k | if (lhs.num != rhs.num) { |
113 | 150k | return lhs.num < rhs.num; |
114 | 150k | } |
115 | 650 | return lhs.gen < rhs.gen; |
116 | 150k | } |
117 | | |
118 | | struct RefRecursionChecker |
119 | | { |
120 | 453k | RefRecursionChecker() = default; |
121 | | |
122 | | RefRecursionChecker(const RefRecursionChecker &) = delete; |
123 | | RefRecursionChecker &operator=(const RefRecursionChecker &) = delete; |
124 | | |
125 | | bool insert(Ref ref) |
126 | 14.8M | { |
127 | 14.8M | if (ref == Ref::INVALID()) { |
128 | 977k | return true; |
129 | 977k | } |
130 | | |
131 | | // insert returns std::pair<iterator,bool> |
132 | | // where the bool is whether the insert succeeded |
133 | 13.8M | return alreadySeenRefs.insert(ref.num).second; |
134 | 14.8M | } |
135 | | |
136 | 13.4M | void remove(Ref ref) { alreadySeenRefs.erase(ref.num); } |
137 | | |
138 | | private: |
139 | | std::set<int> alreadySeenRefs; |
140 | | }; |
141 | | |
142 | | struct RefRecursionCheckerRemover |
143 | | { |
144 | | // Removes ref from c when this object is removed |
145 | 13.4M | RefRecursionCheckerRemover(RefRecursionChecker &c, Ref r) : checker(c), ref(r) { } |
146 | 13.4M | ~RefRecursionCheckerRemover() { checker.remove(ref); } |
147 | | |
148 | | RefRecursionCheckerRemover(const RefRecursionCheckerRemover &) = delete; |
149 | | RefRecursionCheckerRemover &operator=(const RefRecursionCheckerRemover &) = delete; |
150 | | |
151 | | private: |
152 | | RefRecursionChecker &checker; |
153 | | Ref ref; |
154 | | }; |
155 | | |
156 | | namespace std { |
157 | | |
158 | | template<> |
159 | | struct hash<Ref> |
160 | | { |
161 | | using argument_type = Ref; |
162 | | using result_type = size_t; |
163 | | |
164 | 652k | result_type operator()(const argument_type ref) const noexcept { return std::hash<int> {}(ref.num) ^ (std::hash<int> {}(ref.gen) << 1); } |
165 | | }; |
166 | | |
167 | | } |
168 | | |
169 | | //------------------------------------------------------------------------ |
170 | | // object types |
171 | | //------------------------------------------------------------------------ |
172 | | |
173 | | enum ObjType |
174 | | { |
175 | | // simple objects |
176 | | objBool, // boolean |
177 | | objInt, // integer |
178 | | objReal, // real |
179 | | objString, // string |
180 | | objName, // name |
181 | | objNull, // null |
182 | | |
183 | | // complex objects |
184 | | objArray, // array |
185 | | objDict, // dictionary |
186 | | objStream, // stream |
187 | | objRef, // indirect reference |
188 | | |
189 | | // special objects |
190 | | objCmd, // command name |
191 | | objError, // error return from Lexer |
192 | | objEOF, // end of file return from Lexer |
193 | | objNone, // uninitialized object |
194 | | |
195 | | // poppler-only objects |
196 | | objInt64, // integer with at least 64-bits |
197 | | objHexString, // hex string |
198 | | objDead // and object after shallowCopy |
199 | | }; |
200 | | |
201 | | constexpr int numObjTypes = 17; // total number of object types |
202 | | |
203 | | //------------------------------------------------------------------------ |
204 | | // Object |
205 | | //------------------------------------------------------------------------ |
206 | | |
207 | | class POPPLER_PRIVATE_EXPORT Object |
208 | | { |
209 | | public: |
210 | 2.51G | static Object null() { return Object(objNull); } |
211 | 20.8M | static Object eof() { return Object(objEOF); } |
212 | 15.1M | static Object error() { return Object(objError); } |
213 | 4.03G | Object() : type(objNone) { } |
214 | 10.8G | ~Object() { free(); } |
215 | | |
216 | | explicit Object(bool boolnA) |
217 | 1.36M | { |
218 | 1.36M | type = objBool; |
219 | 1.36M | booln = boolnA; |
220 | 1.36M | } |
221 | | explicit Object(int intgA) |
222 | 1.04G | { |
223 | 1.04G | type = objInt; |
224 | 1.04G | intg = intgA; |
225 | 1.04G | } |
226 | | explicit Object(double realA) |
227 | 106M | { |
228 | 106M | type = objReal; |
229 | 106M | real = realA; |
230 | 106M | } |
231 | | explicit Object(std::unique_ptr<GooString> stringA) |
232 | 486k | { |
233 | 486k | assert(stringA); |
234 | 486k | type = objString; |
235 | 486k | string = stringA.release(); |
236 | 486k | } |
237 | | explicit Object(std::string &&stringA) |
238 | 47.6M | { |
239 | 47.6M | type = objString; |
240 | 47.6M | string = new GooString(stringA); |
241 | 47.6M | } |
242 | | Object(ObjType typeA, std::string &&stringA) |
243 | 0 | { |
244 | 0 | assert(typeA == objHexString); |
245 | 0 | type = typeA; |
246 | 0 | string = new GooString(stringA); |
247 | 0 | } |
248 | | Object(ObjType typeA, const char *stringA) |
249 | 700M | { |
250 | 700M | assert(typeA == objName || typeA == objCmd); |
251 | 700M | assert(stringA); |
252 | 700M | type = typeA; |
253 | 700M | cString = copyString(stringA); |
254 | 700M | } |
255 | | explicit Object(long long int64gA) |
256 | 967k | { |
257 | 967k | type = objInt64; |
258 | 967k | int64g = int64gA; |
259 | 967k | } |
260 | | explicit Object(Array *arrayA) |
261 | 34.6M | { |
262 | 34.6M | assert(arrayA); |
263 | 34.6M | type = objArray; |
264 | 34.6M | array = arrayA; |
265 | 34.6M | } |
266 | | explicit Object(Dict *dictA) |
267 | 23.5M | { |
268 | 23.5M | assert(dictA); |
269 | 23.5M | type = objDict; |
270 | 23.5M | dict = dictA; |
271 | 23.5M | } |
272 | | template<typename StreamType> |
273 | | requires(std::is_base_of_v<Stream, StreamType>) |
274 | | explicit Object(std::unique_ptr<StreamType> &&streamA) |
275 | 21.9M | { |
276 | 21.9M | assert(streamA); |
277 | 21.9M | type = objStream; |
278 | 21.9M | stream = streamA.release(); |
279 | 21.9M | } _ZN6ObjectC2I17AutoFreeMemStreamQsr3stdE12is_base_of_vI6StreamT_EEEONSt3__110unique_ptrIS3_NS4_14default_deleteIS3_EEEE Line | Count | Source | 275 | 81.2k | { | 276 | 81.2k | assert(streamA); | 277 | 81.2k | type = objStream; | 278 | 81.2k | stream = streamA.release(); | 279 | 81.2k | } |
Unexecuted instantiation: _ZN6ObjectC2I10FileStreamQsr3stdE12is_base_of_vI6StreamT_EEEONSt3__110unique_ptrIS3_NS4_14default_deleteIS3_EEEE _ZN6ObjectC2I6StreamQsr3stdE12is_base_of_vIS1_T_EEEONSt3__110unique_ptrIS2_NS3_14default_deleteIS2_EEEE Line | Count | Source | 275 | 21.9M | { | 276 | 21.9M | assert(streamA); | 277 | 21.9M | type = objStream; | 278 | 21.9M | stream = streamA.release(); | 279 | 21.9M | } |
_ZN6ObjectC2I9MemStreamQsr3stdE12is_base_of_vI6StreamT_EEEONSt3__110unique_ptrIS3_NS4_14default_deleteIS3_EEEE Line | Count | Source | 275 | 528 | { | 276 | 528 | assert(streamA); | 277 | 528 | type = objStream; | 278 | 528 | stream = streamA.release(); | 279 | 528 | } |
|
280 | | explicit Object(const Ref r) |
281 | 52.7M | { |
282 | 52.7M | type = objRef; |
283 | 52.7M | ref = r; |
284 | 52.7M | } |
285 | | |
286 | | template<typename T> |
287 | | Object(T) = delete; |
288 | | |
289 | | Object(Object &&other) noexcept |
290 | 2.33G | { |
291 | 2.33G | std::memcpy(reinterpret_cast<void *>(this), &other, sizeof(Object)); // NOLINT(bugprone-undefined-memory-manipulation) |
292 | 2.33G | other.type = objDead; |
293 | 2.33G | } |
294 | | |
295 | | Object &operator=(Object &&other) noexcept |
296 | 6.90G | { |
297 | 6.90G | free(); |
298 | | |
299 | 6.90G | std::memcpy(reinterpret_cast<void *>(this), &other, sizeof(Object)); // NOLINT(bugprone-undefined-memory-manipulation) |
300 | 6.90G | other.type = objDead; |
301 | | |
302 | 6.90G | return *this; |
303 | 6.90G | } |
304 | | |
305 | | Object &operator=(const Object &other) = delete; |
306 | | Object(const Object &other) = delete; |
307 | | |
308 | | // Set object to null. |
309 | | void setToNull() |
310 | 152M | { |
311 | 152M | free(); |
312 | 152M | type = objNull; |
313 | 152M | } |
314 | | |
315 | | // Copies all object types except |
316 | | // objArray, objDict, objStream whose refcount is increased by 1 |
317 | | Object copy() const; |
318 | | |
319 | | // Deep copies all object types (recursively) |
320 | | // except objStream whose refcount is increased by 1 |
321 | | Object deepCopy() const; |
322 | | |
323 | | // If object is a Ref, fetch and return the referenced object. |
324 | | // Otherwise, return a copy of the object. |
325 | | Object fetch(XRef *xref, int recursion = 0) const; |
326 | | |
327 | | // Type checking. |
328 | | ObjType getType() const |
329 | 54.6M | { |
330 | 54.6M | CHECK_NOT_DEAD; |
331 | 54.6M | return type; |
332 | 54.6M | } |
333 | | bool isBool() const |
334 | 4.03M | { |
335 | 4.03M | CHECK_NOT_DEAD; |
336 | 4.03M | return type == objBool; |
337 | 4.03M | } |
338 | | bool isInt() const |
339 | 1.49G | { |
340 | 1.49G | CHECK_NOT_DEAD; |
341 | 1.49G | return type == objInt; |
342 | 1.49G | } |
343 | | bool isReal() const |
344 | 8.95k | { |
345 | 8.95k | CHECK_NOT_DEAD; |
346 | 8.95k | return type == objReal; |
347 | 8.95k | } |
348 | | bool isNum() const |
349 | 324M | { |
350 | 324M | CHECK_NOT_DEAD; |
351 | 324M | return type == objInt || type == objReal || type == objInt64; |
352 | 324M | } |
353 | | bool isString() const |
354 | 456M | { |
355 | 456M | CHECK_NOT_DEAD; |
356 | 456M | return type == objString; |
357 | 456M | } |
358 | | bool isHexString() const |
359 | 0 | { |
360 | 0 | CHECK_NOT_DEAD; |
361 | 0 | return type == objHexString; |
362 | 0 | } |
363 | | bool isName() const |
364 | 365M | { |
365 | 365M | CHECK_NOT_DEAD; |
366 | 365M | return type == objName; |
367 | 365M | } |
368 | | bool isNull() const |
369 | 48.5M | { |
370 | 48.5M | CHECK_NOT_DEAD; |
371 | 48.5M | return type == objNull; |
372 | 48.5M | } |
373 | | bool isArray() const |
374 | 33.1M | { |
375 | 33.1M | CHECK_NOT_DEAD; |
376 | 33.1M | return type == objArray; |
377 | 33.1M | } |
378 | | bool isDict() const |
379 | 53.4M | { |
380 | 53.4M | CHECK_NOT_DEAD; |
381 | 53.4M | return type == objDict; |
382 | 53.4M | } |
383 | | bool isStream() const |
384 | 11.8G | { |
385 | 11.8G | CHECK_NOT_DEAD; |
386 | 11.8G | return type == objStream; |
387 | 11.8G | } |
388 | | bool isRef() const |
389 | 8.55M | { |
390 | 8.55M | CHECK_NOT_DEAD; |
391 | 8.55M | return type == objRef; |
392 | 8.55M | } |
393 | | bool isCmd() const |
394 | 229M | { |
395 | 229M | CHECK_NOT_DEAD; |
396 | 229M | return type == objCmd; |
397 | 229M | } |
398 | | bool isError() const |
399 | 177M | { |
400 | 177M | CHECK_NOT_DEAD; |
401 | 177M | return type == objError; |
402 | 177M | } |
403 | | bool isEOF() const |
404 | 1.29G | { |
405 | 1.29G | CHECK_NOT_DEAD; |
406 | 1.29G | return type == objEOF; |
407 | 1.29G | } |
408 | | bool isNone() const |
409 | 2.28M | { |
410 | 2.28M | CHECK_NOT_DEAD; |
411 | 2.28M | return type == objNone; |
412 | 2.28M | } |
413 | | bool isInt64() const |
414 | 5.07M | { |
415 | 5.07M | CHECK_NOT_DEAD; |
416 | 5.07M | return type == objInt64; |
417 | 5.07M | } |
418 | | bool isIntOrInt64() const |
419 | 0 | { |
420 | 0 | CHECK_NOT_DEAD; |
421 | 0 | return type == objInt || type == objInt64; |
422 | 0 | } |
423 | | |
424 | | // Special type checking. |
425 | 190M | bool isName(const char *nameA) const { return type == objName && !strcmp(cString, nameA); } |
426 | | bool isDict(const char *dictType) const; |
427 | 4.60G | bool isCmd(const char *cmdA) const { return type == objCmd && !strcmp(cString, cmdA); } |
428 | | |
429 | | // Accessors. |
430 | | bool getBool() const |
431 | 964k | { |
432 | 964k | OBJECT_TYPE_CHECK(objBool); |
433 | 964k | return booln; |
434 | 964k | } |
435 | | int getInt() const |
436 | 634M | { |
437 | 634M | OBJECT_TYPE_CHECK(objInt); |
438 | 634M | return intg; |
439 | 634M | } |
440 | | double getReal() const |
441 | 651k | { |
442 | 651k | OBJECT_TYPE_CHECK(objReal); |
443 | 651k | return real; |
444 | 651k | } |
445 | | |
446 | | // Note: integers larger than 2^53 can not be exactly represented by a double. |
447 | | // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64(). |
448 | | double getNum() const |
449 | 328M | { |
450 | 328M | OBJECT_3TYPES_CHECK(objInt, objInt64, objReal); |
451 | 328M | return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; |
452 | 328M | } |
453 | | double getNum(bool *ok) const |
454 | 164k | { |
455 | 164k | if (unlikely(type != objInt && type != objInt64 && type != objReal)) { |
456 | 9.34k | *ok = false; |
457 | 9.34k | return 0.; |
458 | 9.34k | } |
459 | 155k | return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; |
460 | 164k | } |
461 | | const GooString *getString() const |
462 | 30.0M | { |
463 | 30.0M | OBJECT_TYPE_CHECK(objString); |
464 | 30.0M | return string; |
465 | 30.0M | } |
466 | | const GooString *getHexString() const |
467 | 0 | { |
468 | 0 | OBJECT_TYPE_CHECK(objHexString); |
469 | 0 | return string; |
470 | 0 | } |
471 | | const char *getName() const |
472 | 210M | { |
473 | 210M | OBJECT_TYPE_CHECK(objName); |
474 | 210M | return cString; |
475 | 210M | } |
476 | | std::string getNameString() const |
477 | 995k | { |
478 | 995k | OBJECT_TYPE_CHECK(objName); |
479 | 995k | return std::string { cString }; |
480 | 995k | } |
481 | | Array *getArray() const |
482 | 7.69M | { |
483 | 7.69M | OBJECT_TYPE_CHECK(objArray); |
484 | 7.69M | return array; |
485 | 7.69M | } |
486 | | Dict *getDict() const |
487 | 21.4M | { |
488 | 21.4M | OBJECT_TYPE_CHECK(objDict); |
489 | 21.4M | return dict; |
490 | 21.4M | } |
491 | | Stream *getStream() const |
492 | 488M | { |
493 | 488M | OBJECT_TYPE_CHECK(objStream); |
494 | 488M | return stream; |
495 | 488M | } |
496 | | Ref getRef() const |
497 | 6.36M | { |
498 | 6.36M | OBJECT_TYPE_CHECK(objRef); |
499 | 6.36M | return ref; |
500 | 6.36M | } |
501 | | int getRefNum() const |
502 | 1.08M | { |
503 | 1.08M | OBJECT_TYPE_CHECK(objRef); |
504 | 1.08M | return ref.num; |
505 | 1.08M | } |
506 | | int getRefGen() const |
507 | 586k | { |
508 | 586k | OBJECT_TYPE_CHECK(objRef); |
509 | 586k | return ref.gen; |
510 | 586k | } |
511 | | const char *getCmd() const |
512 | 79.2M | { |
513 | 79.2M | OBJECT_TYPE_CHECK(objCmd); |
514 | 79.2M | return cString; |
515 | 79.2M | } |
516 | | long long getInt64() const |
517 | 68.7k | { |
518 | 68.7k | OBJECT_TYPE_CHECK(objInt64); |
519 | 68.7k | return int64g; |
520 | 68.7k | } |
521 | | long long getIntOrInt64() const |
522 | 0 | { |
523 | 0 | OBJECT_2TYPES_CHECK(objInt, objInt64); |
524 | 0 | return type == objInt ? intg : int64g; |
525 | 0 | } |
526 | | |
527 | | // Array accessors. |
528 | | int arrayGetLength() const; |
529 | | void arrayAdd(Object &&elem); |
530 | | void arrayRemove(int i); |
531 | | Object arrayGet(int i, int recursion) const; |
532 | | const Object &arrayGetNF(int i) const; |
533 | | |
534 | | // Dict accessors. |
535 | | int dictGetLength() const; |
536 | | void dictAdd(char *key, Object &&val) = delete; |
537 | | void dictAdd(const char *key, Object &&val); |
538 | | void dictSet(const char *key, Object &&val); |
539 | | void dictRemove(const char *key); |
540 | | bool dictIs(const char *dictType) const; |
541 | | Object dictLookup(const char *key, int recursion = 0) const; |
542 | | const Object &dictLookupNF(const char *key) const; |
543 | | const char *dictGetKey(int i) const; |
544 | | Object dictGetVal(int i) const; |
545 | | const Object &dictGetValNF(int i) const; |
546 | | |
547 | | // Stream accessors. |
548 | | [[nodiscard]] bool streamReset(); |
549 | | void streamClose(); |
550 | | int streamGetChar(); |
551 | | int streamGetChars(int nChars, unsigned char *buffer); |
552 | | void streamSetPos(Goffset pos, int dir = 0); |
553 | | Dict *streamGetDict() const; |
554 | | |
555 | | // Output. |
556 | | const char *getTypeName() const; |
557 | | void print(FILE *f = stdout) const; |
558 | | |
559 | | double getNumWithDefaultValue(double defaultValue) const |
560 | 2.78M | { |
561 | 2.78M | if (unlikely(type != objInt && type != objInt64 && type != objReal)) { |
562 | 253k | return defaultValue; |
563 | 253k | } |
564 | 2.52M | return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; |
565 | 2.78M | } |
566 | | |
567 | 141k | bool getBoolWithDefaultValue(bool defaultValue) const { return (type == objBool) ? booln : defaultValue; } |
568 | | |
569 | | private: |
570 | 2.55G | explicit Object(ObjType typeA) { type = typeA; } |
571 | | // Free object contents. |
572 | | void free(); |
573 | | |
574 | | ObjType type; // object type |
575 | | union { // value for each type: |
576 | | bool booln; // boolean |
577 | | int intg; // integer |
578 | | long long int64g; // 64-bit integer |
579 | | double real; // real |
580 | | GooString *string; // [hex] string |
581 | | char *cString; // name or command, depending on objType |
582 | | Array *array; // array |
583 | | Dict *dict; // dictionary |
584 | | Stream *stream; // stream |
585 | | Ref ref; // indirect reference |
586 | | }; |
587 | | }; |
588 | | |
589 | | //------------------------------------------------------------------------ |
590 | | // Array accessors. |
591 | | //------------------------------------------------------------------------ |
592 | | |
593 | | #include "Array.h" |
594 | | |
595 | | //------------------------------------------------------------------------ |
596 | | // Dict accessors. |
597 | | //------------------------------------------------------------------------ |
598 | | |
599 | | #include "Dict.h" |
600 | | |
601 | | //------------------------------------------------------------------------ |
602 | | // Stream accessors. |
603 | | //------------------------------------------------------------------------ |
604 | | |
605 | | #include "Stream.h" |
606 | | |
607 | | #endif |