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