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 | |
42 | Object Object::copy() const |
43 | { |
44 | CHECK_NOT_DEAD; |
45 | |
46 | Object obj; |
47 | std::memcpy(dest: reinterpret_cast<void *>(&obj), src: this, n: 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(s: 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 | |
74 | Object Object::deepCopy() const |
75 | { |
76 | CHECK_NOT_DEAD; |
77 | |
78 | Object obj; |
79 | std::memcpy(dest: reinterpret_cast<void *>(&obj), src: this, n: 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(s: 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 | |
106 | Object Object::fetch(XRef *xref, int recursion) const |
107 | { |
108 | CHECK_NOT_DEAD; |
109 | |
110 | return (type == objRef && xref) ? xref->fetch(ref: ref, recursion) : copy(); |
111 | } |
112 | |
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(p: 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 | |
146 | const char *Object::getTypeName() const |
147 | { |
148 | return objTypeNames[type]; |
149 | } |
150 | |
151 | void Object::print(FILE *f) const |
152 | { |
153 | int i; |
154 | |
155 | switch (type) { |
156 | case objBool: |
157 | fprintf(stream: f, format: "%s" , booln ? "true" : "false" ); |
158 | break; |
159 | case objInt: |
160 | fprintf(stream: f, format: "%d" , intg); |
161 | break; |
162 | case objReal: |
163 | fprintf(stream: f, format: "%g" , real); |
164 | break; |
165 | case objString: |
166 | fprintf(stream: f, format: "(" ); |
167 | fwrite(ptr: string->c_str(), size: 1, n: string->getLength(), s: f); |
168 | fprintf(stream: f, format: ")" ); |
169 | break; |
170 | case objHexString: |
171 | fprintf(stream: f, format: "<" ); |
172 | for (i = 0; i < string->getLength(); i++) { |
173 | fprintf(stream: f, format: "%02x" , string->getChar(i) & 0xff); |
174 | } |
175 | fprintf(stream: f, format: ">" ); |
176 | break; |
177 | case objName: |
178 | fprintf(stream: f, format: "/%s" , cString); |
179 | break; |
180 | case objNull: |
181 | fprintf(stream: f, format: "null" ); |
182 | break; |
183 | case objArray: |
184 | fprintf(stream: f, format: "[" ); |
185 | for (i = 0; i < arrayGetLength(); ++i) { |
186 | if (i > 0) { |
187 | fprintf(stream: f, format: " " ); |
188 | } |
189 | const Object &obj = arrayGetNF(i); |
190 | obj.print(f); |
191 | } |
192 | fprintf(stream: f, format: "]" ); |
193 | break; |
194 | case objDict: |
195 | fprintf(stream: f, format: "<<" ); |
196 | for (i = 0; i < dictGetLength(); ++i) { |
197 | fprintf(stream: f, format: " /%s " , dictGetKey(i)); |
198 | const Object &obj = dictGetValNF(i); |
199 | obj.print(f); |
200 | } |
201 | fprintf(stream: f, format: " >>" ); |
202 | break; |
203 | case objStream: |
204 | fprintf(stream: f, format: "<stream>" ); |
205 | break; |
206 | case objRef: |
207 | fprintf(stream: f, format: "%d %d R" , ref.num, ref.gen); |
208 | break; |
209 | case objCmd: |
210 | fprintf(stream: f, format: "%s" , cString); |
211 | break; |
212 | case objError: |
213 | fprintf(stream: f, format: "<error>" ); |
214 | break; |
215 | case objEOF: |
216 | fprintf(stream: f, format: "<EOF>" ); |
217 | break; |
218 | case objNone: |
219 | fprintf(stream: f, format: "<none>" ); |
220 | break; |
221 | case objDead: |
222 | fprintf(stream: f, format: "<dead>" ); |
223 | break; |
224 | case objInt64: |
225 | fprintf(stream: f, format: "%lld" , int64g); |
226 | break; |
227 | } |
228 | } |
229 | |