Line data Source code
1 : /* File: draw_stereotype_image.c; Copyright and License: see below */
2 :
3 : #include "draw_svg_path_data.h"
4 : #include "draw/draw_stereotype_image.h"
5 : #include "pencil_layout_data.h"
6 : #include "u8/u8_trace.h"
7 : #include "utf8stringbuf/utf8stringbuf.h"
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 : #include <assert.h>
11 :
12 : const double DRAW_STEREOTYPE_IMAGE_WIDTH_TO_HEIGHT = 1.0;
13 :
14 0 : u8_error_t draw_stereotype_image_draw ( const draw_stereotype_image_t *this_,
15 : const char *stereotype,
16 : const data_profile_part_t *profile,
17 : const GdkRGBA *default_color,
18 : u8_error_info_t *out_err_info,
19 : const geometry_rectangle_t *bounds,
20 : cairo_t *cr )
21 : {
22 0 : U8_TRACE_BEGIN();
23 0 : assert( NULL != stereotype );
24 0 : assert( NULL != profile );
25 0 : assert( NULL != out_err_info );
26 0 : assert( NULL != bounds );
27 0 : assert( NULL != cr );
28 0 : u8_error_t result = U8_ERROR_NONE;
29 0 : u8_error_info_init_void( out_err_info );
30 :
31 0 : const utf8stringview_t stereotype_view = UTF8STRINGVIEW_STR(stereotype);
32 : const data_classifier_t *const optional_stereotype
33 0 : = data_profile_part_get_stereotype_by_name_const( profile, &stereotype_view );
34 0 : if ( optional_stereotype != NULL )
35 : {
36 0 : U8_TRACE_INFO_STR( "stereotype", stereotype );
37 0 : const char *const drawing_directives = data_classifier_get_description_const( optional_stereotype );
38 : geometry_rectangle_t io_view_rect;
39 0 : geometry_rectangle_init_empty( &io_view_rect );
40 0 : result |= draw_stereotype_image_private_parse_svg_xml( this_,
41 : false, /* draw */
42 : drawing_directives,
43 : &io_view_rect,
44 : default_color,
45 : out_err_info,
46 : bounds,
47 : cr
48 : );
49 0 : if ( result == U8_ERROR_NONE )
50 : {
51 : /* make view rect quadratic */
52 0 : const double view_width = geometry_rectangle_get_width( &io_view_rect );
53 0 : const double view_height = geometry_rectangle_get_height( &io_view_rect );
54 0 : if ( view_width > view_height)
55 : {
56 0 : geometry_rectangle_set_top( &io_view_rect, geometry_rectangle_get_top( &io_view_rect ) - 0.5*(view_width-view_height) );
57 0 : geometry_rectangle_set_height( &io_view_rect, view_width );
58 : }
59 : else
60 : {
61 0 : geometry_rectangle_set_left( &io_view_rect, geometry_rectangle_get_left( &io_view_rect ) - 0.5*(view_height-view_width) );
62 0 : geometry_rectangle_set_width( &io_view_rect, view_height );
63 : }
64 0 : result |= draw_stereotype_image_private_parse_svg_xml( this_,
65 : true, /* draw */
66 : drawing_directives,
67 : &io_view_rect,
68 : default_color,
69 : out_err_info,
70 : bounds,
71 : cr
72 : );
73 : }
74 :
75 0 : geometry_rectangle_destroy( &io_view_rect );
76 : }
77 : else
78 : {
79 0 : result = U8_ERROR_NOT_FOUND;
80 : }
81 :
82 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
83 : /* draw the rectangle */
84 : {
85 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
86 0 : cairo_rectangle ( cr,
87 : geometry_rectangle_get_left ( bounds ),
88 : geometry_rectangle_get_top ( bounds ),
89 : geometry_rectangle_get_width ( bounds ),
90 : geometry_rectangle_get_height ( bounds )
91 : );
92 0 : cairo_stroke (cr);
93 0 : cairo_set_source_rgba( cr, (*default_color).red, (*default_color).green, (*default_color).blue, (*default_color).alpha );
94 : }
95 : #endif
96 :
97 0 : U8_TRACE_END_ERR(result);
98 0 : return result;
99 : }
100 :
101 : /*! \brief states of parsing svg, the xml parts */
102 : enum draw_stereotype_image_xml_enum {
103 : DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH, /*!< nothing passed yet */
104 : DRAW_STEREOTYPE_IMAGE_XML_TAG_STARTED, /*!< XML tag start passed */
105 : DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG, /*!< XML token path passed */
106 : DRAW_STEREOTYPE_IMAGE_XML_D_ATTR, /*!< XML attribute d: name passed */
107 : DRAW_STEREOTYPE_IMAGE_XML_D_DEF, /*!< XML attribute d: assignment passed */
108 : DRAW_STEREOTYPE_IMAGE_XML_FILL_ATTR, /*!< XML attribute fill: name passed, see svg spec 13.2. Specifying paint */
109 : DRAW_STEREOTYPE_IMAGE_XML_FILL_DEF, /*!< XML attribute fill: assignment passed */
110 : DRAW_STEREOTYPE_IMAGE_XML_FILL_VALUE, /*!< XML attribute fill: single or double quotes passed */
111 : DRAW_STEREOTYPE_IMAGE_XML_STROKE_ATTR, /*!< XML attribute stroke: name passed, see svg spec 13.2. Specifying paint */
112 : DRAW_STEREOTYPE_IMAGE_XML_STROKE_DEF, /*!< XML attribute stroke: assignment passed */
113 : DRAW_STEREOTYPE_IMAGE_XML_STROKE_VALUE, /*!< XML attribute stroke: single or double quotes passed */
114 : DRAW_STEREOTYPE_IMAGE_XML_INSIDE_SGLQ_VALUE, /*!< single-quoted XML attribute-value of any other attribute-name */
115 : DRAW_STEREOTYPE_IMAGE_XML_INSIDE_DBLQ_VALUE, /*!< double-quoted XML attribute-value of any other attribute-name */
116 : };
117 :
118 29 : u8_error_t draw_stereotype_image_private_parse_svg_xml ( const draw_stereotype_image_t *this_,
119 : bool draw,
120 : const char *drawing_directives,
121 : geometry_rectangle_t *io_view_rect,
122 : const GdkRGBA *default_color,
123 : u8_error_info_t *out_err_info,
124 : const geometry_rectangle_t *target_bounds,
125 : cairo_t *cr )
126 : {
127 29 : U8_TRACE_BEGIN();
128 29 : assert( NULL != drawing_directives );
129 29 : assert( NULL != io_view_rect );
130 29 : assert( NULL != out_err_info );
131 29 : assert( NULL != target_bounds );
132 29 : assert( ( ! draw ) || ( NULL != cr ) );
133 29 : u8_error_t result = U8_ERROR_NONE;
134 :
135 : /* states while parsing: */
136 29 : enum draw_stereotype_image_xml_enum parser_state = DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH;
137 29 : uint_fast16_t path_count = 0;
138 29 : GdkRGBA stroke_color = *default_color;
139 29 : GdkRGBA fill_color = { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 0.0 };
140 : char xml_attr_value_buf[64]; /* max 4 floating point numbers and rgba(%,%,%,%) string around */
141 29 : utf8stringbuf_t xml_attr_value = UTF8STRINGBUF(xml_attr_value_buf);
142 :
143 29 : const utf8stringview_t drawing_directives_view = UTF8STRINGVIEW_STR( drawing_directives );
144 : utf8stringviewtokenizer_t tok_iterator;
145 29 : utf8stringviewtokenizer_init( &tok_iterator, &drawing_directives_view, UTF8STRINGVIEWTOKENMODE_TEXT );
146 214 : while( utf8stringviewtokenizer_has_next( &tok_iterator ) && ( result == U8_ERROR_NONE ) )
147 : {
148 185 : const utf8stringview_t tok = utf8stringviewtokenizer_next( &tok_iterator );
149 185 : assert( utf8stringview_get_length( &tok ) > 0 ); /* otherwise this would not be a token */
150 : /* U8_TRACE_INFO_VIEW( "token:", tok ); */
151 :
152 185 : switch ( parser_state )
153 : {
154 31 : case DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH:
155 : {
156 31 : if ( utf8stringview_equals_str( &tok, "<" ) )
157 : {
158 28 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_TAG_STARTED;
159 : }
160 : }
161 31 : break;
162 :
163 28 : case DRAW_STEREOTYPE_IMAGE_XML_TAG_STARTED:
164 : {
165 28 : if ( utf8stringview_equals_str( &tok, "path" ) )
166 : {
167 : /* for each new path, reset the colors to defaults */
168 28 : stroke_color = *default_color;
169 28 : fill_color = (GdkRGBA) { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 0.0 };
170 28 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
171 : }
172 : else
173 : {
174 : /* no error, accept anythig here: */
175 : /* not a path tag, back to ouside state */
176 : /* TODO accept a namespace for the path maybe? */
177 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH;
178 : }
179 : }
180 28 : break;
181 :
182 70 : case DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG:
183 : {
184 70 : if ( utf8stringview_equals_str( &tok, "d" ) )
185 : {
186 28 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_D_ATTR;
187 : }
188 42 : else if ( utf8stringview_equals_str( &tok, "stroke" ) )
189 : {
190 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_STROKE_ATTR;
191 : }
192 42 : else if ( utf8stringview_equals_str( &tok, "fill" ) )
193 : {
194 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_FILL_ATTR;
195 : }
196 42 : else if ( utf8stringview_equals_str( &tok, "\'" ) )
197 : {
198 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_SGLQ_VALUE;
199 : }
200 42 : else if ( utf8stringview_equals_str( &tok, "\"" ) )
201 : {
202 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_DBLQ_VALUE;
203 : }
204 42 : else if ( utf8stringview_equals_str( &tok, "/" ) )
205 : {
206 : /* ignore */
207 : }
208 21 : else if ( utf8stringview_equals_str( &tok, ">" ) )
209 : {
210 21 : if ( draw )
211 : {
212 0 : assert( NULL != cr );
213 : /* fill and stroke */
214 0 : if ( fill_color.alpha > 0.01 )
215 : {
216 0 : if ( stroke_color.alpha > 0.01 )
217 : {
218 0 : cairo_set_source_rgba( cr, fill_color.red, fill_color.green, fill_color.blue, fill_color.alpha );
219 0 : cairo_fill_preserve( cr );
220 0 : cairo_set_source_rgba( cr, stroke_color.red, stroke_color.green, stroke_color.blue, stroke_color.alpha );
221 0 : cairo_stroke( cr );
222 : }
223 : else
224 : {
225 0 : cairo_set_source_rgba( cr, fill_color.red, fill_color.green, fill_color.blue, fill_color.alpha );
226 0 : cairo_fill( cr );
227 : }
228 : }
229 : else
230 : {
231 0 : cairo_set_source_rgba( cr, stroke_color.red, stroke_color.green, stroke_color.blue, stroke_color.alpha );
232 0 : cairo_stroke( cr );
233 : }
234 : }
235 : /* end of path tag */
236 21 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH;
237 : }
238 : }
239 70 : break;
240 :
241 28 : case DRAW_STEREOTYPE_IMAGE_XML_D_ATTR:
242 : {
243 28 : if ( utf8stringview_equals_str( &tok, "=" ) )
244 : {
245 28 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_D_DEF;
246 : }
247 : else
248 : {
249 : /* this is an error */
250 : /* TODO the tokenizer may have split a token, e.g. d:pre-d-post */
251 : /* A possible fix is to implement a token mode for XML-NM-Tokens */
252 0 : result |= U8_ERROR_PARSER_STRUCTURE;
253 0 : u8_error_info_init_line( out_err_info,
254 : U8_ERROR_PARSER_STRUCTURE,
255 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
256 : );
257 :
258 : /* not a d attribute, back to inside path state */
259 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
260 : }
261 : }
262 28 : break;
263 :
264 28 : case DRAW_STEREOTYPE_IMAGE_XML_D_DEF:
265 : {
266 28 : if (( utf8stringview_equals_str( &tok, "\"" ) )||( utf8stringview_equals_str( &tok, "\'" ) ))
267 28 : {
268 : /* process draw commands in sub statemachine */
269 28 : utf8stringviewtokenizer_set_mode( &tok_iterator, UTF8STRINGVIEWTOKENMODE_FLOAT_ONLY );
270 : draw_svg_path_data_t svg_path_data;
271 28 : draw_svg_path_data_init( &svg_path_data );
272 28 : if ( draw )
273 : {
274 0 : result |= draw_svg_path_data_draw( &svg_path_data,
275 : &tok_iterator,
276 : io_view_rect,
277 : out_err_info,
278 : target_bounds,
279 : cr
280 : );
281 : }
282 : else
283 : {
284 : geometry_rectangle_t path_view_rect;
285 28 : geometry_rectangle_init_empty( &path_view_rect );
286 28 : result |= draw_svg_path_data_parse_bounds( &svg_path_data,
287 : &tok_iterator,
288 : &path_view_rect,
289 : out_err_info
290 : );
291 28 : if ( path_count == 0 )
292 : {
293 28 : geometry_rectangle_replace( io_view_rect, &path_view_rect );
294 : }
295 : else
296 : {
297 0 : geometry_rectangle_init_by_bounds( io_view_rect, io_view_rect, &path_view_rect );
298 : }
299 28 : geometry_rectangle_destroy( &path_view_rect );
300 : }
301 28 : draw_svg_path_data_destroy( &svg_path_data );
302 28 : utf8stringviewtokenizer_set_mode( &tok_iterator, UTF8STRINGVIEWTOKENMODE_TEXT );
303 28 : path_count ++;
304 : }
305 : else
306 : {
307 : /* this is an error */
308 0 : result |= U8_ERROR_PARSER_STRUCTURE;
309 0 : u8_error_info_init_line( out_err_info,
310 : U8_ERROR_PARSER_STRUCTURE,
311 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
312 : );
313 : }
314 : /* back to inside path state */
315 28 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
316 : }
317 28 : break;
318 :
319 0 : case DRAW_STEREOTYPE_IMAGE_XML_STROKE_ATTR:
320 : {
321 0 : if ( utf8stringview_equals_str( &tok, "=" ) )
322 : {
323 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_STROKE_DEF;
324 : }
325 : else
326 : {
327 : /* this is an error */
328 : /* TODO the tokenizer may have split a token, e.g. stroke:pre-stroke-post */
329 : /* A possible fix is to implement a token mode for XML-NM-Tokens */
330 0 : result |= U8_ERROR_PARSER_STRUCTURE;
331 0 : u8_error_info_init_line( out_err_info,
332 : U8_ERROR_PARSER_STRUCTURE,
333 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
334 : );
335 :
336 : /* not a stroke attribute, back to inside path state */
337 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
338 : }
339 : }
340 0 : break;
341 :
342 0 : case DRAW_STEREOTYPE_IMAGE_XML_STROKE_DEF:
343 : {
344 0 : if (( utf8stringview_equals_str( &tok, "\"" ) )||( utf8stringview_equals_str( &tok, "\'" ) ))
345 : {
346 : /* end of the value of another, ignored tag */
347 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_STROKE_VALUE;
348 0 : utf8stringbuf_clear( xml_attr_value );
349 : }
350 : else
351 : {
352 : /* this is an error */
353 0 : result |= U8_ERROR_PARSER_STRUCTURE;
354 0 : u8_error_info_init_line( out_err_info,
355 : U8_ERROR_PARSER_STRUCTURE,
356 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
357 : );
358 :
359 : /* not a stroke attribute, back to inside path state */
360 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
361 : }
362 : }
363 0 : break;
364 :
365 0 : case DRAW_STEREOTYPE_IMAGE_XML_STROKE_VALUE:
366 : {
367 0 : if (( utf8stringview_equals_str( &tok, "\"" ) )||( utf8stringview_equals_str( &tok, "\'" ) ))
368 : {
369 : /* parse the color */
370 0 : if ( utf8stringbuf_equals_str( xml_attr_value, "none" ) )
371 : {
372 0 : stroke_color = (GdkRGBA) { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 0.0 };
373 : }
374 : else
375 : {
376 0 : U8_TRACE_INFO_STR( "stroke:", utf8stringbuf_get_string( xml_attr_value ) );
377 0 : const gboolean success = gdk_rgba_parse( &stroke_color, utf8stringbuf_get_string( xml_attr_value ) );
378 0 : if ( ! success )
379 : {
380 0 : result |= U8_ERROR_PARSER_STRUCTURE;
381 0 : u8_error_info_init_line( out_err_info,
382 : U8_ERROR_PARSER_STRUCTURE,
383 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
384 : );
385 : }
386 : }
387 : /* end of the value of fill tag */
388 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
389 : }
390 : else
391 : {
392 0 : utf8stringbuf_append_view( xml_attr_value, &tok );
393 : }
394 : }
395 0 : break;
396 :
397 0 : case DRAW_STEREOTYPE_IMAGE_XML_FILL_ATTR:
398 : {
399 0 : if ( utf8stringview_equals_str( &tok, "=" ) )
400 : {
401 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_FILL_DEF;
402 : }
403 : else
404 : {
405 : /* this is an error */
406 : /* TODO the tokenizer may have split a token, e.g. fill:pre-fill-post */
407 : /* A possible fix is to implement a token mode for XML-NM-Tokens */
408 0 : result |= U8_ERROR_PARSER_STRUCTURE;
409 0 : u8_error_info_init_line( out_err_info,
410 : U8_ERROR_PARSER_STRUCTURE,
411 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
412 : );
413 :
414 : /* not a fill attribute, back to inside path state */
415 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
416 : }
417 : }
418 0 : break;
419 :
420 0 : case DRAW_STEREOTYPE_IMAGE_XML_FILL_DEF:
421 : {
422 0 : if (( utf8stringview_equals_str( &tok, "\"" ) )||( utf8stringview_equals_str( &tok, "\'" ) ))
423 : {
424 : /* end of the value of another, ignored tag */
425 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_FILL_VALUE;
426 0 : utf8stringbuf_clear( xml_attr_value );
427 : }
428 : else
429 : {
430 : /* this is an error */
431 0 : result |= U8_ERROR_PARSER_STRUCTURE;
432 0 : u8_error_info_init_line( out_err_info,
433 : U8_ERROR_PARSER_STRUCTURE,
434 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
435 : );
436 :
437 : /* not a stroke attribute, back to inside path state */
438 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
439 : }
440 : }
441 0 : break;
442 :
443 0 : case DRAW_STEREOTYPE_IMAGE_XML_FILL_VALUE:
444 : {
445 0 : if (( utf8stringview_equals_str( &tok, "\"" ) )||( utf8stringview_equals_str( &tok, "\'" ) ))
446 : {
447 : /* parse the color */
448 0 : if ( utf8stringbuf_equals_str( xml_attr_value, "none" ) )
449 : {
450 0 : fill_color = (GdkRGBA) { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 0.0 };
451 : }
452 : else
453 : {
454 0 : U8_TRACE_INFO_STR( "fill:", utf8stringbuf_get_string( xml_attr_value ) );
455 0 : const gboolean success = gdk_rgba_parse( &fill_color, utf8stringbuf_get_string( xml_attr_value ) );
456 0 : if ( ! success )
457 : {
458 0 : result |= U8_ERROR_PARSER_STRUCTURE;
459 0 : u8_error_info_init_line( out_err_info,
460 : U8_ERROR_PARSER_STRUCTURE,
461 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
462 : );
463 : }
464 : }
465 : /* end of the value of fill tag */
466 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
467 : }
468 : else
469 : {
470 0 : utf8stringbuf_append_view( xml_attr_value, &tok );
471 : }
472 : }
473 0 : break;
474 :
475 0 : case DRAW_STEREOTYPE_IMAGE_XML_INSIDE_SGLQ_VALUE:
476 : {
477 0 : if ( utf8stringview_equals_str( &tok, "\'" ) )
478 : {
479 : /* end of the value of another, ignored tag */
480 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
481 : }
482 : /*
483 : else
484 : {
485 : U8_TRACE_INFO_VIEW( "other single-quoted:", tok );
486 : }
487 : */
488 : }
489 0 : break;
490 :
491 0 : case DRAW_STEREOTYPE_IMAGE_XML_INSIDE_DBLQ_VALUE:
492 : {
493 0 : if ( utf8stringview_equals_str( &tok, "\"" ) )
494 : {
495 : /* end of the value of another, ignored tag */
496 0 : parser_state = DRAW_STEREOTYPE_IMAGE_XML_INSIDE_PATH_TAG;
497 : }
498 : /*
499 : else
500 : {
501 : U8_TRACE_INFO_VIEW( "other double-quoted:", tok );
502 : }
503 : */
504 : }
505 0 : break;
506 : }
507 : }
508 :
509 : /* report error on unfinished drawing */
510 29 : if (( result == U8_ERROR_NONE )&&( parser_state != DRAW_STEREOTYPE_IMAGE_XML_OUTSIDE_PATH ))
511 : {
512 0 : result |= U8_ERROR_PARSER_STRUCTURE;
513 : /* if no other error encountered yet, report this one: */
514 0 : if ( ! u8_error_info_is_error( out_err_info ) )
515 : {
516 0 : u8_error_info_init_line( out_err_info,
517 : U8_ERROR_PARSER_STRUCTURE,
518 0 : utf8stringviewtokenizer_get_line( &tok_iterator )
519 : );
520 : }
521 : }
522 :
523 : /* check if anything was drawn at all */
524 29 : if ( path_count == 0 )
525 : {
526 1 : result |= U8_ERROR_NOT_FOUND;
527 : }
528 :
529 29 : utf8stringviewtokenizer_destroy( &tok_iterator );
530 29 : U8_TRACE_END_ERR(result);
531 29 : return result;
532 : }
533 :
534 :
535 : /*
536 : Copyright 2023-2024 Andreas Warnke
537 : http://www.apache.org/licenses/LICENSE-2.0
538 :
539 : Licensed under the Apache License, Version 2.0 (the "License");
540 : you may not use this file except in compliance with the License.
541 : You may obtain a copy of the License at
542 :
543 :
544 : Unless required by applicable law or agreed to in writing, software
545 : distributed under the License is distributed on an "AS IS" BASIS,
546 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
547 : See the License for the specific language governing permissions and
548 : limitations under the License.
549 : */
|