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 Albert Astals Cid <aacid@kde.org>
19 : // Copyright (C) 2009 Jakub Wilk <ubanus@users.sf.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 : //
24 : // To see a description of the changes please see the Changelog file that
25 : // came with your tarball or type make ChangeLog if you are building from git
26 : //
27 : //========================================================================
28 :
29 : #ifndef OBJECT_H
30 : #define OBJECT_H
31 :
32 : #ifdef USE_GCC_PRAGMAS
33 : #pragma interface
34 : #endif
35 :
36 : #include <set>
37 : #include <stdio.h>
38 : #include <string.h>
39 : #include "goo/gtypes.h"
40 : #include "goo/gmem.h"
41 : #include "goo/GooString.h"
42 : #include "goo/GooLikely.h"
43 : #include "Error.h"
44 :
45 : #define OBJECT_TYPE_CHECK(wanted_type) \
46 : if (unlikely(type != wanted_type)) { \
47 : error(errInternal, 0, (char *) "Call to Object where the object was type {0:d}, " \
48 : "not the expected type {1:d}", type, wanted_type); \
49 : abort(); \
50 : }
51 :
52 : #define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \
53 : if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \
54 : error(errInternal, 0, (char *) "Call to Object where the object was type {0:d}, " \
55 : "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \
56 : abort(); \
57 : }
58 :
59 : class XRef;
60 : class Array;
61 : class Dict;
62 : class Stream;
63 :
64 : //------------------------------------------------------------------------
65 : // Ref
66 : //------------------------------------------------------------------------
67 :
68 : struct Ref {
69 : int num; // object number
70 : int gen; // generation number
71 : };
72 :
73 : //------------------------------------------------------------------------
74 : // object types
75 : //------------------------------------------------------------------------
76 :
77 : enum ObjType {
78 : // simple objects
79 : objBool, // boolean
80 : objInt, // integer
81 : objReal, // real
82 : objString, // string
83 : objName, // name
84 : objNull, // null
85 :
86 : // complex objects
87 : objArray, // array
88 : objDict, // dictionary
89 : objStream, // stream
90 : objRef, // indirect reference
91 :
92 : // special objects
93 : objCmd, // command name
94 : objError, // error return from Lexer
95 : objEOF, // end of file return from Lexer
96 : objNone, // uninitialized object
97 :
98 : // poppler-only objects
99 : objInt64 // integer with at least 64-bits
100 : };
101 :
102 : #define numObjTypes 15 // total number of object types
103 :
104 : //------------------------------------------------------------------------
105 : // Object
106 : //------------------------------------------------------------------------
107 :
108 : #ifdef DEBUG_MEM
109 : #define initObj(t) zeroUnion(); ++numAlloc[type = t]
110 : #else
111 : #define initObj(t) zeroUnion(); type = t
112 : #endif
113 :
114 : class Object {
115 : public:
116 : // clear the anonymous union as best we can -- clear at least a pointer
117 14161 : void zeroUnion() { this->name = NULL; }
118 :
119 : // Default constructor.
120 14012 : Object():
121 14012 : type(objNone) { zeroUnion(); }
122 :
123 : // Initialize an object.
124 : Object *initBool(GBool boolnA)
125 : { initObj(objBool); booln = boolnA; return this; }
126 : Object *initInt(int intgA)
127 : { initObj(objInt); intg = intgA; return this; }
128 : Object *initReal(double realA)
129 : { initObj(objReal); real = realA; return this; }
130 : Object *initString(GooString *stringA)
131 : { initObj(objString); string = stringA; return this; }
132 : Object *initName(const char *nameA)
133 : { initObj(objName); name = copyString(nameA); return this; }
134 149 : Object *initNull()
135 149 : { initObj(objNull); return this; }
136 : Object *initArray(XRef *xref);
137 : Object *initDict(XRef *xref);
138 : Object *initDict(Dict *dictA);
139 : Object *initStream(Stream *streamA);
140 : Object *initRef(int numA, int genA)
141 : { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
142 : Object *initCmd(char *cmdA)
143 : { initObj(objCmd); cmd = copyString(cmdA); return this; }
144 : Object *initError()
145 : { initObj(objError); return this; }
146 : Object *initEOF()
147 : { initObj(objEOF); return this; }
148 : Object *initInt64(long long int64gA)
149 : { initObj(objInt64); int64g = int64gA; return this; }
150 :
151 : // Copy an object.
152 : Object *copy(Object *obj);
153 : Object *shallowCopy(Object *obj) {
154 : *obj = *this;
155 : return obj;
156 : }
157 :
158 : // If object is a Ref, fetch and return the referenced object.
159 : // Otherwise, return a copy of the object.
160 : Object *fetch(XRef *xref, Object *obj, int recursion = 0);
161 :
162 : // Free object contents.
163 : void free();
164 :
165 : // Type checking.
166 55273 : ObjType getType() { return type; }
167 : GBool isBool() { return type == objBool; }
168 : GBool isInt() { return type == objInt; }
169 : GBool isReal() { return type == objReal; }
170 : GBool isNum() { return type == objInt || type == objReal || type == objInt64; }
171 : GBool isString() { return type == objString; }
172 : GBool isName() { return type == objName; }
173 9513 : GBool isNull() { return type == objNull; }
174 23 : GBool isArray() { return type == objArray; }
175 149 : GBool isDict() { return type == objDict; }
176 : GBool isStream() { return type == objStream; }
177 25072 : GBool isRef() { return type == objRef; }
178 : GBool isCmd() { return type == objCmd; }
179 : GBool isError() { return type == objError; }
180 : GBool isEOF() { return type == objEOF; }
181 : GBool isNone() { return type == objNone; }
182 : GBool isInt64() { return type == objInt64; }
183 :
184 : // Special type checking.
185 : GBool isName(const char *nameA)
186 : { return type == objName && !strcmp(name, nameA); }
187 : GBool isDict(const char *dictType);
188 : GBool isStream(char *dictType);
189 : GBool isCmd(const char *cmdA)
190 : { return type == objCmd && !strcmp(cmd, cmdA); }
191 :
192 : // Accessors.
193 0 : GBool getBool() { OBJECT_TYPE_CHECK(objBool); return booln; }
194 4384 : int getInt() { OBJECT_TYPE_CHECK(objInt); return intg; }
195 902 : double getReal() { OBJECT_TYPE_CHECK(objReal); return real; }
196 :
197 : // Note: integers larger than 2^53 can not be exactly represented by a double.
198 : // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
199 : double getNum() { OBJECT_3TYPES_CHECK(objInt, objInt64, objReal);
200 : return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; }
201 3796 : GooString *getString() { OBJECT_TYPE_CHECK(objString); return string; }
202 1307 : char *getName() { OBJECT_TYPE_CHECK(objName); return name; }
203 1089 : Array *getArray() { OBJECT_TYPE_CHECK(objArray); return array; }
204 3315 : Dict *getDict() { OBJECT_TYPE_CHECK(objDict); return dict; }
205 611 : Stream *getStream() { OBJECT_TYPE_CHECK(objStream); return stream; }
206 : Ref getRef() { OBJECT_TYPE_CHECK(objRef); return ref; }
207 1549 : int getRefNum() { OBJECT_TYPE_CHECK(objRef); return ref.num; }
208 1549 : int getRefGen() { OBJECT_TYPE_CHECK(objRef); return ref.gen; }
209 : char *getCmd() { OBJECT_TYPE_CHECK(objCmd); return cmd; }
210 : long long getInt64() { OBJECT_TYPE_CHECK(objInt64); return int64g; }
211 :
212 : // Array accessors.
213 : int arrayGetLength();
214 : void arrayAdd(Object *elem);
215 : void arrayRemove(int i);
216 : Object *arrayGet(int i, Object *obj, int recursion);
217 : Object *arrayGetNF(int i, Object *obj);
218 :
219 : // Dict accessors.
220 : int dictGetLength();
221 : void dictAdd(char *key, Object *val);
222 : void dictSet(const char *key, Object *val);
223 : GBool dictIs(const char *dictType);
224 : Object *dictLookup(const char *key, Object *obj, int recursion = 0);
225 : Object *dictLookupNF(const char *key, Object *obj);
226 : char *dictGetKey(int i);
227 : Object *dictGetVal(int i, Object *obj);
228 : Object *dictGetValNF(int i, Object *obj);
229 :
230 : // Stream accessors.
231 : GBool streamIs(char *dictType);
232 : void streamReset();
233 : void streamClose();
234 : int streamGetChar();
235 : int streamGetChars(int nChars, Guchar *buffer);
236 : int streamLookChar();
237 : char *streamGetLine(char *buf, int size);
238 : Goffset streamGetPos();
239 : void streamSetPos(Goffset pos, int dir = 0);
240 : Dict *streamGetDict();
241 :
242 : // Output.
243 : const char *getTypeName();
244 : void print(FILE *f = stdout);
245 :
246 : // Memory testing.
247 : static void memCheck(FILE *f);
248 :
249 : private:
250 :
251 : ObjType type; // object type
252 : union { // value for each type:
253 : GBool booln; // boolean
254 : int intg; // integer
255 : long long int64g; // 64-bit integer
256 : double real; // real
257 : GooString *string; // string
258 : char *name; // name
259 : Array *array; // array
260 : Dict *dict; // dictionary
261 : Stream *stream; // stream
262 : Ref ref; // indirect reference
263 : char *cmd; // command
264 : };
265 :
266 : #ifdef DEBUG_MEM
267 : static int // number of each type of object
268 : numAlloc[numObjTypes]; // currently allocated
269 : #endif
270 : };
271 :
272 : //------------------------------------------------------------------------
273 : // Array accessors.
274 : //------------------------------------------------------------------------
275 :
276 : #include "Array.h"
277 :
278 23 : inline int Object::arrayGetLength()
279 23 : { OBJECT_TYPE_CHECK(objArray); return array->getLength(); }
280 :
281 : inline void Object::arrayAdd(Object *elem)
282 : { OBJECT_TYPE_CHECK(objArray); array->add(elem); }
283 :
284 : inline void Object::arrayRemove(int i)
285 : { OBJECT_TYPE_CHECK(objArray); array->remove(i); }
286 :
287 : inline Object *Object::arrayGet(int i, Object *obj, int recursion = 0)
288 : { OBJECT_TYPE_CHECK(objArray); return array->get(i, obj, recursion); }
289 :
290 : inline Object *Object::arrayGetNF(int i, Object *obj)
291 : { OBJECT_TYPE_CHECK(objArray); return array->getNF(i, obj); }
292 :
293 : //------------------------------------------------------------------------
294 : // Dict accessors.
295 : //------------------------------------------------------------------------
296 :
297 : #include "Dict.h"
298 :
299 : inline int Object::dictGetLength()
300 : { OBJECT_TYPE_CHECK(objDict); return dict->getLength(); }
301 :
302 : inline void Object::dictAdd(char *key, Object *val)
303 : { OBJECT_TYPE_CHECK(objDict); dict->add(key, val); }
304 :
305 : inline void Object::dictSet(const char *key, Object *val)
306 : { OBJECT_TYPE_CHECK(objDict); dict->set(key, val); }
307 :
308 : inline GBool Object::dictIs(const char *dictType)
309 : { OBJECT_TYPE_CHECK(objDict); return dict->is(dictType); }
310 :
311 : inline GBool Object::isDict(const char *dictType)
312 : { return type == objDict && dictIs(dictType); }
313 :
314 : inline Object *Object::dictLookup(const char *key, Object *obj, int recursion)
315 : { OBJECT_TYPE_CHECK(objDict); return dict->lookup(key, obj, recursion); }
316 :
317 : inline Object *Object::dictLookupNF(const char *key, Object *obj)
318 : { OBJECT_TYPE_CHECK(objDict); return dict->lookupNF(key, obj); }
319 :
320 : inline char *Object::dictGetKey(int i)
321 : { OBJECT_TYPE_CHECK(objDict); return dict->getKey(i); }
322 :
323 : inline Object *Object::dictGetVal(int i, Object *obj)
324 : { OBJECT_TYPE_CHECK(objDict); return dict->getVal(i, obj); }
325 :
326 : inline Object *Object::dictGetValNF(int i, Object *obj)
327 : { OBJECT_TYPE_CHECK(objDict); return dict->getValNF(i, obj); }
328 :
329 : //------------------------------------------------------------------------
330 : // Stream accessors.
331 : //------------------------------------------------------------------------
332 :
333 : #include "Stream.h"
334 :
335 : inline GBool Object::streamIs(char *dictType)
336 : { OBJECT_TYPE_CHECK(objStream); return stream->getDict()->is(dictType); }
337 :
338 : inline GBool Object::isStream(char *dictType)
339 : { return type == objStream && streamIs(dictType); }
340 :
341 : inline void Object::streamReset()
342 : { OBJECT_TYPE_CHECK(objStream); stream->reset(); }
343 :
344 : inline void Object::streamClose()
345 : { OBJECT_TYPE_CHECK(objStream); stream->close(); }
346 :
347 : inline int Object::streamGetChar()
348 : { OBJECT_TYPE_CHECK(objStream); return stream->getChar(); }
349 :
350 : inline int Object::streamGetChars(int nChars, Guchar *buffer)
351 : { OBJECT_TYPE_CHECK(objStream); return stream->doGetChars(nChars, buffer); }
352 :
353 : inline int Object::streamLookChar()
354 : { OBJECT_TYPE_CHECK(objStream); return stream->lookChar(); }
355 :
356 : inline char *Object::streamGetLine(char *buf, int size)
357 : { OBJECT_TYPE_CHECK(objStream); return stream->getLine(buf, size); }
358 :
359 : inline Goffset Object::streamGetPos()
360 : { OBJECT_TYPE_CHECK(objStream); return stream->getPos(); }
361 :
362 : inline void Object::streamSetPos(Goffset pos, int dir)
363 : { OBJECT_TYPE_CHECK(objStream); stream->setPos(pos, dir); }
364 :
365 : inline Dict *Object::streamGetDict()
366 : { OBJECT_TYPE_CHECK(objStream); return stream->getDict(); }
367 :
368 : #endif
|