1 //========================================================================
2 //
3 // Object.cc
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) 2008, 2010, 2012, 2017, 2019 Albert Astals Cid <aacid@kde.org>
17 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
18 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
19 // Copyright (C) 2020 Jakub Alba <jakubalba@gmail.com>
20 //
21 // To see a description of the changes please see the Changelog file that
22 // came with your tarball or type make ChangeLog if you are building from git
23 //
24 //========================================================================
25 
26 #include <config.h>
27 
28 #include <cstddef>
29 #include "Object.h"
30 #include "Array.h"
31 #include "Dict.h"
32 #include "Error.h"
33 #include "Stream.h"
34 #include "XRef.h"
35 
36 //------------------------------------------------------------------------
37 // Object
38 //------------------------------------------------------------------------
39 
40 static const char *objTypeNames[numObjTypes] = { "boolean", "integer", "real", "string", "name", "null", "array", "dictionary", "stream", "ref", "cmd", "error", "eof", "none", "integer64", "hexString", "dead" };
41 
copy() const42 Object Object::copy() const
43 {
44     CHECK_NOT_DEAD;
45 
46     Object obj;
47     std::memcpy(reinterpret_cast<void *>(&obj), this, sizeof(Object));
48 
49     switch (type) {
50     case objString:
51     case objHexString:
52         obj.string = string->copy();
53         break;
54     case objName:
55     case objCmd:
56         obj.cString = copyString(cString);
57         break;
58     case objArray:
59         array->incRef();
60         break;
61     case objDict:
62         dict->incRef();
63         break;
64     case objStream:
65         stream->incRef();
66         break;
67     default:
68         break;
69     }
70 
71     return obj;
72 }
73 
deepCopy() const74 Object Object::deepCopy() const
75 {
76     CHECK_NOT_DEAD;
77 
78     Object obj;
79     std::memcpy(reinterpret_cast<void *>(&obj), this, sizeof(Object));
80 
81     switch (type) {
82     case objString:
83     case objHexString:
84         obj.string = string->copy();
85         break;
86     case objName:
87     case objCmd:
88         obj.cString = copyString(cString);
89         break;
90     case objArray:
91         obj.array = array->deepCopy();
92         break;
93     case objDict:
94         obj.dict = dict->deepCopy();
95         break;
96     case objStream:
97         stream->incRef();
98         break;
99     default:
100         break;
101     }
102 
103     return obj;
104 }
105 
fetch(XRef * xref,int recursion) const106 Object Object::fetch(XRef *xref, int recursion) const
107 {
108     CHECK_NOT_DEAD;
109 
110     return (type == objRef && xref) ? xref->fetch(ref, recursion) : copy();
111 }
112 
free()113 void Object::free()
114 {
115     switch (type) {
116     case objString:
117     case objHexString:
118 
119         delete string;
120         break;
121     case objName:
122     case objCmd:
123         gfree(cString);
124         break;
125     case objArray:
126         if (!array->decRef()) {
127             delete array;
128         }
129         break;
130     case objDict:
131         if (!dict->decRef()) {
132             delete dict;
133         }
134         break;
135     case objStream:
136         if (!stream->decRef()) {
137             delete stream;
138         }
139         break;
140     default:
141         break;
142     }
143     type = objNone;
144 }
145 
getTypeName() const146 const char *Object::getTypeName() const
147 {
148     return objTypeNames[type];
149 }
150 
print(FILE * f) const151 void Object::print(FILE *f) const
152 {
153     int i;
154 
155     switch (type) {
156     case objBool:
157         fprintf(f, "%s", booln ? "true" : "false");
158         break;
159     case objInt:
160         fprintf(f, "%d", intg);
161         break;
162     case objReal:
163         fprintf(f, "%g", real);
164         break;
165     case objString:
166         fprintf(f, "(");
167         fwrite(string->c_str(), 1, string->getLength(), f);
168         fprintf(f, ")");
169         break;
170     case objHexString:
171         fprintf(f, "<");
172         for (i = 0; i < string->getLength(); i++) {
173             fprintf(f, "%02x", string->getChar(i) & 0xff);
174         }
175         fprintf(f, ">");
176         break;
177     case objName:
178         fprintf(f, "/%s", cString);
179         break;
180     case objNull:
181         fprintf(f, "null");
182         break;
183     case objArray:
184         fprintf(f, "[");
185         for (i = 0; i < arrayGetLength(); ++i) {
186             if (i > 0)
187                 fprintf(f, " ");
188             const Object &obj = arrayGetNF(i);
189             obj.print(f);
190         }
191         fprintf(f, "]");
192         break;
193     case objDict:
194         fprintf(f, "<<");
195         for (i = 0; i < dictGetLength(); ++i) {
196             fprintf(f, " /%s ", dictGetKey(i));
197             const Object &obj = dictGetValNF(i);
198             obj.print(f);
199         }
200         fprintf(f, " >>");
201         break;
202     case objStream:
203         fprintf(f, "<stream>");
204         break;
205     case objRef:
206         fprintf(f, "%d %d R", ref.num, ref.gen);
207         break;
208     case objCmd:
209         fprintf(f, "%s", cString);
210         break;
211     case objError:
212         fprintf(f, "<error>");
213         break;
214     case objEOF:
215         fprintf(f, "<EOF>");
216         break;
217     case objNone:
218         fprintf(f, "<none>");
219         break;
220     case objDead:
221         fprintf(f, "<dead>");
222         break;
223     case objInt64:
224         fprintf(f, "%lld", int64g);
225         break;
226     }
227 }
228