1 // Copyright 2016 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/parser/xfa_basic_data.h"
8
9 #include <iterator>
10 #include <utility>
11
12 #include "core/fxcrt/span.h"
13 #include "fxjs/xfa/cjx_boolean.h"
14 #include "fxjs/xfa/cjx_container.h"
15 #include "fxjs/xfa/cjx_datawindow.h"
16 #include "fxjs/xfa/cjx_delta.h"
17 #include "fxjs/xfa/cjx_desc.h"
18 #include "fxjs/xfa/cjx_draw.h"
19 #include "fxjs/xfa/cjx_encrypt.h"
20 #include "fxjs/xfa/cjx_eventpseudomodel.h"
21 #include "fxjs/xfa/cjx_exclgroup.h"
22 #include "fxjs/xfa/cjx_extras.h"
23 #include "fxjs/xfa/cjx_field.h"
24 #include "fxjs/xfa/cjx_form.h"
25 #include "fxjs/xfa/cjx_handler.h"
26 #include "fxjs/xfa/cjx_hostpseudomodel.h"
27 #include "fxjs/xfa/cjx_instancemanager.h"
28 #include "fxjs/xfa/cjx_layoutpseudomodel.h"
29 #include "fxjs/xfa/cjx_logpseudomodel.h"
30 #include "fxjs/xfa/cjx_manifest.h"
31 #include "fxjs/xfa/cjx_model.h"
32 #include "fxjs/xfa/cjx_node.h"
33 #include "fxjs/xfa/cjx_occur.h"
34 #include "fxjs/xfa/cjx_packet.h"
35 #include "fxjs/xfa/cjx_script.h"
36 #include "fxjs/xfa/cjx_signaturepseudomodel.h"
37 #include "fxjs/xfa/cjx_source.h"
38 #include "fxjs/xfa/cjx_subform.h"
39 #include "fxjs/xfa/cjx_textnode.h"
40 #include "fxjs/xfa/cjx_tree.h"
41 #include "fxjs/xfa/cjx_treelist.h"
42 #include "fxjs/xfa/cjx_wsdlconnection.h"
43 #include "fxjs/xfa/cjx_xfa.h"
44 #include "xfa/fxfa/fxfa_basic.h"
45
46 namespace {
47
48 struct PacketTableRecord {
49 uint32_t hash;
50 XFA_PACKETINFO info;
51 };
52
53 const PacketTableRecord kPacketTable[] = {
54 #undef PCKT____
55 #define PCKT____(a, b, c, d, e, f) \
56 {a, {XFA_PacketType::c, XFA_PacketMatch::e, XFA_PacketSupport::f, b, d}},
57 #include "xfa/fxfa/parser/packets.inc"
58 #undef PCKT____
59 };
60
61 constexpr pdfium::span<const PacketTableRecord> kPacketSpan{kPacketTable};
62
63 struct ElementRecord {
64 uint32_t hash; // Hashed as wide string.
65 XFA_Element element;
66 XFA_Element parent;
67 };
68
69 // Contains read-only data that do not require relocation.
70 // Parts that require relocation are in `kElementNames` below.
71 constexpr ElementRecord kElementRecords[] = {
72 #undef ELEM____
73 #define ELEM____(a, b, c, d) {a, XFA_Element::c, XFA_Element::d},
74 #include "xfa/fxfa/parser/elements.inc"
75 #undef ELEM____
76 };
77
78 constexpr pdfium::span<const ElementRecord> kElementRecordSpan{kElementRecords};
79
80 constexpr const char* kElementNames[] = {
81 #undef ELEM____
82 #define ELEM____(a, b, c, d) b,
83 #include "xfa/fxfa/parser/elements.inc"
84 #undef ELEM____
85 };
86
87 constexpr const pdfium::span<const char* const> kElementNameSpan{kElementNames};
88
89 static_assert(std::size(kElementRecords) == std::size(kElementNames),
90 "Size mismatch");
91
92 struct AttributeRecord {
93 uint32_t hash; // Hashed as wide string.
94 XFA_Attribute attribute;
95 XFA_ScriptType script_type;
96 };
97
98 // Contains read-only data that do not require relocation.
99 // Parts that require relocation are in `kAttributeNames` below.
100 constexpr AttributeRecord kAttributeRecords[] = {
101 #undef ATTR____
102 #define ATTR____(a, b, c, d) {a, XFA_Attribute::c, XFA_ScriptType::d},
103 #include "xfa/fxfa/parser/attributes.inc"
104 #undef ATTR____
105 };
106
107 constexpr pdfium::span<const AttributeRecord> kAttributeRecordSpan{
108 kAttributeRecords};
109
110 constexpr const char* kAttributeNames[] = {
111 #undef ATTR____
112 #define ATTR____(a, b, c, d) b,
113 #include "xfa/fxfa/parser/attributes.inc"
114 #undef ATTR____
115 };
116
117 constexpr pdfium::span<const char* const> kAttributeNameSpan{kAttributeNames};
118
119 static_assert(std::size(kAttributeRecords) == std::size(kAttributeNames),
120 "Size mismatch");
121
122 struct AttributeValueRecord {
123 // Associated entry in `kAttributeValueNames` hashed as WideString.
124 uint32_t uHash;
125 XFA_AttributeValue eName;
126 };
127
128 // Contains read-only data that do not require relocation.
129 // Parts that require relocation are in `kAttributeValueNames` below.
130 constexpr AttributeValueRecord kAttributeValueRecords[] = {
131 #undef VALUE____
132 #define VALUE____(a, b, c) {a, XFA_AttributeValue::c},
133 #include "xfa/fxfa/parser/attribute_values.inc"
134 #undef VALUE____
135 };
136
137 constexpr const char* kAttributeValueNames[] = {
138 #undef VALUE____
139 #define VALUE____(a, b, c) b,
140 #include "xfa/fxfa/parser/attribute_values.inc"
141 #undef VALUE____
142 };
143
144 constexpr pdfium::span<const char* const> kAttributeValueNameSpan{
145 kAttributeValueNames};
146
147 static_assert(std::size(kAttributeValueRecords) ==
148 std::size(kAttributeValueNames),
149 "Size mismatch");
150
151 struct ElementAttributeRecord {
152 XFA_Element element;
153 XFA_Attribute attribute;
154 };
155
156 // Contains read-only data that do not require relocation.
157 // Parts that require relocation are in `kElementAttributeCallbacks` below.
158 constexpr ElementAttributeRecord kElementAttributeRecords[] = {
159 #undef ELEM_ATTR____
160 #define ELEM_ATTR____(a, b, c) {XFA_Element::a, XFA_Attribute::b},
161 #include "xfa/fxfa/parser/element_attributes.inc"
162 #undef ELEM_ATTR____
163 };
164
165 constexpr XFA_ATTRIBUTE_CALLBACK kElementAttributeCallbacks[] = {
166 #undef ELEM_ATTR____
167 #define ELEM_ATTR____(a, b, c) c##_static,
168 #include "xfa/fxfa/parser/element_attributes.inc"
169 #undef ELEM_ATTR____
170 };
171
172 constexpr pdfium::span<const XFA_ATTRIBUTE_CALLBACK>
173 kElementAttributeCallbackSpan{kElementAttributeCallbacks};
174
175 static_assert(std::size(kElementAttributeRecords) ==
176 std::size(kElementAttributeCallbacks),
177 "Size mismatch");
178
179 } // namespace
180
XFA_GetPacketByIndex(XFA_PacketType ePacket)181 XFA_PACKETINFO XFA_GetPacketByIndex(XFA_PacketType ePacket) {
182 return kPacketSpan[static_cast<uint8_t>(ePacket)].info;
183 }
184
XFA_GetPacketByName(WideStringView wsName)185 std::optional<XFA_PACKETINFO> XFA_GetPacketByName(WideStringView wsName) {
186 uint32_t hash = FX_HashCode_GetW(wsName);
187 auto* elem = std::lower_bound(
188 std::begin(kPacketTable), std::end(kPacketTable), hash,
189 [](const PacketTableRecord& a, uint32_t hash) { return a.hash < hash; });
190 if (elem != std::end(kPacketTable) && wsName.EqualsASCII(elem->info.name))
191 return elem->info;
192 return std::nullopt;
193 }
194
XFA_ElementToName(XFA_Element elem)195 ByteStringView XFA_ElementToName(XFA_Element elem) {
196 return kElementNameSpan[static_cast<size_t>(elem)];
197 }
198
XFA_GetElementByName(WideStringView name)199 XFA_Element XFA_GetElementByName(WideStringView name) {
200 uint32_t hash = FX_HashCode_GetW(name);
201 auto* elem = std::lower_bound(
202 std::begin(kElementRecords), std::end(kElementRecords), hash,
203 [](const ElementRecord& a, uint32_t hash) { return a.hash < hash; });
204 if (elem == std::end(kElementRecords))
205 return XFA_Element::Unknown;
206
207 size_t index = std::distance(std::begin(kElementRecords), elem);
208 return name.EqualsASCII(kElementNameSpan[index]) ? elem->element
209 : XFA_Element::Unknown;
210 }
211
XFA_AttributeToName(XFA_Attribute attr)212 ByteStringView XFA_AttributeToName(XFA_Attribute attr) {
213 return kAttributeNameSpan[static_cast<size_t>(attr)];
214 }
215
XFA_GetAttributeByName(WideStringView name)216 std::optional<XFA_ATTRIBUTEINFO> XFA_GetAttributeByName(WideStringView name) {
217 uint32_t hash = FX_HashCode_GetW(name);
218 auto* elem = std::lower_bound(
219 kAttributeRecordSpan.begin(), kAttributeRecordSpan.end(), hash,
220 [](const AttributeRecord& a, uint32_t hash) { return a.hash < hash; });
221 if (elem == kAttributeRecordSpan.end()) {
222 return std::nullopt;
223 }
224 size_t index = std::distance(kAttributeRecordSpan.begin(), elem);
225 if (!name.EqualsASCII(kAttributeNameSpan[index])) {
226 return std::nullopt;
227 }
228 XFA_ATTRIBUTEINFO result;
229 result.attribute = elem->attribute;
230 result.eValueType = elem->script_type;
231 return result;
232 }
233
XFA_AttributeValueToName(XFA_AttributeValue item)234 ByteStringView XFA_AttributeValueToName(XFA_AttributeValue item) {
235 return kAttributeValueNameSpan[static_cast<int32_t>(item)];
236 }
237
XFA_GetAttributeValueByName(WideStringView name)238 std::optional<XFA_AttributeValue> XFA_GetAttributeValueByName(
239 WideStringView name) {
240 auto* it =
241 std::lower_bound(std::begin(kAttributeValueRecords),
242 std::end(kAttributeValueRecords), FX_HashCode_GetW(name),
243 [](const AttributeValueRecord& arg, uint32_t hash) {
244 return arg.uHash < hash;
245 });
246 if (it == std::end(kAttributeValueRecords))
247 return std::nullopt;
248
249 size_t index = std::distance(std::begin(kAttributeValueRecords), it);
250 if (!name.EqualsASCII(kAttributeValueNameSpan[index])) {
251 return std::nullopt;
252 }
253
254 return it->eName;
255 }
256
XFA_GetScriptAttributeByName(XFA_Element element,WideStringView attribute_name)257 std::optional<XFA_SCRIPTATTRIBUTEINFO> XFA_GetScriptAttributeByName(
258 XFA_Element element,
259 WideStringView attribute_name) {
260 std::optional<XFA_ATTRIBUTEINFO> attr =
261 XFA_GetAttributeByName(attribute_name);
262 if (!attr.has_value())
263 return std::nullopt;
264
265 while (element != XFA_Element::Unknown) {
266 auto compound_key = std::make_pair(element, attr.value().attribute);
267 auto* it = std::lower_bound(
268 std::begin(kElementAttributeRecords),
269 std::end(kElementAttributeRecords), compound_key,
270 [](const ElementAttributeRecord& arg,
271 const std::pair<XFA_Element, XFA_Attribute>& key) {
272 return std::make_pair(arg.element, arg.attribute) < key;
273 });
274 if (it != std::end(kElementAttributeRecords) &&
275 compound_key == std::make_pair(it->element, it->attribute)) {
276 XFA_SCRIPTATTRIBUTEINFO result;
277 result.attribute = attr.value().attribute;
278 result.eValueType = attr.value().eValueType;
279 size_t index = std::distance(std::begin(kElementAttributeRecords), it);
280 result.callback = kElementAttributeCallbackSpan[index];
281 return result;
282 }
283 element = kElementRecordSpan[static_cast<size_t>(element)].parent;
284 }
285 return std::nullopt;
286 }
287