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