Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-10 10:23:49

0001 //========================================================================
0002 //
0003 // Object.h
0004 //
0005 // Copyright 1996-2003 Glyph & Cog, LLC
0006 //
0007 //========================================================================
0008 
0009 //========================================================================
0010 //
0011 // Modified under the Poppler project - http://poppler.freedesktop.org
0012 //
0013 // All changes made under the Poppler project to this file are licensed
0014 // under GPL version 2 or later
0015 //
0016 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
0017 // Copyright (C) 2008 Kees Cook <kees@outflux.net>
0018 // Copyright (C) 2008, 2010, 2017-2021 Albert Astals Cid <aacid@kde.org>
0019 // Copyright (C) 2009 Jakub Wilk <jwilk@jwilk.net>
0020 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
0021 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
0022 // Copyright (C) 2013, 2017, 2018 Adrian Johnson <ajohnson@redneon.com>
0023 // Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com>
0024 // Copyright (C) 2016, 2020 Jakub Alba <jakubalba@gmail.com>
0025 // 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
0026 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
0027 // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
0028 //
0029 // To see a description of the changes please see the Changelog file that
0030 // came with your tarball or type make ChangeLog if you are building from git
0031 //
0032 //========================================================================
0033 
0034 #ifndef OBJECT_H
0035 #define OBJECT_H
0036 
0037 #include <cassert>
0038 #include <set>
0039 #include <cstdio>
0040 #include <cstring>
0041 #include <climits>
0042 #include "goo/gmem.h"
0043 #include "goo/GooString.h"
0044 #include "goo/GooLikely.h"
0045 #include "Error.h"
0046 #include "poppler_private_export.h"
0047 
0048 #define OBJECT_TYPE_CHECK(wanted_type)                                                                                                                                                                                                         \
0049     if (unlikely(type != wanted_type)) {                                                                                                                                                                                                       \
0050         error(errInternal, 0,                                                                                                                                                                                                                  \
0051               "Call to Object where the object was type {0:d}, "                                                                                                                                                                               \
0052               "not the expected type {1:d}",                                                                                                                                                                                                   \
0053               type, wanted_type);                                                                                                                                                                                                              \
0054         abort();                                                                                                                                                                                                                               \
0055     }
0056 
0057 #define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2)                                                                                                                                                                                        \
0058     if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2)) {                                                                                                                                                                    \
0059         error(errInternal, 0,                                                                                                                                                                                                                  \
0060               "Call to Object where the object was type {0:d}, "                                                                                                                                                                               \
0061               "not the expected type {1:d} or {2:d}",                                                                                                                                                                                          \
0062               type, wanted_type1, wanted_type2);                                                                                                                                                                                               \
0063         abort();                                                                                                                                                                                                                               \
0064     }
0065 
0066 #define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3)                                                                                                                                                                          \
0067     if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) {                                                                                                                                  \
0068         error(errInternal, 0,                                                                                                                                                                                                                  \
0069               "Call to Object where the object was type {0:d}, "                                                                                                                                                                               \
0070               "not the expected type {1:d}, {2:d} or {3:d}",                                                                                                                                                                                   \
0071               type, wanted_type1, wanted_type2, wanted_type3);                                                                                                                                                                                 \
0072         abort();                                                                                                                                                                                                                               \
0073     }
0074 
0075 #define CHECK_NOT_DEAD                                                                                                                                                                                                                         \
0076     if (unlikely(type == objDead)) {                                                                                                                                                                                                           \
0077         error(errInternal, 0, "Call to dead object");                                                                                                                                                                                          \
0078         abort();                                                                                                                                                                                                                               \
0079     }
0080 
0081 class XRef;
0082 class Array;
0083 class Dict;
0084 class Stream;
0085 
0086 //------------------------------------------------------------------------
0087 // Ref
0088 //------------------------------------------------------------------------
0089 
0090 struct Ref
0091 {
0092     int num; // object number
0093     int gen; // generation number
0094 
0095     static constexpr Ref INVALID() { return { -1, -1 }; };
0096 };
0097 
0098 inline bool operator==(const Ref lhs, const Ref rhs) noexcept
0099 {
0100     return lhs.num == rhs.num && lhs.gen == rhs.gen;
0101 }
0102 
0103 inline bool operator!=(const Ref lhs, const Ref rhs) noexcept
0104 {
0105     return lhs.num != rhs.num || lhs.gen != rhs.gen;
0106 }
0107 
0108 inline bool operator<(const Ref lhs, const Ref rhs) noexcept
0109 {
0110     if (lhs.num != rhs.num) {
0111         return lhs.num < rhs.num;
0112     }
0113     return lhs.gen < rhs.gen;
0114 }
0115 
0116 namespace std {
0117 
0118 template<>
0119 struct hash<Ref>
0120 {
0121     using argument_type = Ref;
0122     using result_type = size_t;
0123 
0124     result_type operator()(const argument_type ref) const noexcept { return std::hash<int> {}(ref.num) ^ (std::hash<int> {}(ref.gen) << 1); }
0125 };
0126 
0127 }
0128 
0129 //------------------------------------------------------------------------
0130 // object types
0131 //------------------------------------------------------------------------
0132 
0133 enum ObjType
0134 {
0135     // simple objects
0136     objBool, // boolean
0137     objInt, // integer
0138     objReal, // real
0139     objString, // string
0140     objName, // name
0141     objNull, // null
0142 
0143     // complex objects
0144     objArray, // array
0145     objDict, // dictionary
0146     objStream, // stream
0147     objRef, // indirect reference
0148 
0149     // special objects
0150     objCmd, // command name
0151     objError, // error return from Lexer
0152     objEOF, // end of file return from Lexer
0153     objNone, // uninitialized object
0154 
0155     // poppler-only objects
0156     objInt64, // integer with at least 64-bits
0157     objHexString, // hex string
0158     objDead // and object after shallowCopy
0159 };
0160 
0161 constexpr int numObjTypes = 17; // total number of object types
0162 
0163 //------------------------------------------------------------------------
0164 // Object
0165 //------------------------------------------------------------------------
0166 
0167 class POPPLER_PRIVATE_EXPORT Object
0168 {
0169 public:
0170     Object() : type(objNone) { }
0171     ~Object() { free(); }
0172 
0173     explicit Object(bool boolnA)
0174     {
0175         type = objBool;
0176         booln = boolnA;
0177     }
0178     explicit Object(int intgA)
0179     {
0180         type = objInt;
0181         intg = intgA;
0182     }
0183     explicit Object(ObjType typeA) { type = typeA; }
0184     explicit Object(double realA)
0185     {
0186         type = objReal;
0187         real = realA;
0188     }
0189     explicit Object(GooString *stringA)
0190     {
0191         assert(stringA);
0192         type = objString;
0193         string = stringA;
0194     }
0195     Object(ObjType typeA, GooString *stringA)
0196     {
0197         assert(typeA == objHexString);
0198         assert(stringA);
0199         type = typeA;
0200         string = stringA;
0201     }
0202     Object(ObjType typeA, const char *stringA)
0203     {
0204         assert(typeA == objName || typeA == objCmd);
0205         assert(stringA);
0206         type = typeA;
0207         cString = copyString(stringA);
0208     }
0209     explicit Object(long long int64gA)
0210     {
0211         type = objInt64;
0212         int64g = int64gA;
0213     }
0214     explicit Object(Array *arrayA)
0215     {
0216         assert(arrayA);
0217         type = objArray;
0218         array = arrayA;
0219     }
0220     explicit Object(Dict *dictA)
0221     {
0222         assert(dictA);
0223         type = objDict;
0224         dict = dictA;
0225     }
0226     explicit Object(Stream *streamA)
0227     {
0228         assert(streamA);
0229         type = objStream;
0230         stream = streamA;
0231     }
0232     explicit Object(const Ref r)
0233     {
0234         type = objRef;
0235         ref = r;
0236     }
0237 
0238     template<typename T>
0239     Object(T) = delete;
0240 
0241     Object(Object &&other) noexcept
0242     {
0243         std::memcpy(reinterpret_cast<void *>(this), &other, sizeof(Object));
0244         other.type = objDead;
0245     }
0246 
0247     Object &operator=(Object &&other) noexcept
0248     {
0249         free();
0250 
0251         std::memcpy(reinterpret_cast<void *>(this), &other, sizeof(Object));
0252         other.type = objDead;
0253 
0254         return *this;
0255     }
0256 
0257     Object &operator=(const Object &other) = delete;
0258     Object(const Object &other) = delete;
0259 
0260     // Set object to null.
0261     void setToNull()
0262     {
0263         free();
0264         type = objNull;
0265     }
0266 
0267     // Copies all object types except
0268     // objArray, objDict, objStream whose refcount is increased by 1
0269     Object copy() const;
0270 
0271     // Deep copies all object types (recursively)
0272     // except objStream whose refcount is increased by 1
0273     Object deepCopy() const;
0274 
0275     // If object is a Ref, fetch and return the referenced object.
0276     // Otherwise, return a copy of the object.
0277     Object fetch(XRef *xref, int recursion = 0) const;
0278 
0279     // Type checking.
0280     ObjType getType() const
0281     {
0282         CHECK_NOT_DEAD;
0283         return type;
0284     }
0285     bool isBool() const
0286     {
0287         CHECK_NOT_DEAD;
0288         return type == objBool;
0289     }
0290     bool isInt() const
0291     {
0292         CHECK_NOT_DEAD;
0293         return type == objInt;
0294     }
0295     bool isReal() const
0296     {
0297         CHECK_NOT_DEAD;
0298         return type == objReal;
0299     }
0300     bool isNum() const
0301     {
0302         CHECK_NOT_DEAD;
0303         return type == objInt || type == objReal || type == objInt64;
0304     }
0305     bool isString() const
0306     {
0307         CHECK_NOT_DEAD;
0308         return type == objString;
0309     }
0310     bool isHexString() const
0311     {
0312         CHECK_NOT_DEAD;
0313         return type == objHexString;
0314     }
0315     bool isName() const
0316     {
0317         CHECK_NOT_DEAD;
0318         return type == objName;
0319     }
0320     bool isNull() const
0321     {
0322         CHECK_NOT_DEAD;
0323         return type == objNull;
0324     }
0325     bool isArray() const
0326     {
0327         CHECK_NOT_DEAD;
0328         return type == objArray;
0329     }
0330     bool isDict() const
0331     {
0332         CHECK_NOT_DEAD;
0333         return type == objDict;
0334     }
0335     bool isStream() const
0336     {
0337         CHECK_NOT_DEAD;
0338         return type == objStream;
0339     }
0340     bool isRef() const
0341     {
0342         CHECK_NOT_DEAD;
0343         return type == objRef;
0344     }
0345     bool isCmd() const
0346     {
0347         CHECK_NOT_DEAD;
0348         return type == objCmd;
0349     }
0350     bool isError() const
0351     {
0352         CHECK_NOT_DEAD;
0353         return type == objError;
0354     }
0355     bool isEOF() const
0356     {
0357         CHECK_NOT_DEAD;
0358         return type == objEOF;
0359     }
0360     bool isNone() const
0361     {
0362         CHECK_NOT_DEAD;
0363         return type == objNone;
0364     }
0365     bool isInt64() const
0366     {
0367         CHECK_NOT_DEAD;
0368         return type == objInt64;
0369     }
0370     bool isIntOrInt64() const
0371     {
0372         CHECK_NOT_DEAD;
0373         return type == objInt || type == objInt64;
0374     }
0375 
0376     // Special type checking.
0377     bool isName(const char *nameA) const { return type == objName && !strcmp(cString, nameA); }
0378     bool isDict(const char *dictType) const;
0379     bool isCmd(const char *cmdA) const { return type == objCmd && !strcmp(cString, cmdA); }
0380 
0381     // Accessors.
0382     bool getBool() const
0383     {
0384         OBJECT_TYPE_CHECK(objBool);
0385         return booln;
0386     }
0387     int getInt() const
0388     {
0389         OBJECT_TYPE_CHECK(objInt);
0390         return intg;
0391     }
0392     double getReal() const
0393     {
0394         OBJECT_TYPE_CHECK(objReal);
0395         return real;
0396     }
0397 
0398     // Note: integers larger than 2^53 can not be exactly represented by a double.
0399     // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
0400     double getNum() const
0401     {
0402         OBJECT_3TYPES_CHECK(objInt, objInt64, objReal);
0403         return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real;
0404     }
0405     double getNum(bool *ok) const
0406     {
0407         if (unlikely(type != objInt && type != objInt64 && type != objReal)) {
0408             *ok = false;
0409             return 0.;
0410         }
0411         return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real;
0412     }
0413     const GooString *getString() const
0414     {
0415         OBJECT_TYPE_CHECK(objString);
0416         return string;
0417     }
0418     const GooString *getHexString() const
0419     {
0420         OBJECT_TYPE_CHECK(objHexString);
0421         return string;
0422     }
0423     const char *getName() const
0424     {
0425         OBJECT_TYPE_CHECK(objName);
0426         return cString;
0427     }
0428     Array *getArray() const
0429     {
0430         OBJECT_TYPE_CHECK(objArray);
0431         return array;
0432     }
0433     Dict *getDict() const
0434     {
0435         OBJECT_TYPE_CHECK(objDict);
0436         return dict;
0437     }
0438     Stream *getStream() const
0439     {
0440         OBJECT_TYPE_CHECK(objStream);
0441         return stream;
0442     }
0443     Ref getRef() const
0444     {
0445         OBJECT_TYPE_CHECK(objRef);
0446         return ref;
0447     }
0448     int getRefNum() const
0449     {
0450         OBJECT_TYPE_CHECK(objRef);
0451         return ref.num;
0452     }
0453     int getRefGen() const
0454     {
0455         OBJECT_TYPE_CHECK(objRef);
0456         return ref.gen;
0457     }
0458     const char *getCmd() const
0459     {
0460         OBJECT_TYPE_CHECK(objCmd);
0461         return cString;
0462     }
0463     long long getInt64() const
0464     {
0465         OBJECT_TYPE_CHECK(objInt64);
0466         return int64g;
0467     }
0468     long long getIntOrInt64() const
0469     {
0470         OBJECT_2TYPES_CHECK(objInt, objInt64);
0471         return type == objInt ? intg : int64g;
0472     }
0473 
0474     // Array accessors.
0475     int arrayGetLength() const;
0476     void arrayAdd(Object &&elem);
0477     void arrayRemove(int i);
0478     Object arrayGet(int i, int recursion) const;
0479     const Object &arrayGetNF(int i) const;
0480 
0481     // Dict accessors.
0482     int dictGetLength() const;
0483     void dictAdd(char *key, Object &&val) = delete;
0484     void dictAdd(const char *key, Object &&val);
0485     void dictSet(const char *key, Object &&val);
0486     void dictRemove(const char *key);
0487     bool dictIs(const char *dictType) const;
0488     Object dictLookup(const char *key, int recursion = 0) const;
0489     const Object &dictLookupNF(const char *key) const;
0490     const char *dictGetKey(int i) const;
0491     Object dictGetVal(int i) const;
0492     const Object &dictGetValNF(int i) const;
0493 
0494     // Stream accessors.
0495     void streamReset();
0496     void streamClose();
0497     int streamGetChar();
0498     int streamGetChars(int nChars, unsigned char *buffer);
0499     void streamSetPos(Goffset pos, int dir = 0);
0500     Dict *streamGetDict() const;
0501 
0502     // Output.
0503     const char *getTypeName() const;
0504     void print(FILE *f = stdout) const;
0505 
0506     double getNumWithDefaultValue(double defaultValue) const
0507     {
0508         if (unlikely(type != objInt && type != objInt64 && type != objReal)) {
0509             return defaultValue;
0510         }
0511         return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real;
0512     }
0513 
0514     bool getBoolWithDefaultValue(bool defaultValue) const { return (type == objBool) ? booln : defaultValue; }
0515 
0516 private:
0517     // Free object contents.
0518     void free();
0519 
0520     ObjType type; // object type
0521     union { // value for each type:
0522         bool booln; //   boolean
0523         int intg; //   integer
0524         long long int64g; //   64-bit integer
0525         double real; //   real
0526         GooString *string; // [hex] string
0527         char *cString; //   name or command, depending on objType
0528         Array *array; //   array
0529         Dict *dict; //   dictionary
0530         Stream *stream; //   stream
0531         Ref ref; //   indirect reference
0532     };
0533 };
0534 
0535 //------------------------------------------------------------------------
0536 // Array accessors.
0537 //------------------------------------------------------------------------
0538 
0539 #include "Array.h"
0540 
0541 inline int Object::arrayGetLength() const
0542 {
0543     OBJECT_TYPE_CHECK(objArray);
0544     return array->getLength();
0545 }
0546 
0547 inline void Object::arrayAdd(Object &&elem)
0548 {
0549     OBJECT_TYPE_CHECK(objArray);
0550     array->add(std::move(elem));
0551 }
0552 
0553 inline void Object::arrayRemove(int i)
0554 {
0555     OBJECT_TYPE_CHECK(objArray);
0556     array->remove(i);
0557 }
0558 
0559 inline Object Object::arrayGet(int i, int recursion = 0) const
0560 {
0561     OBJECT_TYPE_CHECK(objArray);
0562     return array->get(i, recursion);
0563 }
0564 
0565 inline const Object &Object::arrayGetNF(int i) const
0566 {
0567     OBJECT_TYPE_CHECK(objArray);
0568     return array->getNF(i);
0569 }
0570 
0571 //------------------------------------------------------------------------
0572 // Dict accessors.
0573 //------------------------------------------------------------------------
0574 
0575 #include "Dict.h"
0576 
0577 inline int Object::dictGetLength() const
0578 {
0579     OBJECT_TYPE_CHECK(objDict);
0580     return dict->getLength();
0581 }
0582 
0583 inline void Object::dictAdd(const char *key, Object &&val)
0584 {
0585     OBJECT_TYPE_CHECK(objDict);
0586     dict->add(key, std::move(val));
0587 }
0588 
0589 inline void Object::dictSet(const char *key, Object &&val)
0590 {
0591     OBJECT_TYPE_CHECK(objDict);
0592     dict->set(key, std::move(val));
0593 }
0594 
0595 inline void Object::dictRemove(const char *key)
0596 {
0597     OBJECT_TYPE_CHECK(objDict);
0598     dict->remove(key);
0599 }
0600 
0601 inline bool Object::dictIs(const char *dictType) const
0602 {
0603     OBJECT_TYPE_CHECK(objDict);
0604     return dict->is(dictType);
0605 }
0606 
0607 inline bool Object::isDict(const char *dictType) const
0608 {
0609     return type == objDict && dictIs(dictType);
0610 }
0611 
0612 inline Object Object::dictLookup(const char *key, int recursion) const
0613 {
0614     OBJECT_TYPE_CHECK(objDict);
0615     return dict->lookup(key, recursion);
0616 }
0617 
0618 inline const Object &Object::dictLookupNF(const char *key) const
0619 {
0620     OBJECT_TYPE_CHECK(objDict);
0621     return dict->lookupNF(key);
0622 }
0623 
0624 inline const char *Object::dictGetKey(int i) const
0625 {
0626     OBJECT_TYPE_CHECK(objDict);
0627     return dict->getKey(i);
0628 }
0629 
0630 inline Object Object::dictGetVal(int i) const
0631 {
0632     OBJECT_TYPE_CHECK(objDict);
0633     return dict->getVal(i);
0634 }
0635 
0636 inline const Object &Object::dictGetValNF(int i) const
0637 {
0638     OBJECT_TYPE_CHECK(objDict);
0639     return dict->getValNF(i);
0640 }
0641 
0642 //------------------------------------------------------------------------
0643 // Stream accessors.
0644 //------------------------------------------------------------------------
0645 
0646 #include "Stream.h"
0647 
0648 inline void Object::streamReset()
0649 {
0650     OBJECT_TYPE_CHECK(objStream);
0651     stream->reset();
0652 }
0653 
0654 inline void Object::streamClose()
0655 {
0656     OBJECT_TYPE_CHECK(objStream);
0657     stream->close();
0658 }
0659 
0660 inline int Object::streamGetChar()
0661 {
0662     OBJECT_TYPE_CHECK(objStream);
0663     return stream->getChar();
0664 }
0665 
0666 inline int Object::streamGetChars(int nChars, unsigned char *buffer)
0667 {
0668     OBJECT_TYPE_CHECK(objStream);
0669     return stream->doGetChars(nChars, buffer);
0670 }
0671 
0672 inline Dict *Object::streamGetDict() const
0673 {
0674     OBJECT_TYPE_CHECK(objStream);
0675     return stream->getDict();
0676 }
0677 
0678 #endif