1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
17 // Copyright (C) 2008 Kees Cook <kees@outflux.net>
18 // Copyright (C) 2008, 2010 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 Adrian Johnson <ajohnson@redneon.com>
23 // Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com>
24 // Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
26 // To see a description of the changes please see the Changelog file that
27 // came with your tarball or type make ChangeLog if you are building from git
29 //========================================================================
34 #ifdef USE_GCC_PRAGMAS
41 #include "goo/gtypes.h"
43 #include "goo/GooString.h"
44 #include "goo/GooLikely.h"
47 #define OBJECT_TYPE_CHECK(wanted_type) \
48 if (unlikely(type != wanted_type)) { \
49 error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
50 "not the expected type {1:d}", type, wanted_type); \
54 #define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2) \
55 if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2)) { \
56 error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
57 "not the expected type {1:d} or {2:d}", type, wanted_type1, wanted_type2); \
61 #define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \
62 if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \
63 error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
64 "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \
73 //------------------------------------------------------------------------
75 //------------------------------------------------------------------------
78 int num
; // object number
79 int gen
; // generation number
82 //------------------------------------------------------------------------
84 //------------------------------------------------------------------------
97 objDict
, // dictionary
99 objRef
, // indirect reference
102 objCmd
, // command name
103 objError
, // error return from Lexer
104 objEOF
, // end of file return from Lexer
105 objNone
, // uninitialized object
107 // poppler-only objects
108 objInt64
// integer with at least 64-bits
111 #define numObjTypes 15 // total number of object types
113 //------------------------------------------------------------------------
115 //------------------------------------------------------------------------
118 #define initObj(t) zeroUnion(); ++numAlloc[type = t]
120 #define initObj(t) zeroUnion(); type = t
125 // clear the anonymous union as best we can -- clear at least a pointer
126 void zeroUnion() { this->name
= NULL
; }
128 // Default constructor.
130 type(objNone
) { zeroUnion(); }
132 // Initialize an object.
133 Object
*initBool(GBool boolnA
)
134 { initObj(objBool
); booln
= boolnA
; return this; }
135 Object
*initInt(int intgA
)
136 { initObj(objInt
); intg
= intgA
; return this; }
137 Object
*initReal(double realA
)
138 { initObj(objReal
); real
= realA
; return this; }
139 Object
*initString(GooString
*stringA
)
140 { initObj(objString
); string
= stringA
; return this; }
141 Object
*initName(const char *nameA
)
142 { initObj(objName
); name
= copyString(nameA
); return this; }
144 { initObj(objNull
); return this; }
145 Object
*initArray(XRef
*xref
);
146 Object
*initDict(XRef
*xref
);
147 Object
*initDict(Dict
*dictA
);
148 Object
*initStream(Stream
*streamA
);
149 Object
*initRef(int numA
, int genA
)
150 { initObj(objRef
); ref
.num
= numA
; ref
.gen
= genA
; return this; }
151 Object
*initCmd(const char *cmdA
)
152 { initObj(objCmd
); cmd
= copyString(cmdA
); return this; }
154 { initObj(objError
); return this; }
156 { initObj(objEOF
); return this; }
157 Object
*initInt64(long long int64gA
)
158 { initObj(objInt64
); int64g
= int64gA
; return this; }
161 Object
*copy(Object
*obj
);
162 Object
*shallowCopy(Object
*obj
) {
167 // If object is a Ref, fetch and return the referenced object.
168 // Otherwise, return a copy of the object.
169 Object
*fetch(XRef
*xref
, Object
*obj
, int recursion
= 0);
171 // Free object contents.
175 ObjType
getType() { return type
; }
176 GBool
isBool() { return type
== objBool
; }
177 GBool
isInt() { return type
== objInt
; }
178 GBool
isReal() { return type
== objReal
; }
179 GBool
isNum() { return type
== objInt
|| type
== objReal
|| type
== objInt64
; }
180 GBool
isString() { return type
== objString
; }
181 GBool
isName() { return type
== objName
; }
182 GBool
isNull() { return type
== objNull
; }
183 GBool
isArray() { return type
== objArray
; }
184 GBool
isDict() { return type
== objDict
; }
185 GBool
isStream() { return type
== objStream
; }
186 GBool
isRef() { return type
== objRef
; }
187 GBool
isCmd() { return type
== objCmd
; }
188 GBool
isError() { return type
== objError
; }
189 GBool
isEOF() { return type
== objEOF
; }
190 GBool
isNone() { return type
== objNone
; }
191 GBool
isInt64() { return type
== objInt64
; }
192 GBool
isIntOrInt64() { return type
== objInt
|| type
== objInt64
; }
194 // Special type checking.
195 GBool
isName(const char *nameA
)
196 { return type
== objName
&& !strcmp(name
, nameA
); }
197 GBool
isDict(const char *dictType
);
198 GBool
isStream(const char *dictType
);
199 GBool
isCmd(const char *cmdA
)
200 { return type
== objCmd
&& !strcmp(cmd
, cmdA
); }
203 GBool
getBool() { OBJECT_TYPE_CHECK(objBool
); return booln
; }
204 int getInt() { OBJECT_TYPE_CHECK(objInt
); return intg
; }
205 double getReal() { OBJECT_TYPE_CHECK(objReal
); return real
; }
207 // Note: integers larger than 2^53 can not be exactly represented by a double.
208 // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
209 double getNum() { OBJECT_3TYPES_CHECK(objInt
, objInt64
, objReal
);
210 return type
== objInt
? (double)intg
: type
== objInt64
? (double)int64g
: real
; }
211 GooString
*getString() { OBJECT_TYPE_CHECK(objString
); return string
; }
212 // After takeString() the only method that should be called for the object is free()
213 // because the object it's not expected to have a NULL string.
214 GooString
*takeString() {
215 OBJECT_TYPE_CHECK(objString
); GooString
*s
= string
; string
= NULL
; return s
; }
216 char *getName() { OBJECT_TYPE_CHECK(objName
); return name
; }
217 Array
*getArray() { OBJECT_TYPE_CHECK(objArray
); return array
; }
218 Dict
*getDict() { OBJECT_TYPE_CHECK(objDict
); return dict
; }
219 Stream
*getStream() { OBJECT_TYPE_CHECK(objStream
); return stream
; }
220 Ref
getRef() { OBJECT_TYPE_CHECK(objRef
); return ref
; }
221 int getRefNum() { OBJECT_TYPE_CHECK(objRef
); return ref
.num
; }
222 int getRefGen() { OBJECT_TYPE_CHECK(objRef
); return ref
.gen
; }
223 char *getCmd() { OBJECT_TYPE_CHECK(objCmd
); return cmd
; }
224 long long getInt64() { OBJECT_TYPE_CHECK(objInt64
); return int64g
; }
225 long long getIntOrInt64() { OBJECT_2TYPES_CHECK(objInt
, objInt64
);
226 return type
== objInt
? intg
: int64g
; }
229 int arrayGetLength();
230 void arrayAdd(Object
*elem
);
231 void arrayRemove(int i
);
232 Object
*arrayGet(int i
, Object
*obj
, int recursion
);
233 Object
*arrayGetNF(int i
, Object
*obj
);
237 void dictAdd(char *key
, Object
*val
);
238 void dictSet(const char *key
, Object
*val
);
239 void dictRemove(const char *key
);
240 GBool
dictIs(const char *dictType
);
241 Object
*dictLookup(const char *key
, Object
*obj
, int recursion
= 0);
242 Object
*dictLookupNF(const char *key
, Object
*obj
);
243 char *dictGetKey(int i
);
244 Object
*dictGetVal(int i
, Object
*obj
);
245 Object
*dictGetValNF(int i
, Object
*obj
);
248 GBool
streamIs(const char *dictType
);
252 int streamGetChars(int nChars
, Guchar
*buffer
);
253 int streamLookChar();
254 char *streamGetLine(char *buf
, int size
);
255 Goffset
streamGetPos();
256 void streamSetPos(Goffset pos
, int dir
= 0);
257 Dict
*streamGetDict();
260 const char *getTypeName();
261 void print(FILE *f
= stdout
);
264 static void memCheck(FILE *f
);
268 ObjType type
; // object type
269 union { // value for each type:
270 GBool booln
; // boolean
272 long long int64g
; // 64-bit integer
274 GooString
*string
; // string
276 Array
*array
; // array
277 Dict
*dict
; // dictionary
278 Stream
*stream
; // stream
279 Ref ref
; // indirect reference
280 char *cmd
; // command
284 static int // number of each type of object
285 numAlloc
[numObjTypes
]; // currently allocated
289 //------------------------------------------------------------------------
291 //------------------------------------------------------------------------
295 inline int Object::arrayGetLength()
296 { OBJECT_TYPE_CHECK(objArray
); return array
->getLength(); }
298 inline void Object::arrayAdd(Object
*elem
)
299 { OBJECT_TYPE_CHECK(objArray
); array
->add(elem
); }
301 inline void Object::arrayRemove(int i
)
302 { OBJECT_TYPE_CHECK(objArray
); array
->remove(i
); }
304 inline Object
*Object::arrayGet(int i
, Object
*obj
, int recursion
= 0)
305 { OBJECT_TYPE_CHECK(objArray
); return array
->get(i
, obj
, recursion
); }
307 inline Object
*Object::arrayGetNF(int i
, Object
*obj
)
308 { OBJECT_TYPE_CHECK(objArray
); return array
->getNF(i
, obj
); }
310 //------------------------------------------------------------------------
312 //------------------------------------------------------------------------
316 inline int Object::dictGetLength()
317 { OBJECT_TYPE_CHECK(objDict
); return dict
->getLength(); }
319 inline void Object::dictAdd(char *key
, Object
*val
)
320 { OBJECT_TYPE_CHECK(objDict
); dict
->add(key
, val
); }
322 inline void Object::dictSet(const char *key
, Object
*val
)
323 { OBJECT_TYPE_CHECK(objDict
); dict
->set(key
, val
); }
325 inline void Object::dictRemove(const char *key
)
326 { OBJECT_TYPE_CHECK(objDict
); dict
->remove(key
); }
328 inline GBool
Object::dictIs(const char *dictType
)
329 { OBJECT_TYPE_CHECK(objDict
); return dict
->is(dictType
); }
331 inline GBool
Object::isDict(const char *dictType
)
332 { return type
== objDict
&& dictIs(dictType
); }
334 inline Object
*Object::dictLookup(const char *key
, Object
*obj
, int recursion
)
335 { OBJECT_TYPE_CHECK(objDict
); return dict
->lookup(key
, obj
, recursion
); }
337 inline Object
*Object::dictLookupNF(const char *key
, Object
*obj
)
338 { OBJECT_TYPE_CHECK(objDict
); return dict
->lookupNF(key
, obj
); }
340 inline char *Object::dictGetKey(int i
)
341 { OBJECT_TYPE_CHECK(objDict
); return dict
->getKey(i
); }
343 inline Object
*Object::dictGetVal(int i
, Object
*obj
)
344 { OBJECT_TYPE_CHECK(objDict
); return dict
->getVal(i
, obj
); }
346 inline Object
*Object::dictGetValNF(int i
, Object
*obj
)
347 { OBJECT_TYPE_CHECK(objDict
); return dict
->getValNF(i
, obj
); }
349 //------------------------------------------------------------------------
351 //------------------------------------------------------------------------
355 inline GBool
Object::streamIs(const char *dictType
)
356 { OBJECT_TYPE_CHECK(objStream
); return stream
->getDict()->is(dictType
); }
358 inline GBool
Object::isStream(const char *dictType
)
359 { return type
== objStream
&& streamIs(dictType
); }
361 inline void Object::streamReset()
362 { OBJECT_TYPE_CHECK(objStream
); stream
->reset(); }
364 inline void Object::streamClose()
365 { OBJECT_TYPE_CHECK(objStream
); stream
->close(); }
367 inline int Object::streamGetChar()
368 { OBJECT_TYPE_CHECK(objStream
); return stream
->getChar(); }
370 inline int Object::streamGetChars(int nChars
, Guchar
*buffer
)
371 { OBJECT_TYPE_CHECK(objStream
); return stream
->doGetChars(nChars
, buffer
); }
373 inline int Object::streamLookChar()
374 { OBJECT_TYPE_CHECK(objStream
); return stream
->lookChar(); }
376 inline char *Object::streamGetLine(char *buf
, int size
)
377 { OBJECT_TYPE_CHECK(objStream
); return stream
->getLine(buf
, size
); }
379 inline Goffset
Object::streamGetPos()
380 { OBJECT_TYPE_CHECK(objStream
); return stream
->getPos(); }
382 inline void Object::streamSetPos(Goffset pos
, int dir
)
383 { OBJECT_TYPE_CHECK(objStream
); stream
->setPos(pos
, dir
); }
385 inline Dict
*Object::streamGetDict()
386 { OBJECT_TYPE_CHECK(objStream
); return stream
->getDict(); }