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_tag_name_get PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function isolates a tag name from the XML script. */
45 /* */
46 /* Note: the buffer size of tag_name, variable_name, variable_string */
47 /* and xml_parameter must be equal to or greater than */
48 /* UX_PICTBRIDGE_MAX_TAG_SIZE, UX_PICTBRIDGE_MAX_VARIABLE_SIZE, */
49 /* UX_PICTBRIDGE_MAX_STRING_SIZE and UX_PICTBRIDGE_MAX_STRING_SIZE. */
50 /* */
51 /* INPUT */
52 /* */
53 /* input_buffer Pointer to object buffer */
54 /* input_length Length of the object */
55 /* tag_name Where to store the tag */
56 /* variable_name Variable name */
57 /* variable_string Variable string */
58 /* xml_parameter ML parameter */
59 /* output_buffer Pointer after the tag */
60 /* output_length Length of the object */
61 /* tag_flag flag specific to this tag */
62 /* */
63 /* OUTPUT */
64 /* */
65 /* Completion Status */
66 /* */
67 /* CALLS */
68 /* */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* _ux_pictbridge_object_parse */
73 /* */
74 /* RELEASE HISTORY */
75 /* */
76 /* DATE NAME DESCRIPTION */
77 /* */
78 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
79 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
80 /* verified memset and memcpy */
81 /* cases, */
82 /* resulting in version 6.1 */
83 /* */
84 /**************************************************************************/
_ux_pictbridge_tag_name_get(UCHAR * input_buffer,ULONG input_length,UCHAR * tag_name,UCHAR * variable_name,UCHAR * variable_string,UCHAR * xml_parameter,UCHAR ** output_buffer,ULONG * output_length,ULONG * tag_flag)85 UINT _ux_pictbridge_tag_name_get(UCHAR *input_buffer, ULONG input_length,
86 UCHAR *tag_name,
87 UCHAR *variable_name,
88 UCHAR *variable_string,
89 UCHAR *xml_parameter,
90 UCHAR **output_buffer, ULONG *output_length,
91 ULONG *tag_flag)
92 {
93 ULONG flag;
94 ULONG char_count;
95 UCHAR *tag_name_end;
96 UCHAR *variable_name_end;
97 UCHAR *variable_string_end;
98 UCHAR *xml_parameter_end;
99
100 /* Reset the local flags. */
101 flag = 0;
102
103 /* Reset the caller's tag_flag. */
104 *tag_flag = 0;
105
106 /* Char count reset. */
107 char_count = 0;
108
109 /* Reset the tag name buffer. */
110 _ux_utility_memory_set(tag_name, 0, UX_PICTBRIDGE_MAX_TAG_SIZE); /* Use case of memset is verified. */
111 tag_name_end = tag_name + UX_PICTBRIDGE_MAX_TAG_SIZE - 1;
112
113 /* Reset the variable name buffer. */
114 _ux_utility_memory_set(variable_name, 0, UX_PICTBRIDGE_MAX_VARIABLE_SIZE); /* Use case of memset is verified. */
115 variable_name_end = variable_name + UX_PICTBRIDGE_MAX_VARIABLE_SIZE - 1;
116
117 /* Reset the variable string buffer. */
118 _ux_utility_memory_set(variable_string, 0, UX_PICTBRIDGE_MAX_STRING_SIZE); /* Use case of memset is verified. */
119 variable_string_end = variable_string + UX_PICTBRIDGE_MAX_STRING_SIZE - 1;
120
121 /* Reset the xml parameter. */
122 _ux_utility_memory_set(xml_parameter, 0, UX_PICTBRIDGE_MAX_STRING_SIZE); /* Use case of memset is verified. */
123 xml_parameter_end = xml_parameter + UX_PICTBRIDGE_MAX_STRING_SIZE - 1;
124
125 /* We parse the current xml tag line. We are now positioned at the "<". */
126 while(input_length)
127 {
128 /* Get a character from the tag line. */
129 switch (*input_buffer)
130 {
131
132 case UX_PICTBRIDGE_TAG_CHAR_START_BRACKET :
133
134 /* Check to see if we are within a quote. */
135 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
136 {
137
138 /* Yes, store the bracket in the string. */
139 if (variable_string > variable_string_end)
140 return(UX_BUFFER_OVERFLOW);
141 *variable_string++ = *input_buffer;
142
143 break;
144 }
145
146 /* Check to see if we are already in the bracket. */
147 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
148
149 /* Yes, we have a syntax violation. */
150 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
151
152 else
153 /* Set the tag flag to start bracket. State machine is now in Tag. */
154 flag |= (UX_PICTBRIDGE_TAG_FLAG_BEGIN | UX_PICTBRIDGE_TAG_FLAG_IN_TAG);
155
156
157 break;
158
159
160 case UX_PICTBRIDGE_TAG_CHAR_CR :
161 case UX_PICTBRIDGE_TAG_CHAR_LF :
162
163 /* If we are in the middle of a <>, we have a format violation. If not, we may have an empty line. */
164 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
165
166 /* We have a XML tag violation. */
167 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
168 else
169 break;
170
171 case UX_PICTBRIDGE_TAG_CHAR_SPACE :
172
173 /* If we are within a tag already, this masks the end. If not, continue looking for
174 an open bracket. */
175 if ((flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN) == 0)
176 break;
177
178 /* Check to see if we are within a quote. */
179 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
180 {
181 /* Yes, store the character. */
182 if (variable_string > variable_string_end)
183 return(UX_BUFFER_OVERFLOW);
184 *variable_string++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
185
186 break;
187 }
188
189 /* If we are in the flag state machine. It marks the end of the flag and maybe the
190 beginning of a variable. */
191 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
192 {
193
194 /* get out of tag state machine. */
195 flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_TAG;
196
197 /* Change state machine to variable. */
198 flag |= (ULONG)UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE;
199
200 }
201 break;
202
203 case UX_PICTBRIDGE_TAG_CHAR_EQUAL :
204
205 /* If we are not within a bracket, this is a loose character ! */
206 if ((flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN) == 0)
207 break;
208
209 /* Check to see if we are within a string. */
210 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
211 {
212 /* Yes, store the character. */
213 if (variable_string > variable_string_end)
214 return(UX_BUFFER_OVERFLOW);
215 *variable_string++ = *input_buffer;
216
217 break;
218 }
219
220 /* If we are in the flag state machine we have an error. */
221 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
222
223 /* Error, we should have been in the variable state machine. */
224 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
225
226 /* If we are in the variable state machine, change the state to expecting string. */
227 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE)
228 {
229
230 /* Get out of the variable state machine. */
231 flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE;
232
233 /* Change state machine to expecting string. */
234 flag |= UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING;
235
236 }
237 break;
238
239 case UX_PICTBRIDGE_TAG_CHAR_QUOTE :
240
241 /* Are we in the string state machine ? */
242 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
243
244 /* Get out of the in string state machine. We are out of any state now. */
245 flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_STRING;
246
247 else
248 {
249
250 /* Are we expecting a string ? */
251 if (flag & UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING)
252 {
253
254 /* Get out of the expecting string state machine. */
255 flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING;
256
257 /* Change state machine to in string. */
258 flag |= UX_PICTBRIDGE_TAG_FLAG_IN_STRING;
259
260 }
261
262 else
263
264 /* Loose character ! */
265 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
266
267 }
268
269 break;
270
271 case UX_PICTBRIDGE_TAG_CHAR_SLASH :
272
273 /* If we are in no particular state at the moment, we could have a begin slash or end slash. */
274 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
275 {
276
277 /* We are in the variable string state machine. Store the "/" as a normal character. */
278 if (variable_string > variable_string_end)
279 return(UX_BUFFER_OVERFLOW);
280 *variable_string++ = *input_buffer;
281
282 break;
283 }
284 /* Check other states. */
285 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
286 {
287
288 /* We are in a tag. 2 scenario here. We are either at the beginning or at the end. */
289 if (char_count != 0)
290
291 /* We are at the end of the tag, this is a self closing tag. */
292 *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_SELF_CLOSING;
293
294 else
295
296 /* This is a normal closing tag. */
297 *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_CLOSING;
298
299 /* We are done here. */
300 break;
301 }
302
303 else
304 {
305
306 /* If we are out of any state machine, it must be a self closing tag. */
307 if (flag & (UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE | UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING))
308
309 /* This is a syntax error, abort. */
310 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
311
312 else
313 {
314 /* We are at the end of the tag, this is a self closing tag. */
315 *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_SELF_CLOSING;
316
317 /* We are done here. */
318 break;
319 }
320
321 }
322
323
324 case UX_PICTBRIDGE_TAG_CHAR_QUESTION_MARK :
325
326 /* If we are in no particular state at the moment, we could have a begin ? or end ?. */
327 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
328
329 /* We are within a quoted string, do not proceed. */
330 break;
331
332 else
333
334 /* This is a comment line, no need for a closing tag. */
335 *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_COMMENT;
336
337 break;
338
339 case UX_PICTBRIDGE_TAG_CHAR_END_BRACKET :
340
341 /* If we are in no particular state at the moment, we could have a begin ? or end ?. */
342 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
343 {
344
345 /* Yes, store the bracket in the string. */
346 if (variable_string > variable_string_end)
347 return(UX_BUFFER_OVERFLOW);
348 *variable_string++ = *input_buffer;
349
350 break;
351 }
352
353 /* Check if we are within a bracket. */
354 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
355 {
356
357 /* Skip the closing bracket. */
358 input_buffer++;
359
360 /* Update length. */
361 input_length--;
362
363 /* We may have a xml parameter between the current tag and its closing counterpart. */
364 while(input_length)
365 {
366
367 /* Get a character between the tag brackets. */
368 switch (*input_buffer)
369 {
370
371 case UX_PICTBRIDGE_TAG_CHAR_CR :
372 case UX_PICTBRIDGE_TAG_CHAR_LF :
373
374 /* Skip potential CR/LF. */
375 break;
376
377
378 case UX_PICTBRIDGE_TAG_CHAR_START_BRACKET :
379
380 /* We have found the beginning of the next tag.
381 Set the output buffer position to the next "<". */
382 *output_buffer = input_buffer;
383
384 /* Set the length remaining. */
385 *output_length = input_length;
386
387 /* We are done here. */
388 return(UX_SUCCESS);
389
390 default :
391
392 /* Whatever we have now, we store into the XML parameter. */
393 if (xml_parameter > xml_parameter_end)
394 return(UX_BUFFER_OVERFLOW);
395 *xml_parameter++ = *input_buffer;
396 break;
397
398 }
399
400 /* Next position. */
401 input_buffer++;
402
403 /* Update length. */
404 input_length--;
405
406 }
407
408 /* Set the output buffer position. */
409 *output_buffer = input_buffer;
410
411 /* Set the length remaining. */
412 *output_length = input_length;
413
414 /* We have reached the end of the xml object. */
415 return(UX_SUCCESS);
416
417 }
418 else
419
420 /* We have a syntax error. */
421 return(UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR);
422
423 default :
424
425 /* Check if we are within a bracket. */
426 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
427
428 /* Yes, increase the char count. This will tell us
429 if we are at the beginning of a tag or at the end. */
430 char_count++;
431
432 /* We have a regular character. Store it in the current state machine. */
433 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
434 {
435 /* We are in the tag state machine. */
436 if (tag_name > tag_name_end)
437 return(UX_BUFFER_OVERFLOW);
438 *tag_name++ = *input_buffer;
439 }
440
441 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE)
442 {
443 /* We are in the variable state machine. */
444 if (variable_name > variable_name_end)
445 return(UX_BUFFER_OVERFLOW);
446 *variable_name++ = *input_buffer;
447 }
448
449 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
450 {
451 /* We are in the variable string state machine. */
452 if (variable_string > variable_string_end)
453 return(UX_BUFFER_OVERFLOW);
454 *variable_string++ = *input_buffer;
455 }
456
457 break;
458
459 }
460
461 /* Next position. */
462 input_buffer++;
463
464 /* Update length. */
465 input_length--;
466
467 }
468
469 /* We get here when we reached an unexpected end of the XML object.
470 if we had a begin bracket, there is an unexpected end. If not, we
471 have an empty line. */
472 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
473
474 /* We have an error. */
475 return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
476
477 else
478
479 /* Not really an error, but we need to inform the caller there is no tag to process. */
480 return(UX_PICTBRIDGE_ERROR_EMPTY_LINE);
481
482 }
483
484