1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** Pictbridge Application */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_pictbridge.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_pictbridge_object_parse PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function parses a XML based pictbridge object. */
45 /* */
46 /* INPUT */
47 /* */
48 /* pictbridge Pictbridge instance */
49 /* xml_object_buffer Pointer to object buffer */
50 /* xml_object_length Length of the object */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* _ux_pictbridge_object_get */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
68 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
69 /* resulting in version 6.1 */
70 /* */
71 /**************************************************************************/
_ux_pictbridge_object_parse(UX_PICTBRIDGE * pictbridge,UCHAR * xml_object_buffer,ULONG xml_object_length)72 UINT _ux_pictbridge_object_parse(UX_PICTBRIDGE *pictbridge, UCHAR *xml_object_buffer,
73 ULONG xml_object_length)
74 {
75 UX_PICTBRIDGE_XML_ITEM *tag_item;
76 UX_PICTBRIDGE_XML_ITEM *tag_entry = UX_NULL;
77 UCHAR tag_name[UX_PICTBRIDGE_MAX_TAG_SIZE];
78 UCHAR variable_name[UX_PICTBRIDGE_MAX_VARIABLE_SIZE];
79 UCHAR variable_string[UX_PICTBRIDGE_MAX_STRING_SIZE];
80 UCHAR xml_parameter[UX_PICTBRIDGE_MAX_STRING_SIZE];
81 UX_PICTBRIDGE_XML_ITEM *tag_history[UX_PICTBRIDGE_MAX_TAG_DEPTH];
82 ULONG tag_history_index;
83 ULONG tag_flag;
84 ULONG closing_tag_count;
85 UINT tag_name_length;
86 UINT tag_history_length;
87 UINT status;
88
89 /* Set the tag position at root. */
90 tag_item = _ux_pictbridge_xml_item_root;
91
92 /* Clear the input tags. */
93 pictbridge -> ux_pictbridge_input_tags = 0;
94
95 /* Clear the input request. */
96 pictbridge -> ux_pictbridge_input_request = 0;
97
98 /* Tag history index is at root. */
99 tag_history_index = 0;
100
101 /* Closing tag count is reset. */
102 closing_tag_count = 0;
103
104 /* This variable remains untouched if the XML object's length is 0. */
105 status = UX_SUCCESS;
106
107 /* We parse the object until all items are parsed or there is a syntax error
108 or a short object. */
109 while(xml_object_length)
110 {
111
112 /* Scan the object buffer for a tag. */
113 status = _ux_pictbridge_tag_name_get(xml_object_buffer, xml_object_length, tag_name,
114 variable_name, variable_string, xml_parameter,
115 &xml_object_buffer, &xml_object_length, &tag_flag);
116
117 /* We may have an error. Check if this is an empty line in which case we are done. */
118 if (status != UX_SUCCESS)
119 {
120
121 /* Check for empty line. */
122 if (status == UX_PICTBRIDGE_ERROR_EMPTY_LINE)
123
124 /* Yes, we have an empty line. Do not proceed but we have a successful completion. */
125 status = UX_SUCCESS;
126
127 /* Do not proceed. */
128 break;
129 }
130
131 /* Check if this is a closing tag ? */
132 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_CLOSING)
133 {
134
135 /* Assume the worst. */
136 status = UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR;
137
138 /* Ensure we do not have a closing tag without a prior normal tag entry. */
139 if (tag_history_index == 0)
140
141 /* Syntax error. */
142 break;
143
144 /* One step back in the tag history. */
145 tag_history_index--;
146
147 /* Calculate the length of the tag item. */
148 status = _ux_utility_string_length_check(tag_name, &tag_name_length, UX_PICTBRIDGE_MAX_TAG_SIZE);
149 if (status != UX_SUCCESS)
150
151 /* Bad name, we should never here if _tag_name_get is OK. */
152 break;
153
154 /* Calculate the length of the current tag name in the tag history. */
155 status = _ux_utility_string_length_check(tag_history[tag_history_index] -> ux_pictbridge_xml_item_tag_name, &tag_history_length, UX_PICTBRIDGE_MAX_TAG_SIZE);
156 if (status != UX_SUCCESS)
157
158 /* Bad name, we should never here if _tag_name_get is OK. */
159 return(status);
160
161 /* If both length do not match, no need to check for a match. */
162 if (tag_history_length == tag_name_length)
163 {
164
165 /* Both length match, we may have a tag match. Check the names */
166 if (_ux_utility_memory_compare(tag_name, tag_history[tag_history_index] -> ux_pictbridge_xml_item_tag_name,
167 tag_name_length) != UX_SUCCESS)
168
169 /* Syntax error. */
170 break;
171 }
172 else
173
174 /* Syntax error. */
175 break;
176
177 /* Increment the closing tag count. */
178 closing_tag_count++;
179
180 /* If we have more than one closing tag consecutively, look for the parent. */
181 if (closing_tag_count > 1)
182 {
183
184 /* Get the parent for this item and set it as the current tag_item. We may already be at the root. */
185 if (tag_entry -> ux_pictbridge_xml_item_parent != UX_NULL)
186
187 /* We have a parent, set it. */
188 tag_item = tag_entry -> ux_pictbridge_xml_item_parent;
189 }
190
191 /* We set status to success. */
192 status = UX_SUCCESS;
193
194 }
195 else
196 {
197
198 /* The tag name is in the tag_name variable but has not been verified yet. */
199 status = _ux_pictbridge_tag_name_scan(tag_item, tag_name, &tag_entry);
200
201 /* We may have an error. */
202 if (status != UX_SUCCESS)
203
204 /* Do not proceed. */
205 break;
206
207 /* Check if this is a comment tag ? */
208 if ((tag_flag & UX_PICTBRIDGE_TAG_FLAG_COMMENT) == 0)
209 {
210
211 /* Reset the closing tag count. */
212 closing_tag_count = 0;
213
214 /* Save the current tag in the tag history. */
215 tag_history[tag_history_index] = tag_entry;
216
217 /* Increase the current tag index. */
218 tag_history_index++;
219
220 /* Check if there is a main tag specified in the tag entry. */
221 if (tag_entry -> ux_pictbridge_xml_item_tag_code != 0)
222 {
223
224 /* If this is a leaf, the tag is not a main request but a variable to be returned. */
225 if (tag_entry -> ux_pictbridge_xml_item_child == UX_PICTBRIDGE_XML_LEAF)
226
227 /* This is a variable. Add it to the other ones. */
228 pictbridge -> ux_pictbridge_input_tags |= tag_entry -> ux_pictbridge_xml_item_tag_code;
229
230 else
231
232 /* Yes we have a tag code, memorize it. This is a main input request. */
233 pictbridge -> ux_pictbridge_input_request = tag_entry -> ux_pictbridge_xml_item_tag_code;
234 }
235 /* We may have a function associated with this tag. Do a sanity check. */
236 if (tag_entry -> ux_pictbridge_xml_item_function != UX_NULL)
237 {
238 /* There is a function associated, so call it. */
239 status = tag_entry -> ux_pictbridge_xml_item_function(pictbridge, variable_name, variable_string, xml_parameter);
240
241 /* We may have an error. */
242 if (status != UX_SUCCESS)
243
244 /* Do not proceed. */
245 break;
246 }
247
248 /* Check if the tag has a child attached to it.
249 If there is neither a child or a function, it means we do not treat this tag name. */
250 if (tag_entry -> ux_pictbridge_xml_item_child != UX_NULL && tag_entry -> ux_pictbridge_xml_item_child != UX_PICTBRIDGE_XML_LEAF)
251 {
252
253 /* We have a child, set it. */
254 tag_item = tag_entry -> ux_pictbridge_xml_item_child;
255
256 /* Reset the tag codes. */
257 pictbridge -> ux_pictbridge_input_tags = 0;
258 }
259
260 /* Check if this is a self closing tag ? */
261 if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_SELF_CLOSING)
262 {
263
264 /* Assume the worst. */
265 status = UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR;
266
267 /* Ensure we do not have a closing tag without a prior normal tag entry. */
268 if (tag_history_index == 0)
269
270 /* Syntax error. */
271 break;
272
273 /* One step back in the tag history. */
274 tag_history_index--;
275
276 /* Calculate the length of the tag item. */
277 status = _ux_utility_string_length_check(tag_name, &tag_name_length, UX_PICTBRIDGE_MAX_TAG_SIZE);
278 if (status != UX_SUCCESS)
279
280 /* Bad name, we should never here if _tag_name_scan is OK! */
281 break;
282
283 /* Calculate the length of the current tag name in the tag history. */
284 status = _ux_utility_string_length_check(tag_history[tag_history_index] -> ux_pictbridge_xml_item_tag_name, &tag_history_length, UX_PICTBRIDGE_MAX_TAG_SIZE);
285 if (status != UX_SUCCESS)
286
287 /* Bad name, we should never here if _tag_name_scan is OK! */
288 break;
289
290 /* If both length do not match, no need to check for a match. */
291 if (tag_history_length == tag_name_length)
292 {
293
294 /* Both length match, we may have a tag match. Check the names */
295 if (_ux_utility_memory_compare(tag_name, tag_history[tag_history_index] -> ux_pictbridge_xml_item_tag_name,
296 tag_name_length) != UX_SUCCESS)
297
298 /* Syntax error. */
299 break;
300 }
301 else
302
303 /* Syntax error. */
304 break;
305
306 /* Increment the closing tag count. */
307 closing_tag_count++;
308
309 /* We set status to success. */
310 status = UX_SUCCESS;
311
312 }
313 }
314 }
315 }
316
317 /* Return completion status. */
318 return(status);
319 }
320
321