Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2021 James Westman <james@jwestman.net>
3 : : *
4 : : * This library is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * This library is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : : * Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with this library; if not, see <https://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : :
19 : : #include "shumate-vector-renderer.h"
20 : : #include "shumate-vector-expression-filter-private.h"
21 : : #include "shumate-vector-expression-interpolate-private.h"
22 : : #include "shumate-vector-expression-type-private.h"
23 : : #include "../shumate-vector-reader-iter.h"
24 : :
25 : : typedef enum {
26 : : GEOM_SINGLE_POINT = 1 << 0,
27 : : GEOM_MULTI_POINT = 1 << 1,
28 : : GEOM_SINGLE_LINESTRING = 1 << 2,
29 : : GEOM_MULTI_LINESTRING = 1 << 3,
30 : : GEOM_SINGLE_POLYGON = 1 << 4,
31 : : GEOM_MULTI_POLYGON = 1 << 5,
32 : : GEOM_ANY_POINT = GEOM_SINGLE_POINT | GEOM_MULTI_POINT,
33 : : GEOM_ANY_LINESTRING = GEOM_SINGLE_LINESTRING | GEOM_MULTI_LINESTRING,
34 : : GEOM_ANY_POLYGON = GEOM_SINGLE_POLYGON | GEOM_MULTI_POLYGON,
35 : : } GeometryTypeFlags;
36 : :
37 : : struct _ShumateVectorExpressionFilter
38 : : {
39 : : ShumateVectorExpression parent_instance;
40 : :
41 : : ExpressionType type;
42 : :
43 : : GPtrArray *expressions;
44 : :
45 : : union {
46 : : ShumateVectorValue value;
47 : : GPtrArray *format_parts;
48 : : char *fast_get_key;
49 : : GHashTable *match_expressions;
50 : : struct {
51 : : char *key;
52 : : GHashTable *haystack;
53 : : } fast_in;
54 : : struct {
55 : : ShumateVectorValue value;
56 : : char *key;
57 : : } fast_eq;
58 : : GeometryTypeFlags fast_geometry_type;
59 : : };
60 : : };
61 : :
62 : : typedef struct {
63 : : ShumateVectorExpression *string;
64 : : ShumateVectorExpression *font_scale;
65 : : ShumateVectorExpression *text_color;
66 : : } FormatExpressionPart;
67 : :
68 [ + + + - ]: 3582 : G_DEFINE_TYPE (ShumateVectorExpressionFilter, shumate_vector_expression_filter, SHUMATE_TYPE_VECTOR_EXPRESSION)
69 : :
70 : :
71 : : static void
72 : 15 : format_expression_part_free (FormatExpressionPart *part)
73 : : {
74 [ + - ]: 15 : g_clear_object (&part->string);
75 [ + + ]: 15 : g_clear_object (&part->font_scale);
76 [ + + ]: 15 : g_clear_object (&part->text_color);
77 : 15 : g_free (part);
78 : 15 : }
79 : : G_DEFINE_AUTOPTR_CLEANUP_FUNC (FormatExpressionPart, format_expression_part_free);
80 : :
81 : :
82 : : const ExprInfo *shumate_vector_expression_type_lookup (register const char *str, register size_t len);
83 : :
84 : :
85 : : static ShumateVectorExpression *optimize (ShumateVectorExpressionFilter *self);
86 : :
87 : :
88 : : ShumateVectorExpression *
89 : 1659 : shumate_vector_expression_filter_from_literal (ShumateVectorValue *value)
90 : : {
91 : 3318 : g_autoptr(ShumateVectorExpressionFilter) self = NULL;
92 : :
93 : 1659 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
94 : 1659 : self->type = EXPR_LITERAL;
95 : 1659 : shumate_vector_value_copy (value, &self->value);
96 : :
97 : 1659 : return (ShumateVectorExpression *)g_steal_pointer (&self);
98 : : }
99 : :
100 : :
101 : : ShumateVectorExpression *
102 : 1881 : shumate_vector_expression_filter_from_array_or_literal (JsonNode *node,
103 : : ShumateVectorExpressionContext *ctx,
104 : : GError **error)
105 : : {
106 [ + + + + ]: 1881 : if (node == NULL || JSON_NODE_HOLDS_NULL (node))
107 : 54 : return shumate_vector_expression_filter_from_literal (&SHUMATE_VECTOR_VALUE_INIT);
108 [ + + ]: 1827 : else if (JSON_NODE_HOLDS_VALUE (node))
109 : : {
110 : 1191 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
111 [ + - ]: 1191 : if (!shumate_vector_value_set_from_json_literal (&value, node, error))
112 : : return NULL;
113 : 1191 : return shumate_vector_expression_filter_from_literal (&value);
114 : : }
115 [ + - ]: 636 : else if (JSON_NODE_HOLDS_ARRAY (node))
116 : 636 : return shumate_vector_expression_filter_from_json_array (json_node_get_array (node), ctx, error);
117 : : else
118 : : {
119 : 0 : g_set_error (error,
120 : : SHUMATE_STYLE_ERROR,
121 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
122 : : "Expected a literal or array");
123 : 0 : return NULL;
124 : : }
125 : : }
126 : :
127 : : ShumateVectorExpression *
128 : 1236 : shumate_vector_expression_filter_from_json_array (JsonArray *array,
129 : : ShumateVectorExpressionContext *ctx,
130 : : GError **error)
131 : : {
132 : 2472 : g_autoptr(ShumateVectorExpressionFilter) self = NULL;
133 : 1236 : JsonNode *op_node;
134 : 1236 : const char *op;
135 : 1236 : const ExprInfo *info;
136 : :
137 [ + + ]: 1236 : if (json_array_get_length (array) == 0)
138 : : {
139 : 3 : g_set_error (error,
140 : : SHUMATE_STYLE_ERROR,
141 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
142 : : "Expected first element of filter array to be a string");
143 : 3 : return NULL;
144 : : }
145 : :
146 : 1233 : op_node = json_array_get_element (array, 0);
147 [ + + + + ]: 1233 : if (!JSON_NODE_HOLDS_VALUE (op_node) || json_node_get_value_type (op_node) != G_TYPE_STRING)
148 : : {
149 : 6 : g_set_error (error,
150 : : SHUMATE_STYLE_ERROR,
151 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
152 : : "Expected first element of filter array to be a string");
153 : 6 : return NULL;
154 : : }
155 : :
156 : 1227 : op = json_node_get_string (op_node);
157 : 1227 : info = shumate_vector_expression_type_lookup (op, strlen (op));
158 : :
159 [ + + ]: 1227 : if (info == NULL)
160 : : {
161 : 3 : g_set_error (error,
162 : : SHUMATE_STYLE_ERROR,
163 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
164 : : "Unrecognized operator %s", op);
165 : 3 : return FALSE;
166 : : }
167 : :
168 : : /* Expressions that don't use the child expressions array */
169 [ + + + + : 1224 : switch (info->type)
+ + + + +
+ + + ]
170 : : {
171 : 18 : case EXPR_COLLATOR:
172 : : {
173 : 18 : JsonNode *node;
174 : 18 : JsonObject *object;
175 : 18 : ShumateVectorExpression *child = NULL;
176 : :
177 [ - + ]: 18 : if (json_array_get_length (array) != 2)
178 : : {
179 : 0 : g_set_error (error,
180 : : SHUMATE_STYLE_ERROR,
181 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
182 : : "Operator `collator` expected exactly 1 argument, got %d",
183 : 0 : json_array_get_length (array) - 1);
184 : 0 : return NULL;
185 : : }
186 : :
187 : 18 : node = json_array_get_element (array, 1);
188 [ - + ]: 18 : if (!JSON_NODE_HOLDS_OBJECT (node))
189 : : {
190 : 0 : g_set_error (error,
191 : : SHUMATE_STYLE_ERROR,
192 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
193 : : "Operator `collator` expected an object");
194 : 0 : return NULL;
195 : : }
196 : :
197 : 18 : object = json_node_get_object (node);
198 : :
199 : 18 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
200 : 18 : self->type = EXPR_COLLATOR;
201 : 18 : self->expressions = g_ptr_array_new_with_free_func (g_object_unref);
202 : :
203 [ + - ]: 18 : if (!(child = shumate_vector_expression_filter_from_array_or_literal (json_object_get_member (object, "case-sensitive"), ctx, error)))
204 : : return NULL;
205 : 18 : g_ptr_array_add (self->expressions, child);
206 : :
207 : 18 : return (ShumateVectorExpression *)g_steal_pointer (&self);
208 : : }
209 : :
210 : 3 : case EXPR_FORMAT:
211 : : {
212 : 3 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
213 : 3 : self->type = EXPR_FORMAT;
214 : 3 : self->format_parts = g_ptr_array_new_with_free_func ((GDestroyNotify)format_expression_part_free);
215 : :
216 [ + - ]: 18 : for (int i = 1, n = json_array_get_length (array); i < n;)
217 : : {
218 : 15 : JsonNode *arg_node = json_array_get_element (array, i);
219 : 15 : JsonNode *format_node = NULL;
220 : 15 : FormatExpressionPart *part = g_new0 (FormatExpressionPart, 1);
221 : :
222 : 15 : g_ptr_array_add (self->format_parts, part);
223 : :
224 : 15 : part->string = shumate_vector_expression_filter_from_array_or_literal (arg_node, ctx, error);
225 [ + - ]: 15 : if (part->string == NULL)
226 : : return NULL;
227 : :
228 : 15 : i ++;
229 [ + + ]: 15 : if (i >= n)
230 : : break;
231 : :
232 : 12 : format_node = json_array_get_element (array, i);
233 [ + + ]: 12 : if (JSON_NODE_HOLDS_OBJECT (format_node))
234 : : {
235 : 6 : JsonObject *format_object = json_node_get_object (format_node);
236 : :
237 : 6 : i ++;
238 : :
239 [ + - ]: 6 : if (!(part->text_color = shumate_vector_expression_filter_from_array_or_literal (json_object_get_member (format_object, "text-color"), ctx, error)))
240 : : return NULL;
241 : :
242 [ + - ]: 6 : if (!(part->font_scale = shumate_vector_expression_filter_from_array_or_literal (json_object_get_member (format_object, "font-scale"), ctx, error)))
243 : : return NULL;
244 : : }
245 : : }
246 : :
247 : : return (ShumateVectorExpression *)g_steal_pointer (&self);
248 : : }
249 : :
250 : 138 : case EXPR_TYPE_LITERAL:
251 : : {
252 : 138 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
253 : 138 : JsonNode *arg;
254 : :
255 [ - + ]: 138 : if (json_array_get_length (array) != 2)
256 : : {
257 : 0 : g_set_error (error,
258 : : SHUMATE_STYLE_ERROR,
259 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
260 : : "Operator `literal` expected exactly 1 argument, got %d",
261 : 0 : json_array_get_length (array) - 1);
262 : 0 : return NULL;
263 : : }
264 : :
265 : 138 : arg = json_array_get_element (array, 1);
266 : :
267 [ - + ]: 138 : if (!shumate_vector_value_set_from_json_literal (&value, arg, error))
268 : : return NULL;
269 : :
270 : 138 : return shumate_vector_expression_filter_from_literal (&value);
271 : : }
272 : :
273 : 6 : case EXPR_INTERPOLATE:
274 : 6 : return shumate_vector_expression_interpolate_from_json_array (array, ctx, error);
275 : :
276 : 12 : case EXPR_STEP:
277 : 12 : return shumate_vector_expression_step_from_json_array (array, ctx, error);
278 : :
279 : 9 : case EXPR_MATCH:
280 : : {
281 : 9 : ShumateVectorExpression *input_expr;
282 : :
283 : 9 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
284 : 9 : self->type = EXPR_MATCH;
285 : 9 : self->expressions = g_ptr_array_new_with_free_func (g_object_unref);
286 : 9 : self->match_expressions = g_hash_table_new_full (
287 : : (GHashFunc)shumate_vector_value_hash,
288 : : (GEqualFunc)shumate_vector_value_equal,
289 : : (GDestroyNotify)shumate_vector_value_free,
290 : : g_object_unref
291 : : );
292 : :
293 [ - + ]: 9 : if (json_array_get_length (array) < 3)
294 : : {
295 : 0 : g_set_error (error,
296 : : SHUMATE_STYLE_ERROR,
297 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
298 : : "Operator `match` expected at least 2 arguments, got %d",
299 : 0 : json_array_get_length (array) - 1);
300 : 0 : return NULL;
301 : : }
302 : :
303 : 9 : input_expr = shumate_vector_expression_filter_from_array_or_literal (json_array_get_element (array, 1), ctx, error);
304 [ + - ]: 9 : if (input_expr == NULL)
305 : : return NULL;
306 : 9 : g_ptr_array_add (self->expressions, input_expr);
307 : :
308 [ + + ]: 24 : for (int i = 2, n = json_array_get_length (array); i + 1 < n; i += 2)
309 : : {
310 : 15 : JsonNode *label_node = json_array_get_element (array, i);
311 : 15 : JsonNode *output_node = json_array_get_element (array, i + 1);
312 : 39 : g_autoptr(ShumateVectorExpression) output_expr =
313 : 15 : shumate_vector_expression_filter_from_array_or_literal (output_node, ctx, error);
314 : :
315 [ + - ]: 15 : if (output_expr == NULL)
316 : : return NULL;
317 : :
318 [ + + ]: 15 : if (JSON_NODE_HOLDS_ARRAY (label_node))
319 : : {
320 : 6 : JsonArray *labels = json_node_get_array (label_node);
321 [ + + ]: 21 : for (int j = 0, m = json_array_get_length (labels); j < m; j ++)
322 : : {
323 : 15 : JsonNode *label = json_array_get_element (labels, j);
324 : 30 : g_autoptr(ShumateVectorValue) label_value = g_new0 (ShumateVectorValue, 1);
325 : :
326 [ - + ]: 15 : if (!shumate_vector_value_set_from_json_literal (label_value, label, error))
327 [ # # ]: 0 : return NULL;
328 : :
329 : 15 : g_hash_table_insert (self->match_expressions, g_steal_pointer (&label_value), g_object_ref (output_expr));
330 : : }
331 : : }
332 : : else
333 : : {
334 [ - - ]: 18 : g_autoptr(ShumateVectorValue) label_value = g_new0 (ShumateVectorValue, 1);
335 : :
336 [ - + ]: 9 : if (!shumate_vector_value_set_from_json_literal (label_value, label_node, error))
337 [ # # ]: 0 : return NULL;
338 : :
339 : 9 : g_hash_table_insert (self->match_expressions, g_steal_pointer (&label_value), g_object_ref (output_expr));
340 : : }
341 : : }
342 : :
343 [ + - ]: 9 : if (json_array_get_length (array) % 2 == 1)
344 : : {
345 : 9 : JsonNode *default_node = json_array_get_element (array, json_array_get_length (array) - 1);
346 : 18 : ShumateVectorExpression *default_expr =
347 : 9 : shumate_vector_expression_filter_from_array_or_literal (default_node, ctx, error);
348 : :
349 [ - + ]: 9 : if (default_expr == NULL)
350 : 0 : return NULL;
351 : :
352 : 9 : g_ptr_array_add (self->expressions, g_steal_pointer (&default_expr));
353 : : }
354 : :
355 : : return (ShumateVectorExpression *)g_steal_pointer (&self);
356 : : }
357 : :
358 : 9 : case EXPR_LET:
359 : : {
360 : 9 : g_auto(ShumateVectorExpressionContext) child_ctx = {0};
361 : 9 : ShumateVectorExpression *child_expr = NULL;
362 : :
363 [ - + ]: 9 : if (json_array_get_length (array) % 2 != 0)
364 : : {
365 : 0 : g_set_error (error,
366 : : SHUMATE_STYLE_ERROR,
367 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
368 : : "Operator `let` expected an odd number of arguments, got %d",
369 : 0 : json_array_get_length (array) - 1);
370 : 0 : return NULL;
371 : : }
372 : :
373 : 9 : child_ctx.parent = ctx;
374 : 9 : child_ctx.variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
375 : :
376 [ + + ]: 21 : for (int i = 1, n = json_array_get_length (array); i < n - 1; i += 2)
377 : : {
378 : 12 : JsonNode *name_node;
379 : 12 : ShumateVectorExpression *expr = NULL;
380 : :
381 : 12 : name_node = json_array_get_element (array, i);
382 [ + - - + ]: 12 : if (!JSON_NODE_HOLDS_VALUE (name_node) || json_node_get_value_type (name_node) != G_TYPE_STRING)
383 : : {
384 : 0 : g_set_error (error,
385 : : SHUMATE_STYLE_ERROR,
386 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
387 : : "Expected variable name to be a string (at index %d)",
388 : : i);
389 : 0 : return NULL;
390 : : }
391 : :
392 : 12 : expr = shumate_vector_expression_filter_from_array_or_literal (
393 : 12 : json_array_get_element (array, i + 1),
394 : : &child_ctx,
395 : : error
396 : : );
397 [ - + ]: 12 : if (expr == NULL)
398 : : return NULL;
399 : :
400 : 12 : g_hash_table_insert (child_ctx.variables,
401 : 12 : (char *)json_node_get_string (name_node),
402 : : expr);
403 : : }
404 : :
405 : 9 : child_expr = shumate_vector_expression_filter_from_array_or_literal (
406 : 9 : json_array_get_element (array, json_array_get_length (array) - 1),
407 : : &child_ctx,
408 : : error
409 : : );
410 : 9 : return child_expr;
411 : : }
412 : :
413 : 9 : case EXPR_VAR:
414 : : {
415 : 9 : JsonNode *arg_node;
416 : 9 : const char *variable = NULL;
417 : :
418 [ - + ]: 9 : if (json_array_get_length (array) != 2)
419 : : {
420 : 0 : g_set_error (error,
421 : : SHUMATE_STYLE_ERROR,
422 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
423 : : "Operator `var` expected exactly one argument, got %d",
424 : 0 : json_array_get_length (array) - 1);
425 : 0 : return NULL;
426 : : }
427 : :
428 : 9 : arg_node = json_array_get_element (array, 1);
429 [ + - - + ]: 9 : if (!JSON_NODE_HOLDS_VALUE (arg_node) || json_node_get_value_type (arg_node) != G_TYPE_STRING)
430 : : {
431 : 0 : g_set_error (error,
432 : : SHUMATE_STYLE_ERROR,
433 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
434 : : "Operator `var` expected a string literal");
435 : 0 : return NULL;
436 : : }
437 : :
438 : 9 : variable = json_node_get_string (arg_node);
439 : :
440 [ + - ]: 9 : for (ShumateVectorExpressionContext *c = ctx; c != NULL; c = c->parent)
441 : : {
442 : 9 : ShumateVectorExpression *expr = g_hash_table_lookup (c->variables, variable);
443 [ + - ]: 9 : if (expr != NULL)
444 : 9 : return g_object_ref (expr);
445 : : }
446 : :
447 : 0 : g_set_error (error,
448 : : SHUMATE_STYLE_ERROR,
449 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
450 : : "Variable `%s` not found",
451 : : variable);
452 : 0 : return NULL;
453 : : }
454 : :
455 : 9 : case EXPR_E:
456 : : {
457 : 9 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
458 : 9 : shumate_vector_value_set_number (&value, G_E);
459 : 9 : return shumate_vector_expression_filter_from_literal (&value);
460 : : }
461 : :
462 : 6 : case EXPR_LN2:
463 : : {
464 : 6 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
465 : 6 : shumate_vector_value_set_number (&value, G_LN2);
466 : 6 : return shumate_vector_expression_filter_from_literal (&value);
467 : : }
468 : :
469 : 9 : case EXPR_PI:
470 : : {
471 : 9 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
472 : 9 : shumate_vector_value_set_number (&value, G_PI);
473 : 9 : return shumate_vector_expression_filter_from_literal (&value);
474 : : }
475 : :
476 : : default:
477 : 996 : break;
478 : : }
479 : :
480 : 996 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
481 : 996 : self->type = info->type;
482 : :
483 [ + + + + ]: 996 : if (info->expect_exprs_set && json_array_get_length (array) - 1 != info->expect_exprs)
484 : : {
485 : 27 : g_set_error (error,
486 : : SHUMATE_STYLE_ERROR,
487 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
488 : : "Operator `%s` expected exactly %d arguments, got %d",
489 : 9 : op, info->expect_exprs, json_array_get_length (array) - 1);
490 : 9 : return FALSE;
491 : : }
492 : :
493 [ + + + + ]: 987 : if (info->expect_ge_exprs_set && json_array_get_length (array) - 1 < info->expect_ge_exprs)
494 : : {
495 : 18 : g_set_error (error,
496 : : SHUMATE_STYLE_ERROR,
497 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
498 : : "Operator `%s` expected at least %d arguments, got %d",
499 : 6 : op, info->expect_ge_exprs, json_array_get_length (array) - 1);
500 : 6 : return FALSE;
501 : : }
502 : :
503 [ + + + + ]: 981 : if (info->expect_le_exprs_set && json_array_get_length (array) - 1 > info->expect_le_exprs)
504 : : {
505 : 18 : g_set_error (error,
506 : : SHUMATE_STYLE_ERROR,
507 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
508 : : "Operator `%s` expected at most %d arguments, got %d",
509 : 6 : op, info->expect_le_exprs, json_array_get_length (array) - 1);
510 : 6 : return FALSE;
511 : : }
512 : :
513 [ + + ]: 2706 : for (int i = 1; i < json_array_get_length (array); i ++)
514 : : {
515 : 1734 : JsonNode *arg = json_array_get_element (array, i);
516 : 1731 : g_autoptr(ShumateVectorExpression) expr = NULL;
517 : :
518 [ + + ]: 1734 : if (i == 1
519 [ + + ]: 945 : && info->lookup_first_arg
520 [ + + ]: 492 : && JSON_NODE_HOLDS_VALUE (arg)
521 [ + + ]: 162 : && json_node_get_value_type (arg) == G_TYPE_STRING)
522 : 24 : {
523 : : /* If the first argument of a function is a string,
524 : : * convert it to a GET expression so we can do things like
525 : : * ["==", "admin_level", 2] */
526 : 24 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
527 : 24 : const char *string = json_node_get_string (arg);
528 : :
529 [ + + ]: 24 : if (g_strcmp0 ("zoom", string) == 0)
530 : : {
531 : 3 : expr = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
532 : 3 : ((ShumateVectorExpressionFilter *)expr)->type = EXPR_ZOOM;
533 : : }
534 [ + + ]: 21 : else if (g_strcmp0 ("$type", string) == 0)
535 : : {
536 : 9 : expr = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
537 : 9 : ((ShumateVectorExpressionFilter *)expr)->type = EXPR_GEOMETRY_TYPE;
538 : : }
539 : : else
540 : : {
541 : 12 : expr = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
542 : 12 : ((ShumateVectorExpressionFilter *)expr)->type = EXPR_FAST_GET;
543 [ - + ]: 24 : ((ShumateVectorExpressionFilter *)expr)->fast_get_key = g_strdup (string);
544 : : }
545 : : }
546 [ + + ]: 1710 : else if (!(expr = shumate_vector_expression_filter_from_array_or_literal (arg, ctx, error)))
547 : : return NULL;
548 : :
549 [ + + ]: 1731 : if (self->expressions == NULL)
550 : 945 : self->expressions = g_ptr_array_new_with_free_func (g_object_unref);
551 : 1731 : g_ptr_array_add (self->expressions, g_steal_pointer (&expr));
552 : : }
553 : :
554 : 972 : return optimize (g_steal_pointer (&self));
555 : : }
556 : :
557 : :
558 : : ShumateVectorExpression *
559 : 27 : shumate_vector_expression_filter_from_format (const char *format, GError **error)
560 : : {
561 : 54 : g_autoptr(ShumateVectorExpressionFilter) self = NULL;
562 [ - + ]: 27 : g_auto(GStrv) parts = NULL;
563 : 27 : int balance = 0;
564 : :
565 [ + + - + ]: 27 : if (strchr (format, '{') == NULL || strchr (format, '}') == NULL)
566 : : {
567 : 24 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
568 : 24 : shumate_vector_value_set_string (&value, format);
569 : 24 : return shumate_vector_expression_filter_from_literal (&value);
570 : : }
571 : :
572 : 3 : self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
573 : 3 : self->type = EXPR_CONCAT;
574 : 3 : self->expressions = g_ptr_array_new_with_free_func (g_object_unref);
575 : :
576 : : /* Ensure the braces in the format string are balanced and not nested */
577 [ + + ]: 57 : for (int i = 0, n = strlen (format); i < n; i ++)
578 : : {
579 [ + + ]: 54 : if (format[i] == '{')
580 : 3 : balance ++;
581 [ + + ]: 51 : else if (format[i] == '}')
582 : 3 : balance --;
583 : :
584 [ - + ]: 54 : if (balance != 0 && balance != 1)
585 : : {
586 : 0 : g_set_error (error,
587 : : SHUMATE_STYLE_ERROR,
588 : : SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
589 : : "Format string `%s` is nested or unbalanced",
590 : : format);
591 : 0 : return NULL;
592 : : }
593 : : }
594 : :
595 : 3 : parts = g_strsplit_set (format, "{}", 0);
596 : :
597 : 3 : for (int i = 0; TRUE;)
598 : : {
599 : 3 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
600 : 6 : g_autoptr(ShumateVectorExpressionFilter) get_expr = NULL;
601 : :
602 [ + - ]: 6 : if (parts[i] == NULL)
603 : : break;
604 : :
605 [ + - ]: 6 : if (strlen (parts[i]) > 0)
606 : : {
607 : 6 : shumate_vector_value_set_string (&value, parts[i]);
608 : 6 : g_ptr_array_add (self->expressions, shumate_vector_expression_filter_from_literal (&value));
609 : : }
610 : 6 : i ++;
611 : :
612 [ + + ]: 6 : if (parts[i] == NULL)
613 : : break;
614 : :
615 : 3 : get_expr = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FILTER, NULL);
616 : 3 : get_expr->type = EXPR_FAST_GET;
617 [ - + ]: 3 : get_expr->fast_get_key = g_strdup (parts[i]);
618 : 3 : g_ptr_array_add (self->expressions, g_steal_pointer (&get_expr));
619 : 3 : i ++;
620 : : }
621 : :
622 : 3 : return (ShumateVectorExpression *)g_steal_pointer (&self);
623 : : }
624 : :
625 : : static GeometryTypeFlags
626 : 18 : parse_geometry_type_flag (const char *flag)
627 : : {
628 [ + + ]: 18 : if (g_strcmp0 (flag, "Point") == 0)
629 : : return GEOM_SINGLE_POINT;
630 [ + - ]: 15 : else if (g_strcmp0 (flag, "MultiPoint") == 0)
631 : : return GEOM_MULTI_POINT;
632 [ + + ]: 15 : else if (g_strcmp0 (flag, "LineString") == 0)
633 : : return GEOM_SINGLE_LINESTRING;
634 [ + + ]: 9 : else if (g_strcmp0 (flag, "MultiLineString") == 0)
635 : : return GEOM_MULTI_LINESTRING;
636 [ + + ]: 6 : else if (g_strcmp0 (flag, "Polygon") == 0)
637 : : return GEOM_SINGLE_POLYGON;
638 [ + - ]: 3 : else if (g_strcmp0 (flag, "MultiPolygon") == 0)
639 : : return GEOM_MULTI_POLYGON;
640 : : else
641 : 3 : return 0;
642 : : }
643 : :
644 : : static ShumateVectorExpression *
645 : 972 : optimize (ShumateVectorExpressionFilter *self)
646 : : {
647 [ + + + + : 972 : switch (self->type)
+ ]
648 : : {
649 : 24 : case EXPR_ANY:
650 : : case EXPR_ALL:
651 [ + + - + ]: 24 : if (self->expressions == NULL || self->expressions->len == 0)
652 : : {
653 [ - + ]: 6 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
654 : 6 : shumate_vector_value_set_boolean (&self->value, self->type == EXPR_ALL);
655 : 6 : self->type = EXPR_LITERAL;
656 : : }
657 : : break;
658 : :
659 : 393 : case EXPR_EQ:
660 : : case EXPR_NE:
661 : : {
662 : 393 : ShumateVectorExpressionFilter *key_expr, *value_expr;
663 : :
664 [ + + ]: 393 : if (self->expressions->len != 2)
665 : : break;
666 : :
667 : 387 : key_expr = self->expressions->pdata[0];
668 : 387 : value_expr = self->expressions->pdata[1];
669 : :
670 [ + + + - ]: 387 : if (!SHUMATE_IS_VECTOR_EXPRESSION_FILTER (key_expr) || !SHUMATE_IS_VECTOR_EXPRESSION_FILTER (value_expr))
671 : : break;
672 [ + + ]: 375 : if (value_expr->type != EXPR_LITERAL)
673 : : break;
674 : :
675 [ + + + ]: 303 : switch (key_expr->type)
676 : : {
677 : 12 : case EXPR_FAST_GET:
678 [ + + ]: 12 : self->type = self->type == EXPR_EQ ? EXPR_FAST_EQ : EXPR_FAST_NE;
679 [ - + ]: 12 : self->fast_eq.key = g_strdup (key_expr->fast_get_key);
680 : 12 : shumate_vector_value_copy (&value_expr->value, &self->fast_eq.value);
681 [ + - ]: 12 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
682 : : break;
683 : 12 : case EXPR_GEOMETRY_TYPE:
684 : : {
685 : 12 : const char *geometry_type;
686 : :
687 [ + - ]: 12 : if (!shumate_vector_value_get_string (&value_expr->value, &geometry_type))
688 : : break;
689 : :
690 [ + + ]: 12 : self->type = self->type == EXPR_EQ ? EXPR_FAST_GEOMETRY_TYPE : EXPR_FAST_NOT_GEOMETRY_TYPE;
691 : 12 : self->fast_geometry_type = parse_geometry_type_flag (geometry_type);
692 [ + - ]: 12 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
693 : : break;
694 : : }
695 : : default:
696 : : break;
697 : : }
698 : :
699 : : break;
700 : : }
701 : :
702 : 42 : case EXPR_GET:
703 : : case EXPR_HAS:
704 : : case EXPR_NOT_HAS:
705 : : {
706 : 42 : ShumateVectorExpressionFilter *key_expr = self->expressions->pdata[0];
707 : 42 : const char *key;
708 : :
709 [ + - ]: 42 : if (self->expressions->len != 1)
710 : : break;
711 : :
712 [ + - ]: 42 : if (!SHUMATE_IS_VECTOR_EXPRESSION_FILTER (key_expr))
713 : : break;
714 [ + + ]: 42 : if (key_expr->type != EXPR_LITERAL)
715 : : break;
716 : :
717 [ + - ]: 27 : if (shumate_vector_value_get_string (&key_expr->value, &key))
718 : : {
719 [ + + + + ]: 27 : self->type = (self->type == EXPR_GET) ? EXPR_FAST_GET : (self->type == EXPR_HAS) ? EXPR_FAST_HAS : EXPR_FAST_NOT_HAS;
720 [ - + ]: 27 : self->fast_get_key = g_strdup (key);
721 [ + - ]: 27 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
722 : : }
723 : : break;
724 : : }
725 : :
726 : 21 : case EXPR_IN:
727 : : case EXPR_NOT_IN:
728 : : {
729 : 21 : ShumateVectorExpressionFilter *key_expr = self->expressions->pdata[0];
730 : :
731 [ + - ]: 21 : if (!SHUMATE_IS_VECTOR_EXPRESSION_FILTER (key_expr))
732 : : break;
733 : :
734 [ + + + ]: 21 : switch (key_expr->type)
735 : : {
736 : 3 : case EXPR_GEOMETRY_TYPE:
737 [ + + ]: 6 : for (int i = 1, n = self->expressions->len; i < n; i ++)
738 : : {
739 : 3 : ShumateVectorExpressionFilter *expr = self->expressions->pdata[i];
740 [ + - + - ]: 3 : if (!SHUMATE_IS_VECTOR_EXPRESSION_FILTER (expr) || expr->type != EXPR_LITERAL)
741 : : break;
742 : : }
743 : :
744 [ - + ]: 3 : self->type = self->type == EXPR_IN ? EXPR_FAST_GEOMETRY_TYPE : EXPR_FAST_NOT_GEOMETRY_TYPE;
745 : 3 : self->fast_geometry_type = 0;
746 : :
747 [ + + ]: 6 : for (int i = 1; i < self->expressions->len; i ++)
748 : : {
749 : 3 : ShumateVectorExpressionFilter *value_expr = self->expressions->pdata[i];
750 : :
751 [ + - ]: 3 : if (value_expr->value.type == SHUMATE_VECTOR_VALUE_TYPE_ARRAY)
752 : : {
753 [ + + ]: 9 : for (int j = 0, n = value_expr->value.array->len; j < n; j ++)
754 : : {
755 : 6 : const char *geometry_type;
756 [ + - ]: 6 : if (shumate_vector_value_get_string (g_ptr_array_index (value_expr->value.array, j), &geometry_type))
757 : 6 : self->fast_geometry_type |= parse_geometry_type_flag (geometry_type);
758 : : }
759 : : }
760 : : else
761 : : {
762 : 0 : const char *geometry_type;
763 [ # # ]: 0 : if (shumate_vector_value_get_string (&value_expr->value, &geometry_type))
764 : 0 : self->fast_geometry_type |= parse_geometry_type_flag (geometry_type);
765 : : }
766 : : }
767 : :
768 : 3 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
769 : : break;
770 : :
771 : 9 : case EXPR_FAST_GET:
772 [ + + ]: 18 : for (int i = 1, n = self->expressions->len; i < n; i ++)
773 : : {
774 : 9 : ShumateVectorExpressionFilter *expr = self->expressions->pdata[i];
775 [ + - + - ]: 9 : if (!SHUMATE_IS_VECTOR_EXPRESSION_FILTER (expr) || expr->type != EXPR_LITERAL)
776 : : break;
777 : : }
778 : :
779 [ + + ]: 9 : self->type = self->type == EXPR_IN ? EXPR_FAST_IN : EXPR_FAST_NOT_IN;
780 [ - + ]: 9 : self->fast_in.key = g_strdup (key_expr->fast_get_key);
781 : :
782 : 9 : self->fast_in.haystack = g_hash_table_new_full (
783 : : (GHashFunc)shumate_vector_value_hash, (GEqualFunc)shumate_vector_value_equal, (GDestroyNotify)shumate_vector_value_free, NULL
784 : : );
785 [ + + ]: 18 : for (int i = 1; i < self->expressions->len; i ++)
786 : : {
787 : 9 : ShumateVectorExpressionFilter *value_expr = self->expressions->pdata[i];
788 : :
789 [ + - ]: 9 : if (value_expr->value.type == SHUMATE_VECTOR_VALUE_TYPE_ARRAY)
790 : : {
791 [ + + ]: 33 : for (int j = 0, n = value_expr->value.array->len; j < n; j ++)
792 : : {
793 : 24 : ShumateVectorValue *value = g_new0 (ShumateVectorValue, 1);
794 : 24 : shumate_vector_value_copy (g_ptr_array_index (value_expr->value.array, j), value);
795 : 24 : g_hash_table_add (self->fast_in.haystack, value);
796 : : }
797 : : }
798 : : else
799 : : {
800 : 0 : ShumateVectorValue *value = g_new0 (ShumateVectorValue, 1);
801 : 0 : shumate_vector_value_copy (&value_expr->value, value);
802 : 0 : g_hash_table_add (self->fast_in.haystack, value);
803 : : }
804 : : }
805 : :
806 : 9 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
807 : : break;
808 : :
809 : : default:
810 : : break;
811 : : }
812 : :
813 : : break;
814 : : }
815 : :
816 : : default:
817 : : break;
818 : : }
819 : :
820 : 972 : return (ShumateVectorExpression *)self;
821 : : }
822 : :
823 : :
824 : : static void
825 : 2715 : shumate_vector_expression_filter_finalize (GObject *object)
826 : : {
827 : 2715 : ShumateVectorExpressionFilter *self = (ShumateVectorExpressionFilter *)object;
828 : :
829 [ + + ]: 2715 : g_clear_pointer (&self->expressions, g_ptr_array_unref);
830 : :
831 [ + + + + : 2715 : switch (self->type)
+ + + ]
832 : : {
833 : 1665 : case EXPR_LITERAL:
834 : 1665 : shumate_vector_value_unset (&self->value);
835 : 1665 : break;
836 : 3 : case EXPR_FORMAT:
837 [ + - ]: 3 : g_clear_pointer (&self->format_parts, g_ptr_array_unref);
838 : : break;
839 : 9 : case EXPR_MATCH:
840 [ + - ]: 9 : g_clear_pointer (&self->match_expressions, g_hash_table_unref);
841 : : break;
842 : 42 : case EXPR_FAST_GET:
843 : : case EXPR_FAST_HAS:
844 : : case EXPR_FAST_NOT_HAS:
845 [ + - ]: 42 : g_clear_pointer (&self->fast_get_key, g_free);
846 : : break;
847 : 9 : case EXPR_FAST_IN:
848 : : case EXPR_FAST_NOT_IN:
849 [ + - ]: 9 : g_clear_pointer (&self->fast_in.key, g_free);
850 [ + - ]: 9 : g_clear_pointer (&self->fast_in.haystack, g_hash_table_unref);
851 : : break;
852 : 12 : case EXPR_FAST_EQ:
853 : : case EXPR_FAST_NE:
854 [ + - ]: 12 : g_clear_pointer (&self->fast_eq.key, g_free);
855 : 12 : shumate_vector_value_unset (&self->fast_eq.value);
856 : 12 : break;
857 : : default:
858 : : break;
859 : : }
860 : :
861 : 2715 : G_OBJECT_CLASS (shumate_vector_expression_filter_parent_class)->finalize (object);
862 : 2715 : }
863 : :
864 : :
865 : : static gboolean
866 : 2808 : shumate_vector_expression_filter_eval (ShumateVectorExpression *expr,
867 : : ShumateVectorRenderScope *scope,
868 : : ShumateVectorValue *out)
869 : : {
870 : 2808 : ShumateVectorExpressionFilter *self = (ShumateVectorExpressionFilter *)expr;
871 : 5616 : g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
872 : 2808 : g_auto(ShumateVectorValue) value2 = SHUMATE_VECTOR_VALUE_INIT;
873 : 2808 : g_auto(ShumateVectorValue) value3 = SHUMATE_VECTOR_VALUE_INIT;
874 : 2808 : gboolean inverted = FALSE;
875 : 2808 : gboolean boolean;
876 : 2808 : double number, number2;
877 : 2808 : g_autofree char *string = NULL;
878 : 2808 : ShumateVectorExpression **expressions = NULL;
879 : 2808 : ShumateVectorCollator collator;
880 : 2808 : guint n_expressions = 0;
881 : :
882 [ + + ]: 2808 : if (self->expressions)
883 : : {
884 : 906 : expressions = (ShumateVectorExpression **)self->expressions->pdata;
885 : 906 : n_expressions = self->expressions->len;
886 : : }
887 : :
888 [ + + + + : 2808 : switch (self->type)
+ - + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + -
+ + + + +
+ + + + +
+ + + +
- ]
889 : : {
890 : 1800 : case EXPR_LITERAL:
891 : 1800 : shumate_vector_value_copy (&self->value, out);
892 : 1800 : return TRUE;
893 : :
894 : 27 : case EXPR_TO_BOOLEAN:
895 : : {
896 [ + - ]: 27 : g_assert (n_expressions == 1);
897 : :
898 [ + - ]: 27 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
899 : : return FALSE;
900 : :
901 [ + - + + : 27 : switch (value.type)
+ ]
902 : : {
903 : 3 : case SHUMATE_VECTOR_VALUE_TYPE_NULL:
904 : 3 : shumate_vector_value_set_boolean (out, FALSE);
905 : 3 : return TRUE;
906 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
907 : 0 : shumate_vector_value_copy (&value, out);
908 : 0 : return TRUE;
909 : 15 : case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
910 [ + + + + ]: 15 : shumate_vector_value_set_boolean (out, value.number != 0 && !isnan (value.number));
911 : 15 : return TRUE;
912 : 6 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
913 [ + - + + ]: 6 : shumate_vector_value_set_boolean (out, value.string != NULL && value.string[0] != '\0');
914 : 6 : return TRUE;
915 : 3 : default:
916 : 3 : shumate_vector_value_set_boolean (out, TRUE);
917 : 3 : return TRUE;
918 : : }
919 : : }
920 : :
921 : : case EXPR_TO_COLOR:
922 [ + - ]: 21 : for (int i = 0; i < n_expressions; i ++)
923 : : {
924 : 21 : GdkRGBA rgba;
925 : :
926 [ - + ]: 21 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
927 : 0 : continue;
928 : :
929 [ + + ]: 21 : if (shumate_vector_value_get_color (&value, &rgba))
930 : : {
931 : 18 : shumate_vector_value_set_color (out, &rgba);
932 : 18 : return TRUE;
933 : : }
934 : : }
935 : :
936 : : return FALSE;
937 : :
938 : : case EXPR_TO_NUMBER:
939 [ + - ]: 24 : for (int i = 0; i < n_expressions; i ++)
940 : : {
941 [ - + ]: 24 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
942 : 0 : continue;
943 : :
944 [ + + + + : 24 : switch (value.type)
- ]
945 : : {
946 : 3 : case SHUMATE_VECTOR_VALUE_TYPE_NULL:
947 : 3 : shumate_vector_value_set_number (out, 0);
948 : 3 : return TRUE;
949 : 6 : case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
950 [ + + ]: 6 : shumate_vector_value_set_number (out, value.boolean ? 1 : 0);
951 : 6 : return TRUE;
952 : 3 : case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
953 : 3 : shumate_vector_value_copy (&value, out);
954 : 3 : return TRUE;
955 : 12 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
956 : : {
957 : 12 : char *endptr = NULL;
958 : 12 : number = g_ascii_strtod (value.string, &endptr);
959 [ + - + - : 12 : if (errno == 0 && endptr != NULL && *endptr == '\0')
+ + ]
960 : : {
961 : 9 : shumate_vector_value_set_number (out, number);
962 : 9 : return TRUE;
963 : : }
964 : : }
965 : 3 : break;
966 : : default:
967 : : break;
968 : : }
969 : : }
970 : :
971 : : return FALSE;
972 : :
973 : 42 : case EXPR_TO_STRING:
974 : : {
975 : 42 : g_autofree char *string = NULL;
976 : :
977 [ - + ]: 42 : g_assert (n_expressions == 1);
978 : :
979 [ + - ]: 42 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
980 : : return FALSE;
981 : 42 : string = shumate_vector_value_as_string (&value);
982 : 42 : shumate_vector_value_set_string (out, string);
983 : 42 : return TRUE;
984 : : }
985 : :
986 : 0 : case EXPR_TYPEOF:
987 : : {
988 [ # # ]: 0 : g_assert (n_expressions == 1);
989 : :
990 [ # # ]: 0 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
991 : : return FALSE;
992 : :
993 [ # # # # : 0 : switch (value.type)
# # # # ]
994 : : {
995 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_NULL:
996 : 0 : shumate_vector_value_set_string (out, "null");
997 : 0 : return TRUE;
998 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
999 : 0 : shumate_vector_value_set_string (out, "boolean");
1000 : 0 : return TRUE;
1001 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
1002 : 0 : shumate_vector_value_set_string (out, "number");
1003 : 0 : return TRUE;
1004 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
1005 : 0 : shumate_vector_value_set_string (out, "string");
1006 : 0 : return TRUE;
1007 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
1008 : 0 : shumate_vector_value_set_string (out, "array");
1009 : 0 : return TRUE;
1010 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
1011 : 0 : shumate_vector_value_set_string (out, "color");
1012 : 0 : return TRUE;
1013 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
1014 : 0 : shumate_vector_value_set_string (out, "resolvedImage");
1015 : 0 : return TRUE;
1016 : 0 : default:
1017 : 0 : shumate_vector_value_set_string (out, "value");
1018 : 0 : return TRUE;
1019 : : }
1020 : : }
1021 : :
1022 : 6 : case EXPR_NOT:
1023 [ - + ]: 6 : g_assert (n_expressions == 1);
1024 : :
1025 [ + - ]: 6 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1026 : : return FALSE;
1027 [ + - ]: 6 : if (!shumate_vector_value_get_boolean (&value, &boolean))
1028 : : return FALSE;
1029 : :
1030 : 6 : shumate_vector_value_set_boolean (out, !boolean);
1031 : 6 : return TRUE;
1032 : :
1033 : 9 : case EXPR_NONE:
1034 : 9 : inverted = TRUE;
1035 : 15 : G_GNUC_FALLTHROUGH;
1036 : 15 : case EXPR_ANY:
1037 [ + + ]: 30 : for (int i = 0; i < n_expressions; i ++)
1038 : : {
1039 [ + - ]: 21 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
1040 : : return FALSE;
1041 [ + - ]: 21 : if (!shumate_vector_value_get_boolean (&value, &boolean))
1042 : : return FALSE;
1043 : :
1044 [ + + ]: 21 : if (boolean)
1045 : : {
1046 : 6 : shumate_vector_value_set_boolean (out, TRUE ^ inverted);
1047 : 6 : return TRUE;
1048 : : }
1049 : : }
1050 : :
1051 : 9 : shumate_vector_value_set_boolean (out, FALSE ^ inverted);
1052 : 9 : return TRUE;
1053 : :
1054 : : case EXPR_ALL:
1055 [ + + ]: 12 : for (int i = 0; i < n_expressions; i ++)
1056 : : {
1057 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
1058 : : return FALSE;
1059 [ + - ]: 9 : if (!shumate_vector_value_get_boolean (&value, &boolean))
1060 : : return FALSE;
1061 : :
1062 [ + + ]: 9 : if (!boolean)
1063 : : {
1064 : 3 : shumate_vector_value_set_boolean (out, FALSE);
1065 : 3 : return TRUE;
1066 : : }
1067 : : }
1068 : :
1069 : 3 : shumate_vector_value_set_boolean (out, TRUE);
1070 : 3 : return TRUE;
1071 : :
1072 : 6 : case EXPR_NOT_HAS:
1073 : 6 : inverted = TRUE;
1074 : 12 : G_GNUC_FALLTHROUGH;
1075 : 12 : case EXPR_HAS:
1076 [ - + ]: 12 : g_assert (n_expressions == 1);
1077 : :
1078 : 12 : string = shumate_vector_expression_eval_string (expressions[0], scope, NULL);
1079 : 12 : shumate_vector_render_scope_get_variable (scope, string, &value);
1080 : 12 : shumate_vector_value_set_boolean (out, !shumate_vector_value_is_null (&value) ^ inverted);
1081 : 12 : return TRUE;
1082 : :
1083 : 3 : case EXPR_GET:
1084 [ - + ]: 3 : g_assert (n_expressions == 1);
1085 : :
1086 : 3 : string = shumate_vector_expression_eval_string (expressions[0], scope, NULL);
1087 : 3 : shumate_vector_render_scope_get_variable (scope, string, out);
1088 : 3 : return TRUE;
1089 : :
1090 : 3 : case EXPR_NOT_IN:
1091 : 3 : inverted = TRUE;
1092 : 9 : G_GNUC_FALLTHROUGH;
1093 : 9 : case EXPR_IN:
1094 [ - + ]: 9 : g_assert (n_expressions >= 1);
1095 : :
1096 : 9 : shumate_vector_expression_eval (expressions[0], scope, &value);
1097 : :
1098 [ + + ]: 21 : for (int i = 1; i < n_expressions; i ++)
1099 : : {
1100 : 18 : shumate_vector_expression_eval (expressions[i], scope, &value2);
1101 : :
1102 [ + + ]: 18 : if (shumate_vector_value_equal (&value, &value2))
1103 : : {
1104 : 3 : shumate_vector_value_set_boolean (out, TRUE ^ inverted);
1105 : 3 : return TRUE;
1106 : : }
1107 [ + + ]: 15 : else if (value2.type == SHUMATE_VECTOR_VALUE_TYPE_ARRAY)
1108 : : {
1109 [ + - ]: 12 : for (int i = 0, n = value2.array->len; i < n; i ++)
1110 [ + + ]: 12 : if (shumate_vector_value_equal (&value, g_ptr_array_index (value2.array, i)))
1111 : : {
1112 : 3 : shumate_vector_value_set_boolean (out, TRUE ^ inverted);
1113 : 3 : return TRUE;
1114 : : }
1115 : : }
1116 : : }
1117 : :
1118 : 3 : shumate_vector_value_set_boolean (out, FALSE ^ inverted);
1119 : 3 : return TRUE;
1120 : :
1121 : 24 : case EXPR_NE:
1122 : 24 : inverted = TRUE;
1123 : 369 : G_GNUC_FALLTHROUGH;
1124 : 369 : case EXPR_EQ:
1125 [ - + ]: 369 : g_assert (n_expressions == 2 || n_expressions == 3);
1126 : :
1127 [ + + ]: 369 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1128 : : return FALSE;
1129 [ + - ]: 366 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1130 : : return FALSE;
1131 : :
1132 [ + + ]: 366 : if (n_expressions == 3)
1133 : : {
1134 : 6 : const char *str1, *str2;
1135 : 6 : g_autofree char *str1_auto = NULL;
1136 : 6 : g_autofree char *str2_auto = NULL;
1137 : :
1138 [ - + ]: 6 : if (!shumate_vector_value_get_string (&value, &str1))
1139 : : return FALSE;
1140 [ - + ]: 6 : if (!shumate_vector_value_get_string (&value2, &str2))
1141 : : return FALSE;
1142 : :
1143 [ - + ]: 6 : if (!shumate_vector_expression_eval (expressions[2], scope, &value3))
1144 : : return FALSE;
1145 [ - + ]: 6 : if (!shumate_vector_value_get_collator (&value3, &collator))
1146 : : return FALSE;
1147 : :
1148 [ + + ]: 6 : if (!collator.case_sensitive)
1149 : : {
1150 : 3 : str1 = str1_auto = g_utf8_casefold (str1, -1);
1151 : 3 : str2 = str2_auto = g_utf8_casefold (str2, -1);
1152 : : }
1153 : :
1154 : 6 : shumate_vector_value_set_boolean (out, (g_utf8_collate (str1, str2) == 0) ^ inverted);
1155 : 6 : return TRUE;
1156 : : }
1157 : : else
1158 : : {
1159 : 360 : shumate_vector_value_set_boolean (out, shumate_vector_value_equal (&value, &value2) ^ inverted);
1160 : 360 : return TRUE;
1161 : : }
1162 : :
1163 : 78 : case EXPR_LT:
1164 : : case EXPR_GT:
1165 : : case EXPR_LE:
1166 : : case EXPR_GE:
1167 : : {
1168 : 78 : int cmp;
1169 : 78 : const char *str, *str2;
1170 : 78 : g_autofree char *str_auto = NULL;
1171 : 78 : g_autofree char *str2_auto = NULL;
1172 [ - + ]: 78 : g_assert (n_expressions == 2 || n_expressions == 3);
1173 : :
1174 [ + - ]: 78 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1175 : : return FALSE;
1176 [ + - ]: 78 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1177 : : return FALSE;
1178 : :
1179 [ + + ]: 78 : if (n_expressions == 3)
1180 : : {
1181 [ + - ]: 6 : if (!shumate_vector_expression_eval (expressions[2], scope, &value3))
1182 : : return FALSE;
1183 [ + - ]: 6 : if (!shumate_vector_value_get_collator (&value3, &collator))
1184 : : return FALSE;
1185 : :
1186 [ + - ]: 6 : if (!shumate_vector_value_get_string (&value, &str))
1187 : : return FALSE;
1188 [ + - ]: 6 : if (!shumate_vector_value_get_string (&value2, &str2))
1189 : : return FALSE;
1190 : :
1191 [ + - ]: 6 : if (!collator.case_sensitive)
1192 : : {
1193 : 6 : str = str_auto = g_utf8_casefold (str, -1);
1194 : 6 : str2 = str2_auto = g_utf8_casefold (str2, -1);
1195 : : }
1196 : :
1197 : 6 : cmp = g_utf8_collate (str, str2);
1198 : : }
1199 [ + + ]: 72 : else if (shumate_vector_value_get_number (&value, &number))
1200 : : {
1201 [ + - ]: 51 : if (!shumate_vector_value_get_number (&value2, &number2))
1202 : : return FALSE;
1203 : :
1204 [ + + + + ]: 51 : cmp = number > number2 ? 1 : number < number2 ? -1 : 0;
1205 : : }
1206 [ + + ]: 21 : else if (shumate_vector_value_get_string (&value, &str))
1207 : : {
1208 [ + - ]: 18 : if (!shumate_vector_value_get_string (&value2, &str2))
1209 : : return FALSE;
1210 : :
1211 : 18 : cmp = g_utf8_collate (str, str2);
1212 : : }
1213 : : else
1214 : : return FALSE;
1215 : :
1216 [ + + + + : 75 : switch (self->type)
- ]
1217 : : {
1218 : 15 : case EXPR_LT:
1219 : 15 : shumate_vector_value_set_boolean (out, (cmp < 0) ^ inverted);
1220 : 15 : break;
1221 : 15 : case EXPR_GT:
1222 : 15 : shumate_vector_value_set_boolean (out, (cmp > 0) ^ inverted);
1223 : 15 : break;
1224 : 18 : case EXPR_LE:
1225 : 18 : shumate_vector_value_set_boolean (out, (cmp <= 0) ^ inverted);
1226 : 18 : break;
1227 : 27 : case EXPR_GE:
1228 : 27 : shumate_vector_value_set_boolean (out, (cmp >= 0) ^ inverted);
1229 : 27 : break;
1230 : 0 : default:
1231 : 0 : g_assert_not_reached ();
1232 : : }
1233 : :
1234 : : return TRUE;
1235 : : }
1236 : :
1237 : : case EXPR_CASE:
1238 [ + - ]: 15 : for (int i = 0; i < n_expressions; i += 2)
1239 : : {
1240 [ + - ]: 15 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
1241 : : return FALSE;
1242 : :
1243 [ + + ]: 15 : if (i + 1 == n_expressions)
1244 : : {
1245 : : /* fallback value */
1246 : 3 : shumate_vector_value_steal (&value, out);
1247 : 3 : return TRUE;
1248 : : }
1249 : : else
1250 : : {
1251 : 12 : gboolean bool_result;
1252 [ + - ]: 12 : if (!shumate_vector_value_get_boolean (&value, &bool_result))
1253 : 6 : return FALSE;
1254 : :
1255 [ + + ]: 12 : if (bool_result)
1256 : 6 : return shumate_vector_expression_eval (expressions[i + 1], scope, out);
1257 : : }
1258 : : }
1259 : :
1260 : : /* no case matched and there was no fallback */
1261 : : return FALSE;
1262 : :
1263 : : case EXPR_COALESCE:
1264 [ + + ]: 24 : for (int i = 0; i < n_expressions; i ++)
1265 : : {
1266 [ + + ]: 21 : if (!shumate_vector_expression_eval (expressions[i], scope, out))
1267 : 6 : continue;
1268 : :
1269 [ + + ]: 15 : if (shumate_vector_value_is_null (out))
1270 : 6 : continue;
1271 : :
1272 : : return TRUE;
1273 : : }
1274 : :
1275 : : /* no expression succeeded, return null */
1276 : 3 : shumate_vector_value_unset (out);
1277 : 3 : return TRUE;
1278 : :
1279 : 9 : case EXPR_MATCH:
1280 : : {
1281 : 9 : ShumateVectorExpression *output_expr;
1282 : :
1283 [ - + ]: 9 : g_assert (n_expressions == 1 || n_expressions == 2);
1284 : :
1285 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1286 : : return FALSE;
1287 : :
1288 : 9 : output_expr = g_hash_table_lookup (self->match_expressions, &value);
1289 : :
1290 [ + + ]: 9 : if (output_expr != NULL)
1291 : 6 : return shumate_vector_expression_eval (output_expr, scope, out);
1292 [ + - ]: 3 : else if (n_expressions == 2)
1293 : 3 : return shumate_vector_expression_eval (expressions[1], scope, out);
1294 : : else
1295 : : return FALSE;
1296 : : }
1297 : :
1298 : : /* no case matched and there was no fallback */
1299 : : return FALSE;
1300 : :
1301 : 36 : case EXPR_CONCAT:
1302 : : {
1303 : 72 : g_autoptr(GString) string_builder = g_string_new ("");
1304 : :
1305 [ + + ]: 90 : for (int i = 0; i < n_expressions; i ++)
1306 : : {
1307 [ - + ]: 54 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
1308 : 0 : return FALSE;
1309 : :
1310 : 54 : g_free (string);
1311 : 54 : string = shumate_vector_value_as_string (&value);
1312 : :
1313 [ - + ]: 108 : g_string_append (string_builder, string);
1314 : : }
1315 : :
1316 : 36 : shumate_vector_value_set_string (out, string_builder->str);
1317 : 36 : return TRUE;
1318 : : }
1319 : :
1320 : 3 : case EXPR_DOWNCASE:
1321 : : {
1322 : 3 : const char *str;
1323 : 3 : g_autofree char *string_down = NULL;
1324 [ - + ]: 3 : g_assert (n_expressions == 1);
1325 : :
1326 [ - + ]: 3 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1327 : : return FALSE;
1328 [ - + ]: 3 : if (!shumate_vector_value_get_string (&value, &str))
1329 : : return FALSE;
1330 : :
1331 : 3 : string_down = g_utf8_strdown (str, -1);
1332 : :
1333 : 3 : shumate_vector_value_set_string (out, string_down);
1334 : 3 : return TRUE;
1335 : : }
1336 : :
1337 : 3 : case EXPR_RESOLVED_LOCALE:
1338 : : {
1339 : 3 : g_autofree char *locale = NULL;
1340 : :
1341 [ - + ]: 3 : g_assert (n_expressions == 1);
1342 : :
1343 [ - + ]: 3 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1344 : : return FALSE;
1345 [ - + ]: 3 : if (!shumate_vector_value_get_collator (&value, &collator))
1346 : : return FALSE;
1347 : :
1348 [ - + ]: 3 : locale = g_strdup (g_get_language_names ()[0]);
1349 : :
1350 : : /* if there is an encoding at the end, remove it */
1351 [ + - ]: 3 : if (strchr (locale, '.'))
1352 : 3 : *strchr (locale, '.') = '\0';
1353 : :
1354 : : /* replace _ with - */
1355 : 3 : g_strdelimit (locale, "_", '-');
1356 : :
1357 : 3 : shumate_vector_value_set_string (out, locale);
1358 : 3 : return TRUE;
1359 : : }
1360 : :
1361 : 3 : case EXPR_UPCASE:
1362 : : {
1363 : 3 : const char *str;
1364 : 3 : g_autofree char *string_up = NULL;
1365 [ - + ]: 3 : g_assert (n_expressions == 1);
1366 : :
1367 [ - + ]: 3 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1368 : : return FALSE;
1369 [ - + ]: 3 : if (!shumate_vector_value_get_string (&value, &str))
1370 : : return FALSE;
1371 : :
1372 : 3 : string_up = g_utf8_strup (str, -1);
1373 : :
1374 : 3 : shumate_vector_value_set_string (out, string_up);
1375 : 3 : return TRUE;
1376 : : }
1377 : :
1378 : 21 : case EXPR_ADD:
1379 : : case EXPR_MUL:
1380 : : case EXPR_MIN:
1381 : : case EXPR_MAX:
1382 [ - + ]: 21 : g_assert (n_expressions >= 1);
1383 : :
1384 [ + - ]: 21 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1385 : : return FALSE;
1386 [ + - ]: 21 : if (!shumate_vector_value_get_number (&value, &number))
1387 : : return FALSE;
1388 : :
1389 [ + + ]: 54 : for (int i = 1; i < n_expressions; i ++)
1390 : : {
1391 [ + - ]: 39 : if (!shumate_vector_expression_eval (expressions[i], scope, &value))
1392 : : return FALSE;
1393 [ + + ]: 39 : if (!shumate_vector_value_get_number (&value, &number2))
1394 : : return FALSE;
1395 : :
1396 [ + + + + : 33 : switch (self->type)
- ]
1397 : : {
1398 : 9 : case EXPR_ADD:
1399 : 9 : number += number2;
1400 : 9 : break;
1401 : 6 : case EXPR_MUL:
1402 : 6 : number *= number2;
1403 : 6 : break;
1404 : 9 : case EXPR_MIN:
1405 [ + + ]: 9 : number = MIN (number, number2);
1406 : 9 : break;
1407 : 9 : case EXPR_MAX:
1408 [ + + ]: 9 : number = MAX (number, number2);
1409 : 9 : break;
1410 : 0 : default:
1411 : 33 : g_assert_not_reached ();
1412 : : }
1413 : : }
1414 : :
1415 : 15 : shumate_vector_value_set_number (out, number);
1416 : 15 : return TRUE;
1417 : :
1418 : 9 : case EXPR_SUB:
1419 [ - + ]: 9 : g_assert (n_expressions >= 1);
1420 [ - + ]: 9 : g_assert (n_expressions <= 2);
1421 : :
1422 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1423 : : return FALSE;
1424 [ + - ]: 9 : if (!shumate_vector_value_get_number (&value, &number))
1425 : : return FALSE;
1426 : :
1427 [ + + ]: 9 : if (n_expressions == 1)
1428 : 3 : shumate_vector_value_set_number (out, 0 - number);
1429 : : else
1430 : : {
1431 [ + - ]: 6 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1432 : : return FALSE;
1433 [ + - ]: 6 : if (!shumate_vector_value_get_number (&value2, &number2))
1434 : : return FALSE;
1435 : :
1436 : 6 : shumate_vector_value_set_number (out, number - number2);
1437 : : }
1438 : : return TRUE;
1439 : :
1440 : 36 : case EXPR_DIV:
1441 : : case EXPR_REM:
1442 : : case EXPR_POW:
1443 [ - + ]: 36 : g_assert (n_expressions == 2);
1444 : :
1445 [ + - ]: 36 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1446 : : return FALSE;
1447 [ + - ]: 36 : if (!shumate_vector_value_get_number (&value, &number))
1448 : : return FALSE;
1449 : :
1450 [ + - ]: 36 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1451 : : return FALSE;
1452 [ + - ]: 36 : if (!shumate_vector_value_get_number (&value2, &number2))
1453 : : return FALSE;
1454 : :
1455 [ + + + - ]: 36 : switch (self->type)
1456 : : {
1457 : 18 : case EXPR_DIV:
1458 [ + + ]: 18 : if (number2 == 0)
1459 [ + + + + ]: 18 : shumate_vector_value_set_number (out, number == 0 ? NAN : number > 0 ? INFINITY : -INFINITY);
1460 : : else
1461 : 3 : shumate_vector_value_set_number (out, number / number2);
1462 : : return TRUE;
1463 : :
1464 : 12 : case EXPR_REM:
1465 [ + + ]: 12 : if (number2 == 0)
1466 : 9 : shumate_vector_value_set_number (out, NAN);
1467 : : else
1468 : 3 : shumate_vector_value_set_number (out, fmod (number, number2));
1469 : : return TRUE;
1470 : :
1471 : 6 : case EXPR_POW:
1472 : 6 : number = pow (number, number2);
1473 [ + - ]: 6 : if (isnan (number))
1474 : : return FALSE;
1475 : :
1476 : 6 : shumate_vector_value_set_number (out, number);
1477 : 6 : return TRUE;
1478 : :
1479 : 0 : default:
1480 : 0 : g_assert_not_reached ();
1481 : : }
1482 : :
1483 : : return TRUE;
1484 : :
1485 : 48 : case EXPR_ABS:
1486 : : case EXPR_ACOS:
1487 : : case EXPR_ASIN:
1488 : : case EXPR_ATAN:
1489 : : case EXPR_CEIL:
1490 : : case EXPR_COS:
1491 : : case EXPR_FLOOR:
1492 : : case EXPR_LN:
1493 : : case EXPR_LOG10:
1494 : : case EXPR_LOG2:
1495 : : case EXPR_ROUND:
1496 : : case EXPR_SIN:
1497 : : case EXPR_SQRT:
1498 : : case EXPR_TAN:
1499 [ - + ]: 48 : g_assert (n_expressions == 1);
1500 : :
1501 [ + - ]: 48 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1502 : : return FALSE;
1503 [ + - ]: 48 : if (!shumate_vector_value_get_number (&value, &number))
1504 : : return FALSE;
1505 : :
1506 [ + + + + : 48 : switch (self->type)
+ + + + +
+ + + + +
- ]
1507 : : {
1508 : 6 : case EXPR_ABS:
1509 : 6 : number = fabs (number);
1510 : 6 : break;
1511 : 3 : case EXPR_ACOS:
1512 : 3 : number = acos (number);
1513 : 3 : break;
1514 : 3 : case EXPR_ASIN:
1515 : 3 : number = asin (number);
1516 : 3 : break;
1517 : 3 : case EXPR_ATAN:
1518 : 3 : number = atan (number);
1519 : 3 : break;
1520 : 3 : case EXPR_CEIL:
1521 : 3 : number = ceil (number);
1522 : 3 : break;
1523 : 3 : case EXPR_COS:
1524 : 3 : number = cos (number);
1525 : 3 : break;
1526 : 3 : case EXPR_FLOOR:
1527 : 3 : number = floor (number);
1528 : 3 : break;
1529 : 3 : case EXPR_LN:
1530 : 3 : number = log (number);
1531 : 3 : break;
1532 : 3 : case EXPR_LOG10:
1533 : 3 : number = log10 (number);
1534 : 3 : break;
1535 : 3 : case EXPR_LOG2:
1536 : 3 : number = log2 (number);
1537 : 3 : break;
1538 : 6 : case EXPR_ROUND:
1539 : 6 : number = round (number);
1540 : 6 : break;
1541 : 3 : case EXPR_SIN:
1542 : 3 : number = sin (number);
1543 : 3 : break;
1544 : 3 : case EXPR_SQRT:
1545 : 3 : number = sqrt (number);
1546 : 3 : break;
1547 : 3 : case EXPR_TAN:
1548 : 3 : number = tan (number);
1549 : 3 : break;
1550 : 0 : default:
1551 : 0 : g_assert_not_reached ();
1552 : : }
1553 : :
1554 [ + - ]: 48 : if (isnan (number))
1555 : : return FALSE;
1556 : :
1557 : 48 : shumate_vector_value_set_number (out, number);
1558 : 48 : return TRUE;
1559 : :
1560 : 6 : case EXPR_IMAGE:
1561 : : {
1562 : 2808 : g_autoptr(ShumateVectorSprite) sprite = NULL;
1563 [ - + ]: 6 : g_assert (n_expressions == 1);
1564 : :
1565 : 6 : string = shumate_vector_expression_eval_string (expressions[0], scope, NULL);
1566 [ - + ]: 6 : if (string == NULL)
1567 : : {
1568 : 0 : shumate_vector_value_unset (out);
1569 : 0 : return TRUE;
1570 : : }
1571 : :
1572 : 6 : sprite = shumate_vector_sprite_sheet_get_sprite (scope->sprites, string, scope->scale_factor);
1573 [ + + ]: 6 : if (sprite == NULL)
1574 : : {
1575 : 3 : shumate_vector_value_unset (out);
1576 : 3 : return TRUE;
1577 : : }
1578 : :
1579 : 3 : shumate_vector_value_set_image (out, sprite, string);
1580 : 3 : return TRUE;
1581 : : }
1582 : :
1583 : 18 : case EXPR_COLLATOR:
1584 [ - + ]: 18 : g_assert (n_expressions == 1);
1585 : :
1586 : 18 : collator.case_sensitive = shumate_vector_expression_eval_boolean (expressions[0], scope, FALSE);
1587 : 18 : shumate_vector_value_set_collator (out, &collator);
1588 : 18 : return TRUE;
1589 : :
1590 : 3 : case EXPR_FORMAT:
1591 : : {
1592 : 3 : FormatExpressionPart **format_expressions = (FormatExpressionPart **)self->format_parts->pdata;
1593 : 3 : n_expressions = self->format_parts->len;
1594 : 2811 : g_autoptr(GPtrArray) format_parts = g_ptr_array_new_full (n_expressions, (GDestroyNotify)shumate_vector_format_part_free);
1595 : :
1596 [ + + ]: 18 : for (int i = 0; i < n_expressions; i++)
1597 : : {
1598 [ + - ]: 33 : g_autoptr(ShumateVectorFormatPart) part = g_new0 (ShumateVectorFormatPart, 1);
1599 : :
1600 [ - + ]: 15 : if (!shumate_vector_expression_eval (format_expressions[i]->string, scope, &value))
1601 : 0 : return FALSE;
1602 : :
1603 [ + - + - ]: 15 : switch (value.type)
1604 : : {
1605 : 12 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
1606 : : {
1607 : 12 : const char *string;
1608 : 12 : shumate_vector_value_get_string (&value, &string);
1609 : :
1610 [ - + ]: 12 : if (strlen (string) == 0)
1611 : 0 : continue;
1612 : :
1613 [ - + ]: 12 : part->string = g_strdup (string);
1614 : 12 : break;
1615 : : }
1616 : :
1617 : 0 : case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
1618 : : {
1619 : 0 : part->string = shumate_vector_value_as_string (&value);
1620 : 0 : shumate_vector_value_get_image (&value, &part->sprite);
1621 : 0 : g_object_ref (part->sprite);
1622 : 0 : break;
1623 : : }
1624 : :
1625 : 3 : case SHUMATE_VECTOR_VALUE_TYPE_NULL:
1626 : 3 : continue;
1627 : :
1628 : : default:
1629 : : return FALSE;
1630 : : }
1631 : :
1632 [ + + ]: 12 : if (format_expressions[i]->text_color != NULL)
1633 : : {
1634 [ - + ]: 6 : if (!shumate_vector_expression_eval (format_expressions[i]->text_color, scope, &value))
1635 : 0 : return FALSE;
1636 : :
1637 [ + + ]: 6 : if (!shumate_vector_value_is_null (&value))
1638 : : {
1639 [ - + ]: 3 : if (!shumate_vector_value_get_color (&value, &part->text_color))
1640 : 0 : return FALSE;
1641 : 3 : part->has_text_color = TRUE;
1642 : : }
1643 : : }
1644 : :
1645 [ + + ]: 12 : if (format_expressions[i]->font_scale != NULL)
1646 : : {
1647 [ - + ]: 6 : if (!shumate_vector_expression_eval (format_expressions[i]->font_scale, scope, &value))
1648 : 0 : return FALSE;
1649 : :
1650 [ + + ]: 6 : if (!shumate_vector_value_is_null (&value))
1651 : : {
1652 [ - + ]: 3 : if (!shumate_vector_value_get_number (&value, &part->font_scale))
1653 : 0 : return FALSE;
1654 : 3 : part->has_font_scale = TRUE;
1655 : : }
1656 : : }
1657 : :
1658 : 12 : g_ptr_array_add (format_parts, g_steal_pointer (&part));
1659 : : }
1660 : :
1661 : 3 : shumate_vector_value_set_formatted (out, format_parts);
1662 : 3 : return TRUE;
1663 : : }
1664 : :
1665 : 6 : case EXPR_GEOMETRY_TYPE:
1666 : : {
1667 : 6 : VectorTile__Tile__Feature *feature = shumate_vector_reader_iter_get_feature_struct (scope->reader);
1668 : 6 : ShumateGeometryType geometry_type;
1669 : :
1670 [ - + ]: 6 : if (feature == NULL)
1671 : : {
1672 : 0 : shumate_vector_value_unset (out);
1673 : 0 : return TRUE;
1674 : : }
1675 : :
1676 : 6 : geometry_type = shumate_vector_reader_iter_get_feature_geometry_type (scope->reader);
1677 : :
1678 [ + - - - : 6 : switch (geometry_type)
- - - ]
1679 : : {
1680 : 6 : case SHUMATE_GEOMETRY_TYPE_POINT:
1681 : 6 : shumate_vector_value_set_string (out, "Point");
1682 : 6 : return TRUE;
1683 : 0 : case SHUMATE_GEOMETRY_TYPE_MULTIPOINT:
1684 : 0 : shumate_vector_value_set_string (out, "MultiPoint");
1685 : 0 : return TRUE;
1686 : 0 : case SHUMATE_GEOMETRY_TYPE_LINESTRING:
1687 : 0 : shumate_vector_value_set_string (out, "LineString");
1688 : 0 : return TRUE;
1689 : 0 : case SHUMATE_GEOMETRY_TYPE_MULTILINESTRING:
1690 : 0 : shumate_vector_value_set_string (out, "MultiLineString");
1691 : 0 : return TRUE;
1692 : 0 : case SHUMATE_GEOMETRY_TYPE_POLYGON:
1693 : 0 : shumate_vector_value_set_string (out, "Polygon");
1694 : 0 : return TRUE;
1695 : 0 : case SHUMATE_GEOMETRY_TYPE_MULTIPOLYGON:
1696 : 0 : shumate_vector_value_set_string (out, "MultiPolygon");
1697 : 0 : return TRUE;
1698 : 0 : default:
1699 : 0 : shumate_vector_value_unset (out);
1700 : 0 : return TRUE;
1701 : : }
1702 : : }
1703 : :
1704 : 0 : case EXPR_ID:
1705 : : {
1706 : 0 : VectorTile__Tile__Feature *feature = shumate_vector_reader_iter_get_feature_struct (scope->reader);
1707 : :
1708 [ # # # # ]: 0 : if (!feature || !feature->has_id)
1709 : 0 : shumate_vector_value_unset (out);
1710 : : else
1711 : 0 : shumate_vector_value_set_number (out, feature->id);
1712 : : return TRUE;
1713 : : }
1714 : :
1715 : 42 : case EXPR_ZOOM:
1716 : 42 : shumate_vector_value_set_number (out, scope->zoom_level);
1717 : 42 : return TRUE;
1718 : :
1719 : 9 : case EXPR_AT:
1720 : : {
1721 : 9 : GPtrArray *array;
1722 [ - + ]: 9 : g_assert (n_expressions == 2);
1723 : :
1724 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1725 : : return FALSE;
1726 [ + - ]: 9 : if (!shumate_vector_value_get_number (&value, &number))
1727 : : return FALSE;
1728 : :
1729 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1730 : : return FALSE;
1731 [ + - ]: 9 : if (!(array = shumate_vector_value_get_array (&value2)))
1732 : : return FALSE;
1733 : :
1734 [ + - + + : 9 : if (number < 0 || number >= array->len || number != (int)number)
+ - ]
1735 : : return FALSE;
1736 : :
1737 : 6 : shumate_vector_value_copy (g_ptr_array_index (array, (int)number), out);
1738 : 6 : return TRUE;
1739 : : }
1740 : :
1741 : 18 : case EXPR_INDEX_OF:
1742 [ - + ]: 18 : g_assert (n_expressions == 2 || n_expressions == 3);
1743 : :
1744 [ + - ]: 18 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1745 : : return FALSE;
1746 : :
1747 [ + + ]: 18 : if (n_expressions == 3)
1748 : : {
1749 [ + - ]: 3 : if (!shumate_vector_expression_eval (expressions[2], scope, &value2))
1750 : : return FALSE;
1751 [ + - ]: 3 : if (!shumate_vector_value_get_number (&value2, &number))
1752 : : return FALSE;
1753 [ + - + - ]: 3 : if (number != (int)number || number < 0)
1754 : : return FALSE;
1755 : : }
1756 : : else
1757 : 15 : number = 0;
1758 : :
1759 [ + - ]: 18 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1760 : : return FALSE;
1761 : :
1762 [ + + - ]: 18 : switch (value2.type)
1763 : : {
1764 : 12 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
1765 : : {
1766 : 12 : const char *string;
1767 : 12 : const char *substring;
1768 : 12 : const char *found;
1769 : :
1770 : 12 : shumate_vector_value_get_string (&value2, &string);
1771 [ + - ]: 12 : if (!shumate_vector_value_get_string (&value, &substring))
1772 : : return FALSE;
1773 : :
1774 [ - + ]: 12 : number = MIN (number, g_utf8_strlen (string, -1));
1775 : 12 : found = strstr (g_utf8_offset_to_pointer (string, (int)number), substring);
1776 : :
1777 [ + + ]: 12 : if (found == NULL)
1778 : 6 : shumate_vector_value_set_number (out, -1);
1779 : : else
1780 : 6 : shumate_vector_value_set_number (out, g_utf8_pointer_to_offset (string, found));
1781 : :
1782 : : return TRUE;
1783 : : }
1784 : :
1785 : 6 : case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
1786 : : {
1787 : 6 : GPtrArray *array = shumate_vector_value_get_array (&value2);
1788 : :
1789 [ + + ]: 24 : for (; number < array->len; number ++)
1790 : : {
1791 [ + + ]: 15 : if (shumate_vector_value_equal (g_ptr_array_index (array, (int)number), &value))
1792 : : {
1793 : 3 : shumate_vector_value_set_number (out, number);
1794 : 3 : return TRUE;
1795 : : }
1796 : : }
1797 : :
1798 : 3 : shumate_vector_value_set_number (out, -1);
1799 : 3 : return TRUE;
1800 : : }
1801 : :
1802 : : default:
1803 : : return FALSE;
1804 : : }
1805 : :
1806 : 9 : case EXPR_LENGTH:
1807 [ - + ]: 9 : g_assert (n_expressions == 1);
1808 : :
1809 [ + - ]: 9 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1810 : : return FALSE;
1811 : :
1812 [ + + - ]: 9 : switch (value.type)
1813 : : {
1814 : 3 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
1815 : : {
1816 : 3 : const char *string;
1817 : 3 : shumate_vector_value_get_string (&value, &string);
1818 : 3 : shumate_vector_value_set_number (out, g_utf8_strlen (string, -1));
1819 : 3 : return TRUE;
1820 : : }
1821 : :
1822 : 6 : case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
1823 : : {
1824 : 6 : GPtrArray *array = shumate_vector_value_get_array (&value);
1825 : 6 : shumate_vector_value_set_number (out, array->len);
1826 : 6 : return TRUE;
1827 : : }
1828 : :
1829 : : default:
1830 : : return FALSE;
1831 : : }
1832 : :
1833 : 54 : case EXPR_SLICE:
1834 : : {
1835 : 54 : double start, end;
1836 : :
1837 [ - + ]: 54 : g_assert (n_expressions == 2 || n_expressions == 3);
1838 : :
1839 [ - + ]: 54 : if (!shumate_vector_expression_eval (expressions[0], scope, &value))
1840 : : return FALSE;
1841 : :
1842 [ - + ]: 54 : if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
1843 : : return FALSE;
1844 [ - + ]: 54 : if (!shumate_vector_value_get_number (&value2, &start))
1845 : : return FALSE;
1846 [ - + ]: 54 : if (start != (int)start)
1847 : : return FALSE;
1848 : :
1849 [ + + ]: 54 : if (n_expressions == 3)
1850 : : {
1851 [ - + ]: 33 : if (!shumate_vector_expression_eval (expressions[2], scope, &value2))
1852 : : return FALSE;
1853 [ - + ]: 33 : if (!shumate_vector_value_get_number (&value2, &end))
1854 : : return FALSE;
1855 [ - + ]: 33 : if (end != (int)end)
1856 : : return FALSE;
1857 : : }
1858 : : else
1859 : 21 : end = G_MAXDOUBLE;
1860 : :
1861 [ - + + ]: 54 : switch (value.type)
1862 : : {
1863 : 27 : case SHUMATE_VECTOR_VALUE_TYPE_STRING:
1864 : : {
1865 : 27 : const char *input;
1866 : 27 : const char *start_ptr, *end_ptr;
1867 : 27 : long len;
1868 : :
1869 : 27 : shumate_vector_value_get_string (&value, &input);
1870 : 27 : len = g_utf8_strlen (input, -1);
1871 : :
1872 [ + + ]: 27 : if (start < 0)
1873 [ + + ]: 12 : start = MAX (len + start, 0);
1874 : : else
1875 [ + + ]: 21 : start = MIN (start, len);
1876 : :
1877 [ + + ]: 27 : if (end < 0)
1878 [ + + ]: 12 : end = MAX (len + end, 0);
1879 : : else
1880 [ + + ]: 33 : end = MIN (end, len);
1881 : :
1882 [ + + ]: 27 : if (start >= end)
1883 : : {
1884 : 9 : shumate_vector_value_set_string (out, "");
1885 : 9 : return TRUE;
1886 : : }
1887 : :
1888 : 18 : start_ptr = g_utf8_offset_to_pointer (input, (int)start);
1889 : 18 : end_ptr = g_utf8_offset_to_pointer (input, (int)end);
1890 : :
1891 : 18 : string = g_strndup (start_ptr, end_ptr - start_ptr);
1892 : 18 : shumate_vector_value_set_string (out, string);
1893 : 18 : return TRUE;
1894 : : }
1895 : :
1896 : 27 : case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
1897 : : {
1898 : 27 : GPtrArray *array = shumate_vector_value_get_array (&value);
1899 : 27 : long len = array->len;
1900 : :
1901 [ + + ]: 27 : if (start < 0)
1902 [ + + ]: 12 : start = MAX (len + start, 0);
1903 : : else
1904 [ + + ]: 21 : start = MIN (start, len);
1905 : :
1906 [ + + ]: 27 : if (end < 0)
1907 [ + + ]: 12 : end = MAX (len + end, 0);
1908 : : else
1909 [ + + ]: 30 : end = MIN (end, len);
1910 : :
1911 : 27 : shumate_vector_value_start_array (out);
1912 [ + + ]: 66 : for (int i = start; i < end; i ++)
1913 : : {
1914 : 39 : shumate_vector_value_copy (
1915 : 39 : g_ptr_array_index (array, (int)i),
1916 : : &value2
1917 : : );
1918 : 39 : shumate_vector_value_array_append (out, &value2);
1919 : : }
1920 : : return TRUE;
1921 : : }
1922 : :
1923 : : default:
1924 : : return FALSE;
1925 : : }
1926 : : }
1927 : :
1928 : 6 : case EXPR_FAST_NOT_HAS:
1929 : 6 : inverted = TRUE;
1930 : 12 : G_GNUC_FALLTHROUGH;
1931 : 12 : case EXPR_FAST_HAS:
1932 : 12 : shumate_vector_render_scope_get_variable (scope, self->fast_get_key, &value);
1933 : 12 : shumate_vector_value_set_boolean (out, !shumate_vector_value_is_null (&value) ^ inverted);
1934 : 12 : return TRUE;
1935 : :
1936 : 9 : case EXPR_FAST_GET:
1937 : 9 : shumate_vector_render_scope_get_variable (scope, self->fast_get_key, out);
1938 : 9 : return TRUE;
1939 : :
1940 : 3 : case EXPR_FAST_NOT_IN:
1941 : 3 : inverted = TRUE;
1942 : 6 : G_GNUC_FALLTHROUGH;
1943 : 6 : case EXPR_FAST_IN:
1944 : 6 : shumate_vector_render_scope_get_variable (scope, self->fast_in.key, &value);
1945 : 6 : shumate_vector_value_set_boolean (out, g_hash_table_contains (self->fast_in.haystack, &value) ^ inverted);
1946 : 6 : return TRUE;
1947 : :
1948 : 3 : case EXPR_FAST_NE:
1949 : 3 : inverted = TRUE;
1950 : 12 : G_GNUC_FALLTHROUGH;
1951 : 12 : case EXPR_FAST_EQ:
1952 : 12 : shumate_vector_render_scope_get_variable (scope, self->fast_eq.key, &value);
1953 : 12 : shumate_vector_value_set_boolean (out, shumate_vector_value_equal (&value, &self->fast_eq.value) ^ inverted);
1954 : 12 : return TRUE;
1955 : :
1956 : 6 : case EXPR_FAST_NOT_GEOMETRY_TYPE:
1957 : 6 : inverted = TRUE;
1958 : 9 : G_GNUC_FALLTHROUGH;
1959 : 9 : case EXPR_FAST_GEOMETRY_TYPE:
1960 : : {
1961 : 9 : VectorTile__Tile__Feature *feature = shumate_vector_reader_iter_get_feature_struct (scope->reader);
1962 : 9 : gboolean result = FALSE;
1963 : :
1964 [ - + ]: 9 : if (feature == NULL)
1965 : : {
1966 : 0 : shumate_vector_value_unset (out);
1967 : 0 : return TRUE;
1968 : : }
1969 : :
1970 [ + - - - ]: 9 : switch (feature->type)
1971 : : {
1972 : 9 : case VECTOR_TILE__TILE__GEOM_TYPE__POINT:
1973 [ + + ]: 9 : if (self->fast_geometry_type & GEOM_ANY_POINT)
1974 : : {
1975 [ + - ]: 3 : if ((self->fast_geometry_type & GEOM_ANY_POINT) == GEOM_ANY_POINT)
1976 : : result = TRUE;
1977 : : else
1978 : : {
1979 : 3 : ShumateGeometryType geometry_type = shumate_vector_reader_iter_get_feature_geometry_type (scope->reader);
1980 [ + - ]: 3 : if (self->fast_geometry_type & GEOM_SINGLE_POINT)
1981 : 3 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_POINT);
1982 [ # # ]: 0 : else if (self->fast_geometry_type & GEOM_MULTI_POINT)
1983 : 0 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_MULTIPOINT);
1984 : : else
1985 : 0 : g_assert_not_reached ();
1986 : : }
1987 : : }
1988 : : else
1989 : : result = FALSE;
1990 : : break;
1991 : :
1992 : 0 : case VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING:
1993 [ # # ]: 0 : if (self->fast_geometry_type & GEOM_ANY_LINESTRING)
1994 : : {
1995 [ # # ]: 0 : if ((self->fast_geometry_type & GEOM_ANY_LINESTRING) == GEOM_ANY_LINESTRING)
1996 : : result = TRUE;
1997 : : else
1998 : : {
1999 : 0 : ShumateGeometryType geometry_type = shumate_vector_reader_iter_get_feature_geometry_type (scope->reader);
2000 [ # # ]: 0 : if (self->fast_geometry_type & GEOM_SINGLE_LINESTRING)
2001 : 0 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_LINESTRING);
2002 [ # # ]: 0 : else if (self->fast_geometry_type & GEOM_MULTI_LINESTRING)
2003 : 0 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_MULTILINESTRING);
2004 : : else
2005 : 0 : g_assert_not_reached ();
2006 : : }
2007 : : }
2008 : : else
2009 : : result = FALSE;
2010 : : break;
2011 : :
2012 : 0 : case VECTOR_TILE__TILE__GEOM_TYPE__POLYGON:
2013 [ # # ]: 0 : if (self->fast_geometry_type & GEOM_ANY_POLYGON)
2014 : : {
2015 [ # # ]: 0 : if ((self->fast_geometry_type & GEOM_ANY_POLYGON) == GEOM_ANY_POLYGON)
2016 : : result = TRUE;
2017 : : else
2018 : : {
2019 : 0 : ShumateGeometryType geometry_type = shumate_vector_reader_iter_get_feature_geometry_type (scope->reader);
2020 [ # # ]: 0 : if (self->fast_geometry_type & GEOM_SINGLE_POLYGON)
2021 : 0 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_POLYGON);
2022 [ # # ]: 0 : else if (self->fast_geometry_type & GEOM_MULTI_POLYGON)
2023 : 0 : result = (geometry_type == SHUMATE_GEOMETRY_TYPE_MULTIPOLYGON);
2024 : : else
2025 : 0 : g_assert_not_reached ();
2026 : : }
2027 : : }
2028 : : else
2029 : : result = FALSE;
2030 : : break;
2031 : :
2032 : : default:
2033 : : result = FALSE;
2034 : : break;
2035 : : }
2036 : :
2037 : 9 : shumate_vector_value_set_boolean (out, result ^ inverted);
2038 : 9 : return TRUE;
2039 : : }
2040 : :
2041 : 0 : default:
2042 : 2808 : g_assert_not_reached ();
2043 : : }
2044 : : }
2045 : :
2046 : : static ShumateVectorIndexBitset *
2047 : 33 : shumate_vector_expression_filter_eval_bitset (ShumateVectorExpression *expr,
2048 : : ShumateVectorRenderScope *scope,
2049 : : ShumateVectorIndexBitset *mask)
2050 : : {
2051 : 33 : ShumateVectorExpressionFilter *self = (ShumateVectorExpressionFilter *)expr;
2052 : 33 : VectorTile__Tile__Layer *layer = shumate_vector_reader_iter_get_layer_struct (scope->reader);
2053 : 33 : ShumateVectorIndexBitset *bitset = NULL;
2054 : :
2055 [ + - + + : 33 : switch (self->type)
+ - + +
+ ]
2056 : : {
2057 : 12 : case EXPR_LITERAL:
2058 : : {
2059 : 12 : gboolean result = FALSE;
2060 : 12 : bitset = shumate_vector_index_bitset_new (layer->n_features);
2061 : 12 : shumate_vector_value_get_boolean (&self->value, &result);
2062 [ + + ]: 12 : if (result)
2063 : 6 : shumate_vector_index_bitset_not (bitset);
2064 : 12 : return bitset;
2065 : : }
2066 : :
2067 : 0 : case EXPR_FAST_EQ:
2068 : : case EXPR_FAST_NE:
2069 : 0 : bitset = shumate_vector_index_get_bitset (scope->index, scope->source_layer_idx, self->fast_eq.key, &self->fast_eq.value);
2070 [ # # ]: 0 : if (bitset == NULL)
2071 : 0 : bitset = shumate_vector_index_bitset_new (layer->n_features);
2072 : : else
2073 : 0 : bitset = shumate_vector_index_bitset_copy (bitset);
2074 [ # # ]: 0 : if (self->type == EXPR_FAST_NE)
2075 : 0 : shumate_vector_index_bitset_not (bitset);
2076 : : return bitset;
2077 : :
2078 : 3 : case EXPR_FAST_NOT_IN:
2079 : : case EXPR_FAST_IN:
2080 : : {
2081 : 3 : GHashTableIter iter;
2082 : 3 : ShumateVectorValue *value;
2083 : 3 : bitset = shumate_vector_index_bitset_new (layer->n_features);
2084 : 3 : g_hash_table_iter_init (&iter, self->fast_in.haystack);
2085 [ + + ]: 12 : while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&value))
2086 : : {
2087 : 6 : ShumateVectorIndexBitset *current_bitset = shumate_vector_index_get_bitset (scope->index, scope->source_layer_idx, self->fast_in.key, value);
2088 [ + + ]: 6 : if (current_bitset != NULL)
2089 : 3 : shumate_vector_index_bitset_or (bitset, current_bitset);
2090 : : }
2091 : :
2092 [ - + ]: 3 : if (self->type == EXPR_FAST_NOT_IN)
2093 : 0 : shumate_vector_index_bitset_not (bitset);
2094 : :
2095 : 3 : return bitset;
2096 : : }
2097 : :
2098 : 3 : case EXPR_FAST_HAS:
2099 : : case EXPR_FAST_NOT_HAS:
2100 : 3 : bitset = shumate_vector_index_get_bitset_has (scope->index, scope->source_layer_idx, self->fast_get_key);
2101 [ - + ]: 3 : if (bitset == NULL)
2102 : 0 : bitset = shumate_vector_index_bitset_new (layer->n_features);
2103 : : else
2104 : 3 : bitset = shumate_vector_index_bitset_copy (bitset);
2105 [ - + ]: 3 : if (self->type == EXPR_FAST_NOT_HAS)
2106 : 0 : shumate_vector_index_bitset_not (bitset);
2107 : : return bitset;
2108 : :
2109 : 6 : case EXPR_FAST_GEOMETRY_TYPE:
2110 : : case EXPR_FAST_NOT_GEOMETRY_TYPE:
2111 : : {
2112 : 6 : ShumateVectorIndexBitset *current_bitset;
2113 : 6 : bitset = shumate_vector_index_bitset_new (layer->n_features);
2114 : :
2115 [ - - - + ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_POINT)
2116 : : {
2117 : 0 : case GEOM_ANY_POINT:
2118 : 0 : current_bitset = shumate_vector_index_get_bitset_broad_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_POINT);
2119 : 0 : break;
2120 : 0 : case GEOM_SINGLE_POINT:
2121 : 0 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_POINT);
2122 : 0 : break;
2123 : 0 : case GEOM_MULTI_POINT:
2124 : 0 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_MULTIPOINT);
2125 : 0 : break;
2126 : : default:
2127 : : current_bitset = NULL;
2128 : : break;
2129 : : }
2130 [ # # ]: 0 : if (current_bitset != NULL)
2131 : 0 : shumate_vector_index_bitset_or (bitset, current_bitset);
2132 : :
2133 [ + + - - ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_LINESTRING)
2134 : : {
2135 : 3 : case GEOM_ANY_LINESTRING:
2136 : 3 : current_bitset = shumate_vector_index_get_bitset_broad_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_LINESTRING);
2137 : 3 : break;
2138 : 3 : case GEOM_SINGLE_LINESTRING:
2139 : 3 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_LINESTRING);
2140 : 3 : break;
2141 : 0 : case GEOM_MULTI_LINESTRING:
2142 : 0 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_MULTILINESTRING);
2143 : 0 : break;
2144 : : default:
2145 : : current_bitset = NULL;
2146 : : break;
2147 : : }
2148 [ + - ]: 6 : if (current_bitset != NULL)
2149 : 6 : shumate_vector_index_bitset_or (bitset, current_bitset);
2150 : :
2151 [ - - - + ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_POLYGON)
2152 : : {
2153 : 0 : case GEOM_ANY_POLYGON:
2154 : 0 : current_bitset = shumate_vector_index_get_bitset_broad_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_POLYGON);
2155 : 0 : break;
2156 : 0 : case GEOM_SINGLE_POLYGON:
2157 : 0 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_POLYGON);
2158 : 0 : break;
2159 : 0 : case GEOM_MULTI_POLYGON:
2160 : 0 : current_bitset = shumate_vector_index_get_bitset_geometry_type (scope->index, scope->source_layer_idx, SHUMATE_GEOMETRY_TYPE_MULTIPOLYGON);
2161 : 0 : break;
2162 : : default:
2163 : : current_bitset = NULL;
2164 : : break;
2165 : : }
2166 [ # # ]: 0 : if (current_bitset != NULL)
2167 : 0 : shumate_vector_index_bitset_or (bitset, current_bitset);
2168 : :
2169 : : return bitset;
2170 : : }
2171 : :
2172 : 0 : case EXPR_NOT:
2173 : 0 : bitset = shumate_vector_expression_filter_eval_bitset (g_ptr_array_index (self->expressions, 0), scope, mask);
2174 : 0 : shumate_vector_index_bitset_not (bitset);
2175 : 0 : return bitset;
2176 : :
2177 : : case EXPR_ALL:
2178 [ + + ]: 9 : for (int i = 0; i < self->expressions->len; i ++)
2179 : : {
2180 : 6 : ShumateVectorIndexBitset *current_bitset = shumate_vector_expression_filter_eval_bitset (g_ptr_array_index (self->expressions, i), scope, bitset);
2181 [ + + ]: 6 : if (i == 0)
2182 : : bitset = current_bitset;
2183 : : else
2184 : : {
2185 : 3 : shumate_vector_index_bitset_and (bitset, current_bitset);
2186 : 3 : shumate_vector_index_bitset_free (current_bitset);
2187 : : }
2188 : :
2189 [ + - ]: 6 : if (bitset == NULL)
2190 : : return NULL;
2191 : : }
2192 : : return bitset;
2193 : :
2194 : : case EXPR_ANY:
2195 : : case EXPR_NONE:
2196 [ + + ]: 9 : for (int i = 0; i < self->expressions->len; i ++)
2197 : : {
2198 : 6 : ShumateVectorIndexBitset *current_bitset;
2199 : 6 : current_bitset = shumate_vector_expression_filter_eval_bitset (g_ptr_array_index (self->expressions, i), scope, bitset);
2200 : : /* Invert the result bitset so we can pass it to the mask parameter of eval_bitset(), saving some work
2201 : : if there are any non-bitset-optimized expressions */
2202 : 6 : shumate_vector_index_bitset_not (current_bitset);
2203 [ + + ]: 6 : if (i == 0)
2204 : : bitset = current_bitset;
2205 : : else
2206 : : {
2207 : 3 : shumate_vector_index_bitset_and (bitset, current_bitset);
2208 : 3 : shumate_vector_index_bitset_free (current_bitset);
2209 : : }
2210 : : }
2211 : :
2212 [ + - ]: 3 : if (self->type == EXPR_ANY)
2213 : 3 : shumate_vector_index_bitset_not (bitset);
2214 : :
2215 : : return bitset;
2216 : :
2217 : 3 : default:
2218 : 3 : return SHUMATE_VECTOR_EXPRESSION_CLASS (shumate_vector_expression_filter_parent_class)->eval_bitset (expr, scope, mask);
2219 : : }
2220 : : }
2221 : :
2222 : : static void
2223 : 33 : shumate_vector_expression_filter_collect_indexes (ShumateVectorExpression *expr,
2224 : : const char *layer_name,
2225 : : ShumateVectorIndexDescription *index_description)
2226 : : {
2227 : 33 : ShumateVectorExpressionFilter *self = (ShumateVectorExpressionFilter *)expr;
2228 : :
2229 [ + - + + : 33 : switch (self->type)
+ + ]
2230 : : {
2231 : 0 : case EXPR_FAST_EQ:
2232 : : case EXPR_FAST_NE:
2233 : 0 : shumate_vector_index_description_add (index_description, layer_name, self->fast_eq.key, &self->fast_eq.value);
2234 : 0 : break;
2235 : :
2236 : 3 : case EXPR_FAST_IN:
2237 : : case EXPR_FAST_NOT_IN:
2238 : : {
2239 : 3 : GHashTableIter iter;
2240 : 3 : ShumateVectorValue *value;
2241 : 3 : g_hash_table_iter_init (&iter, self->fast_in.haystack);
2242 [ + + ]: 9 : while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&value))
2243 : 6 : shumate_vector_index_description_add (index_description, layer_name, self->fast_in.key, value);
2244 : 3 : break;
2245 : : }
2246 : :
2247 : 3 : case EXPR_FAST_HAS:
2248 : : case EXPR_FAST_NOT_HAS:
2249 : 3 : shumate_vector_index_description_add_has_index (index_description, layer_name, self->fast_get_key);
2250 : 3 : break;
2251 : :
2252 : 6 : case EXPR_FAST_GEOMETRY_TYPE:
2253 : : case EXPR_FAST_NOT_GEOMETRY_TYPE:
2254 [ - - - + ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_POINT)
2255 : : {
2256 : 0 : case GEOM_ANY_POINT:
2257 : 0 : shumate_vector_index_description_add_broad_geometry_type (index_description, layer_name);
2258 : 0 : break;
2259 : 0 : case GEOM_SINGLE_POINT:
2260 : 0 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2261 : 0 : break;
2262 : 0 : case GEOM_MULTI_POINT:
2263 : 0 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2264 : 0 : break;
2265 : : }
2266 : :
2267 [ + + - - ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_LINESTRING)
2268 : : {
2269 : 3 : case GEOM_ANY_LINESTRING:
2270 : 3 : shumate_vector_index_description_add_broad_geometry_type (index_description, layer_name);
2271 : 3 : break;
2272 : 3 : case GEOM_SINGLE_LINESTRING:
2273 : 3 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2274 : 3 : break;
2275 : 0 : case GEOM_MULTI_LINESTRING:
2276 : 0 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2277 : 0 : break;
2278 : : }
2279 : :
2280 [ - - - + ]: 6 : switch (self->fast_geometry_type & GEOM_ANY_POLYGON)
2281 : : {
2282 : 0 : case GEOM_ANY_POLYGON:
2283 : 0 : shumate_vector_index_description_add_broad_geometry_type (index_description, layer_name);
2284 : 0 : break;
2285 : 0 : case GEOM_SINGLE_POLYGON:
2286 : 0 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2287 : 0 : break;
2288 : 0 : case GEOM_MULTI_POLYGON:
2289 : 0 : shumate_vector_index_description_add_geometry_type (index_description, layer_name);
2290 : 0 : break;
2291 : : }
2292 : : break;
2293 : :
2294 : : case EXPR_ANY:
2295 : : case EXPR_ALL:
2296 : : case EXPR_NONE:
2297 : : case EXPR_NOT:
2298 [ + + ]: 18 : for (int i = 0; i < self->expressions->len; i ++)
2299 : 12 : shumate_vector_expression_collect_indexes (g_ptr_array_index (self->expressions, i), layer_name, index_description);
2300 : : break;
2301 : :
2302 : : default:
2303 : : break;
2304 : : }
2305 : 33 : }
2306 : :
2307 : : static void
2308 : 12 : shumate_vector_expression_filter_class_init (ShumateVectorExpressionFilterClass *klass)
2309 : : {
2310 : 12 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
2311 : 12 : ShumateVectorExpressionClass *expr_class = SHUMATE_VECTOR_EXPRESSION_CLASS (klass);
2312 : :
2313 : 12 : object_class->finalize = shumate_vector_expression_filter_finalize;
2314 : 12 : expr_class->eval = shumate_vector_expression_filter_eval;
2315 : 12 : expr_class->eval_bitset = shumate_vector_expression_filter_eval_bitset;
2316 : 12 : expr_class->collect_indexes = shumate_vector_expression_filter_collect_indexes;
2317 : : }
2318 : :
2319 : :
2320 : : static void
2321 : 2715 : shumate_vector_expression_filter_init (ShumateVectorExpressionFilter *self)
2322 : : {
2323 : 2715 : }
|