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>
25 // To see a description of the changes please see the Changelog file that
26 // came with your tarball or type make ChangeLog if you are building from git
28 //========================================================================
33 #ifdef USE_GCC_PRAGMAS
40 #include "goo/gtypes.h"
42 #include "goo/GooString.h"
43 #include "goo/GooLikely.h"
46 #define OBJECT_TYPE_CHECK(wanted_type) \
47 if (unlikely(type != wanted_type)) { \
48 error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
49 "not the expected type {1:d}", type, wanted_type); \
53 #define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \
54 if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \
55 error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
56 "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \
65 //------------------------------------------------------------------------
67 //------------------------------------------------------------------------
70 int num
; // object number
71 int gen
; // generation number
74 //------------------------------------------------------------------------
76 //------------------------------------------------------------------------
89 objDict
, // dictionary
91 objRef
, // indirect reference
94 objCmd
, // command name
95 objError
, // error return from Lexer
96 objEOF
, // end of file return from Lexer
97 objNone
, // uninitialized object
99 // poppler-only objects
100 objInt64
// integer with at least 64-bits
103 #define numObjTypes 15 // total number of object types
105 //------------------------------------------------------------------------
107 //------------------------------------------------------------------------
110 #define initObj(t) zeroUnion(); ++numAlloc[type = t]
112 #define initObj(t) zeroUnion(); type = t
117 // clear the anonymous union as best we can -- clear at least a pointer
118 void zeroUnion() { this->name
= NULL
; }
120 // Default constructor.
122 type(objNone
) { zeroUnion(); }
124 // Initialize an object.
125 Object
*initBool(GBool boolnA
)
126 { initObj(objBool
); booln
= boolnA
; return this; }
127 Object
*initInt(int intgA
)
128 { initObj(objInt
); intg
= intgA
; return this; }
129 Object
*initReal(double realA
)
130 { initObj(objReal
); real
= realA
; return this; }
131 Object
*initString(GooString
*stringA
)
132 { initObj(objString
); string
= stringA
; return this; }
133 Object
*initName(const char *nameA
)
134 { initObj(objName
); name
= copyString(nameA
); return this; }
136 { initObj(objNull
); return this; }
137 Object
*initArray(XRef
*xref
);
138 Object
*initDict(XRef
*xref
);
139 Object
*initDict(Dict
*dictA
);
140 Object
*initStream(Stream
*streamA
);
141 Object
*initRef(int numA
, int genA
)
142 { initObj(objRef
); ref
.num
= numA
; ref
.gen
= genA
; return this; }
143 Object
*initCmd(const char *cmdA
)
144 { initObj(objCmd
); cmd
= copyString(cmdA
); return this; }
146 { initObj(objError
); return this; }
148 { initObj(objEOF
); return this; }
149 Object
*initInt64(long long int64gA
)
150 { initObj(objInt64
); int64g
= int64gA
; return this; }
153 Object
*copy(Object
*obj
);
154 Object
*shallowCopy(Object
*obj
) {
159 // If object is a Ref, fetch and return the referenced object.
160 // Otherwise, return a copy of the object.
161 Object
*fetch(XRef
*xref
, Object
*obj
, int recursion
= 0);
163 // Free object contents.
167 ObjType
getType() { return type
; }
168 GBool
isBool() { return type
== objBool
; }
169 GBool
isInt() { return type
== objInt
; }
170 GBool
isReal() { return type
== objReal
; }
171 GBool
isNum() { return type
== objInt
|| type
== objReal
|| type
== objInt64
; }
172 GBool
isString() { return type
== objString
; }
173 GBool
isName() { return type
== objName
; }
174 GBool
isNull() { return type
== objNull
; }
175 GBool
isArray() { return type
== objArray
; }
176 GBool
isDict() { return type
== objDict
; }
177 GBool
isStream() { return type
== objStream
; }
178 GBool
isRef() { return type
== objRef
; }
179 GBool
isCmd() { return type
== objCmd
; }
180 GBool
isError() { return type
== objError
; }
181 GBool
isEOF() { return type
== objEOF
; }
182 GBool
isNone() { return type
== objNone
; }
183 GBool
isInt64() { return type
== objInt64
; }
185 // Special type checking.
186 GBool
isName(const char *nameA
)
187 { return type
== objName
&& !strcmp(name
, nameA
); }
188 GBool
isDict(const char *dictType
);
189 GBool
isStream(const char *dictType
);
190 GBool
isCmd(const char *cmdA
)
191 { return type
== objCmd
&& !strcmp(cmd
, cmdA
); }
194 GBool
getBool() { OBJECT_TYPE_CHECK(objBool
); return booln
; }
195 int getInt() { OBJECT_TYPE_CHECK(objInt
); return intg
; }
196 double getReal() { OBJECT_TYPE_CHECK(objReal
); return real
; }
198 // Note: integers larger than 2^53 can not be exactly represented by a double.
199 // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
200 double getNum() { OBJECT_3TYPES_CHECK(objInt
, objInt64
, objReal
);
201 return type
== objInt
? (double)intg
: type
== objInt64
? (double)int64g
: real
; }
202 GooString
*getString() { OBJECT_TYPE_CHECK(objString
); return string
; }
203 // After takeString() the only method that should be called for the object is free()
204 // because the object it's not expected to have a NULL string.
205 GooString
*takeString() {
206 OBJECT_TYPE_CHECK(objString
); GooString
*s
= string
; string
= NULL
; return s
; }
207 char *getName() { OBJECT_TYPE_CHECK(objName
); return name
; }
208 Array
*getArray() { OBJECT_TYPE_CHECK(objArray
); return array
; }
209 Dict
*getDict() { OBJECT_TYPE_CHECK(objDict
); return dict
; }
210 Stream
*getStream() { OBJECT_TYPE_CHECK(objStream
); return stream
; }
211 Ref
getRef() { OBJECT_TYPE_CHECK(objRef
); return ref
; }
212 int getRefNum() { OBJECT_TYPE_CHECK(objRef
); return ref
.num
; }
213 int getRefGen() { OBJECT_TYPE_CHECK(objRef
); return ref
.gen
; }
214 char *getCmd() { OBJECT_TYPE_CHECK(objCmd
); return cmd
; }
215 long long getInt64() { OBJECT_TYPE_CHECK(objInt64
); return int64g
; }
218 int arrayGetLength();
219 void arrayAdd(Object
*elem
);
220 void arrayRemove(int i
);
221 Object
*arrayGet(int i
, Object
*obj
, int recursion
);
222 Object
*arrayGetNF(int i
, Object
*obj
);
226 void dictAdd(char *key
, Object
*val
);
227 void dictSet(const char *key
, Object
*val
);
228 GBool
dictIs(const char *dictType
);
229 Object
*dictLookup(const char *key
, Object
*obj
, int recursion
= 0);
230 Object
*dictLookupNF(const char *key
, Object
*obj
);
231 char *dictGetKey(int i
);
232 Object
*dictGetVal(int i
, Object
*obj
);
233 Object
*dictGetValNF(int i
, Object
*obj
);
236 GBool
streamIs(const char *dictType
);
240 int streamGetChars(int nChars
, Guchar
*buffer
);
241 int streamLookChar();
242 char *streamGetLine(char *buf
, int size
);
243 Goffset
streamGetPos();
244 void streamSetPos(Goffset pos
, int dir
= 0);
245 Dict
*streamGetDict();
248 const char *getTypeName();
249 void print(FILE *f
= stdout
);
252 static void memCheck(FILE *f
);
256 ObjType type
; // object type
257 union { // value for each type:
258 GBool booln
; // boolean
260 long long int64g
; // 64-bit integer
262 GooString
*string
; // string
264 Array
*array
; // array
265 Dict
*dict
; // dictionary
266 Stream
*stream
; // stream
267 Ref ref
; // indirect reference
268 char *cmd
; // command
272 static int // number of each type of object
273 numAlloc
[numObjTypes
]; // currently allocated
277 //------------------------------------------------------------------------
279 //------------------------------------------------------------------------
283 inline int Object::arrayGetLength()
284 { OBJECT_TYPE_CHECK(objArray
); return array
->getLength(); }
286 inline void Object::arrayAdd(Object
*elem
)
287 { OBJECT_TYPE_CHECK(objArray
); array
->add(elem
); }
289 inline void Object::arrayRemove(int i
)
290 { OBJECT_TYPE_CHECK(objArray
); array
->remove(i
); }
292 inline Object
*Object::arrayGet(int i
, Object
*obj
, int recursion
= 0)
293 { OBJECT_TYPE_CHECK(objArray
); return array
->get(i
, obj
, recursion
); }
295 inline Object
*Object::arrayGetNF(int i
, Object
*obj
)
296 { OBJECT_TYPE_CHECK(objArray
); return array
->getNF(i
, obj
); }
298 //------------------------------------------------------------------------
300 //------------------------------------------------------------------------
304 inline int Object::dictGetLength()
305 { OBJECT_TYPE_CHECK(objDict
); return dict
->getLength(); }
307 inline void Object::dictAdd(char *key
, Object
*val
)
308 { OBJECT_TYPE_CHECK(objDict
); dict
->add(key
, val
); }
310 inline void Object::dictSet(const char *key
, Object
*val
)
311 { OBJECT_TYPE_CHECK(objDict
); dict
->set(key
, val
); }
313 inline GBool
Object::dictIs(const char *dictType
)
314 { OBJECT_TYPE_CHECK(objDict
); return dict
->is(dictType
); }
316 inline GBool
Object::isDict(const char *dictType
)
317 { return type
== objDict
&& dictIs(dictType
); }
319 inline Object
*Object::dictLookup(const char *key
, Object
*obj
, int recursion
)
320 { OBJECT_TYPE_CHECK(objDict
); return dict
->lookup(key
, obj
, recursion
); }
322 inline Object
*Object::dictLookupNF(const char *key
, Object
*obj
)
323 { OBJECT_TYPE_CHECK(objDict
); return dict
->lookupNF(key
, obj
); }
325 inline char *Object::dictGetKey(int i
)
326 { OBJECT_TYPE_CHECK(objDict
); return dict
->getKey(i
); }
328 inline Object
*Object::dictGetVal(int i
, Object
*obj
)
329 { OBJECT_TYPE_CHECK(objDict
); return dict
->getVal(i
, obj
); }
331 inline Object
*Object::dictGetValNF(int i
, Object
*obj
)
332 { OBJECT_TYPE_CHECK(objDict
); return dict
->getValNF(i
, obj
); }
334 //------------------------------------------------------------------------
336 //------------------------------------------------------------------------
340 inline GBool
Object::streamIs(const char *dictType
)
341 { OBJECT_TYPE_CHECK(objStream
); return stream
->getDict()->is(dictType
); }
343 inline GBool
Object::isStream(const char *dictType
)
344 { return type
== objStream
&& streamIs(dictType
); }
346 inline void Object::streamReset()
347 { OBJECT_TYPE_CHECK(objStream
); stream
->reset(); }
349 inline void Object::streamClose()
350 { OBJECT_TYPE_CHECK(objStream
); stream
->close(); }
352 inline int Object::streamGetChar()
353 { OBJECT_TYPE_CHECK(objStream
); return stream
->getChar(); }
355 inline int Object::streamGetChars(int nChars
, Guchar
*buffer
)
356 { OBJECT_TYPE_CHECK(objStream
); return stream
->doGetChars(nChars
, buffer
); }
358 inline int Object::streamLookChar()
359 { OBJECT_TYPE_CHECK(objStream
); return stream
->lookChar(); }
361 inline char *Object::streamGetLine(char *buf
, int size
)
362 { OBJECT_TYPE_CHECK(objStream
); return stream
->getLine(buf
, size
); }
364 inline Goffset
Object::streamGetPos()
365 { OBJECT_TYPE_CHECK(objStream
); return stream
->getPos(); }
367 inline void Object::streamSetPos(Goffset pos
, int dir
)
368 { OBJECT_TYPE_CHECK(objStream
); stream
->setPos(pos
, dir
); }
370 inline Dict
*Object::streamGetDict()
371 { OBJECT_TYPE_CHECK(objStream
); return stream
->getDict(); }