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// Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com>
24//
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
27//
28//========================================================================
29
30#ifndef OBJECT_H
31#define OBJECT_H
32
33#ifdef USE_GCC_PRAGMAS
34#pragma interface
35#endif
36
37#include <set>
38#include <stdio.h>
39#include <string.h>
40#include "goo/gtypes.h"
41#include "goo/gmem.h"
42#include "goo/GooString.h"
43#include "goo/GooLikely.h"
44#include "Error.h"
45
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); \
50 abort(); \
51 }
52
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); \
57 abort(); \
58 }
59
60class XRef;
61class Array;
62class Dict;
63class Stream;
64
65//------------------------------------------------------------------------
66// Ref
67//------------------------------------------------------------------------
68
69struct Ref {
70 int num; // object number
71 int gen; // generation number
72};
73
74//------------------------------------------------------------------------
75// object types
76//------------------------------------------------------------------------
77
78enum ObjType {
79 // simple objects
80 objBool, // boolean
81 objInt, // integer
82 objReal, // real
83 objString, // string
84 objName, // name
85 objNull, // null
86
87 // complex objects
88 objArray, // array
89 objDict, // dictionary
90 objStream, // stream
91 objRef, // indirect reference
92
93 // special objects
94 objCmd, // command name
95 objError, // error return from Lexer
96 objEOF, // end of file return from Lexer
97 objNone, // uninitialized object
98
99 // poppler-only objects
100 objInt64 // integer with at least 64-bits
101};
102
103#define numObjTypes 15 // total number of object types
104
105//------------------------------------------------------------------------
106// Object
107//------------------------------------------------------------------------
108
109#ifdef DEBUG_MEM
110#define initObj(t) zeroUnion(); ++numAlloc[type = t]
111#else
112#define initObj(t) zeroUnion(); type = t
113#endif
114
115class Object {
116public:
117 // clear the anonymous union as best we can -- clear at least a pointer
118 void zeroUnion() { this->name = NULL; }
119
120 // Default constructor.
121 Object():
122 type(objNone) { zeroUnion(); }
123
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; }
135 Object *initNull()
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(char *cmdA)
144 { initObj(objCmd); cmd = copyString(cmdA); return this; }
145 Object *initError()
146 { initObj(objError); return this; }
147 Object *initEOF()
148 { initObj(objEOF); return this; }
149 Object *initInt64(long long int64gA)
150 { initObj(objInt64); int64g = int64gA; return this; }
151
152 // Copy an object.
153 Object *copy(Object *obj);
154 Object *shallowCopy(Object *obj) {
155 *obj = *this;
156 return obj;
157 }
158
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);
162
163 // Free object contents.
164 void free();
165
166 // Type checking.
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; }
184
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(char *dictType);
190 GBool isCmd(const char *cmdA)
191 { return type == objCmd && !strcmp(cmd, cmdA); }
192
193 // Accessors.
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; }
197
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; }
216
217 // Array accessors.
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);
223
224 // Dict accessors.
225 int dictGetLength();
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);
234
235 // Stream accessors.
236 GBool streamIs(char *dictType);
237 void streamReset();
238 void streamClose();
239 int streamGetChar();
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();
246
247 // Output.
248 const char *getTypeName();
249 void print(FILE *f = stdout);
250
251 // Memory testing.
252 static void memCheck(FILE *f);
253
254private:
255
256 ObjType type; // object type
257 union { // value for each type:
258 GBool booln; // boolean
259 int intg; // integer
260 long long int64g; // 64-bit integer
261 double real; // real
262 GooString *string; // string
263 char *name; // name
264 Array *array; // array
265 Dict *dict; // dictionary
266 Stream *stream; // stream
267 Ref ref; // indirect reference
268 char *cmd; // command
269 };
270
271#ifdef DEBUG_MEM
272 static int // number of each type of object
273 numAlloc[numObjTypes]; // currently allocated
274#endif
275};
276
277//------------------------------------------------------------------------
278// Array accessors.
279//------------------------------------------------------------------------
280
281#include "Array.h"
282
283inline int Object::arrayGetLength()
284 { OBJECT_TYPE_CHECK(objArray); return array->getLength(); }
285
286inline void Object::arrayAdd(Object *elem)
287 { OBJECT_TYPE_CHECK(objArray); array->add(elem); }
288
289inline void Object::arrayRemove(int i)
290 { OBJECT_TYPE_CHECK(objArray); array->remove(i); }
291
292inline Object *Object::arrayGet(int i, Object *obj, int recursion = 0)
293 { OBJECT_TYPE_CHECK(objArray); return array->get(i, obj, recursion); }
294
295inline Object *Object::arrayGetNF(int i, Object *obj)
296 { OBJECT_TYPE_CHECK(objArray); return array->getNF(i, obj); }
297
298//------------------------------------------------------------------------
299// Dict accessors.
300//------------------------------------------------------------------------
301
302#include "Dict.h"
303
304inline int Object::dictGetLength()
305 { OBJECT_TYPE_CHECK(objDict); return dict->getLength(); }
306
307inline void Object::dictAdd(char *key, Object *val)
308 { OBJECT_TYPE_CHECK(objDict); dict->add(key, val); }
309
310inline void Object::dictSet(const char *key, Object *val)
311 { OBJECT_TYPE_CHECK(objDict); dict->set(key, val); }
312
313inline GBool Object::dictIs(const char *dictType)
314 { OBJECT_TYPE_CHECK(objDict); return dict->is(dictType); }
315
316inline GBool Object::isDict(const char *dictType)
317 { return type == objDict && dictIs(dictType); }
318
319inline Object *Object::dictLookup(const char *key, Object *obj, int recursion)
320 { OBJECT_TYPE_CHECK(objDict); return dict->lookup(key, obj, recursion); }
321
322inline Object *Object::dictLookupNF(const char *key, Object *obj)
323 { OBJECT_TYPE_CHECK(objDict); return dict->lookupNF(key, obj); }
324
325inline char *Object::dictGetKey(int i)
326 { OBJECT_TYPE_CHECK(objDict); return dict->getKey(i); }
327
328inline Object *Object::dictGetVal(int i, Object *obj)
329 { OBJECT_TYPE_CHECK(objDict); return dict->getVal(i, obj); }
330
331inline Object *Object::dictGetValNF(int i, Object *obj)
332 { OBJECT_TYPE_CHECK(objDict); return dict->getValNF(i, obj); }
333
334//------------------------------------------------------------------------
335// Stream accessors.
336//------------------------------------------------------------------------
337
338#include "Stream.h"
339
340inline GBool Object::streamIs(char *dictType)
341 { OBJECT_TYPE_CHECK(objStream); return stream->getDict()->is(dictType); }
342
343inline GBool Object::isStream(char *dictType)
344 { return type == objStream && streamIs(dictType); }
345
346inline void Object::streamReset()
347 { OBJECT_TYPE_CHECK(objStream); stream->reset(); }
348
349inline void Object::streamClose()
350 { OBJECT_TYPE_CHECK(objStream); stream->close(); }
351
352inline int Object::streamGetChar()
353 { OBJECT_TYPE_CHECK(objStream); return stream->getChar(); }
354
355inline int Object::streamGetChars(int nChars, Guchar *buffer)
356 { OBJECT_TYPE_CHECK(objStream); return stream->doGetChars(nChars, buffer); }
357
358inline int Object::streamLookChar()
359 { OBJECT_TYPE_CHECK(objStream); return stream->lookChar(); }
360
361inline char *Object::streamGetLine(char *buf, int size)
362 { OBJECT_TYPE_CHECK(objStream); return stream->getLine(buf, size); }
363
364inline Goffset Object::streamGetPos()
365 { OBJECT_TYPE_CHECK(objStream); return stream->getPos(); }
366
367inline void Object::streamSetPos(Goffset pos, int dir)
368 { OBJECT_TYPE_CHECK(objStream); stream->setPos(pos, dir); }
369
370inline Dict *Object::streamGetDict()
371 { OBJECT_TYPE_CHECK(objStream); return stream->getDict(); }
372
373#endif
374