fix getsup (HH)
[luatex.git] / source / libs / poppler / poppler-src / poppler / Object.h
blob312a8eb32cbfa9ce6e50818e3706ebe97a6f8e68
1 //========================================================================
2 //
3 // Object.h
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
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 //========================================================================
31 #ifndef OBJECT_H
32 #define OBJECT_H
34 #ifdef USE_GCC_PRAGMAS
35 #pragma interface
36 #endif
38 #include <set>
39 #include <stdio.h>
40 #include <string.h>
41 #include "goo/gtypes.h"
42 #include "goo/gmem.h"
43 #include "goo/GooString.h"
44 #include "goo/GooLikely.h"
45 #include "Error.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); \
51 abort(); \
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); \
58 abort(); \
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); \
65 abort(); \
68 class XRef;
69 class Array;
70 class Dict;
71 class Stream;
73 //------------------------------------------------------------------------
74 // Ref
75 //------------------------------------------------------------------------
77 struct Ref {
78 int num; // object number
79 int gen; // generation number
82 //------------------------------------------------------------------------
83 // object types
84 //------------------------------------------------------------------------
86 enum ObjType {
87 // simple objects
88 objBool, // boolean
89 objInt, // integer
90 objReal, // real
91 objString, // string
92 objName, // name
93 objNull, // null
95 // complex objects
96 objArray, // array
97 objDict, // dictionary
98 objStream, // stream
99 objRef, // indirect reference
101 // special objects
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 //------------------------------------------------------------------------
114 // Object
115 //------------------------------------------------------------------------
117 #ifdef DEBUG_MEM
118 #define initObj(t) zeroUnion(); ++numAlloc[type = t]
119 #else
120 #define initObj(t) zeroUnion(); type = t
121 #endif
123 class Object {
124 public:
125 // clear the anonymous union as best we can -- clear at least a pointer
126 void zeroUnion() { this->name = NULL; }
128 // Default constructor.
129 Object():
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; }
143 Object *initNull()
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; }
153 Object *initError()
154 { initObj(objError); return this; }
155 Object *initEOF()
156 { initObj(objEOF); return this; }
157 Object *initInt64(long long int64gA)
158 { initObj(objInt64); int64g = int64gA; return this; }
160 // Copy an object.
161 Object *copy(Object *obj);
162 Object *shallowCopy(Object *obj) {
163 *obj = *this;
164 return 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.
172 void free();
174 // Type checking.
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); }
202 // Accessors.
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; }
228 // Array accessors.
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);
235 // Dict accessors.
236 int dictGetLength();
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);
247 // Stream accessors.
248 GBool streamIs(const char *dictType);
249 void streamReset();
250 void streamClose();
251 int streamGetChar();
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();
259 // Output.
260 const char *getTypeName();
261 void print(FILE *f = stdout);
263 // Memory testing.
264 static void memCheck(FILE *f);
266 private:
268 ObjType type; // object type
269 union { // value for each type:
270 GBool booln; // boolean
271 int intg; // integer
272 long long int64g; // 64-bit integer
273 double real; // real
274 GooString *string; // string
275 char *name; // name
276 Array *array; // array
277 Dict *dict; // dictionary
278 Stream *stream; // stream
279 Ref ref; // indirect reference
280 char *cmd; // command
283 #ifdef DEBUG_MEM
284 static int // number of each type of object
285 numAlloc[numObjTypes]; // currently allocated
286 #endif
289 //------------------------------------------------------------------------
290 // Array accessors.
291 //------------------------------------------------------------------------
293 #include "Array.h"
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 //------------------------------------------------------------------------
311 // Dict accessors.
312 //------------------------------------------------------------------------
314 #include "Dict.h"
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 //------------------------------------------------------------------------
350 // Stream accessors.
351 //------------------------------------------------------------------------
353 #include "Stream.h"
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(); }
388 #endif