GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 82.5% 254 / 0 / 308
Functions: 84.6% 33 / 0 / 39
Branches: 67.6% 123 / 0 / 182

shumate/shumate-vector-value.c
Line Branch Exec Source
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 #include "shumate-vector-renderer.h"
19 #include "shumate-vector-value-private.h"
20
21 /**
22 * ShumateVectorValue: (copy-func shumate_vector_value_dup) (free-func shumate_vector_value_free)
23 *
24 * A mutable value used in the vector style specification.
25 *
26 * Since: 1.6
27 */
28
29
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 7 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 7 not taken.
2 G_DEFINE_BOXED_TYPE (ShumateVectorValue, shumate_vector_value, shumate_vector_value_dup, shumate_vector_value_free);
30
31 enum {
32 COLOR_UNSET,
33 COLOR_SET,
34 COLOR_INVALID,
35 };
36
37
38 /**
39 * shumate_vector_value_new:
40 *
41 * Creates a new [struct@VectorValue] with a null value.
42 *
43 * Returns: (transfer full): a new [struct@VectorValue] with a null value
44 * Since: 1.6
45 */
46 ShumateVectorValue *
47 ✗ shumate_vector_value_new (void)
48 {
49 ✗ ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
50 ✗ return self;
51 }
52
53 /**
54 * shumate_vector_value_new_from_value:
55 * @value: a [struct@GObject.Value]
56 *
57 * Creates a new [struct@VectorValue] from a [struct@GObject.Value]. Returns
58 * `NULL` if the GValue does not contain a compatible value.
59 *
60 * Returns: (transfer full) (nullable): a new [struct@VectorValue] with the value from @value
61 * Since: 1.6
62 */
63 ShumateVectorValue *
64 4 shumate_vector_value_new_from_value (const GValue *value)
65 {
66 4 ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
67
2/2
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 8 taken 2 times.
4 if (shumate_vector_value_set_from_g_value (self, value))
68 return self;
69 else
70 {
71
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 7 not taken.
2 g_free (self);
72 return NULL;
73 }
74 }
75
76 /**
77 * shumate_vector_value_new_number:
78 * @number: a number value
79 *
80 * Creates a new [struct@VectorValue] with a number value.
81 *
82 * Returns: (transfer full): a new [struct@VectorValue] with the given number value
83 * Since: 1.6
84 */
85 ShumateVectorValue *
86 2 shumate_vector_value_new_number (double number)
87 {
88 2 ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
89 2 shumate_vector_value_set_number (self, number);
90 2 return self;
91 }
92
93 /**
94 * shumate_vector_value_new_string:
95 * @string: a string value
96 *
97 * Creates a new [struct@VectorValue] with a string value.
98 *
99 * Returns: (transfer full): a new [struct@VectorValue] with the given string value
100 * Since: 1.6
101 */
102 ShumateVectorValue *
103 ✗ shumate_vector_value_new_string (const char *string)
104 {
105 ✗ ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
106 ✗ shumate_vector_value_set_string (self, string);
107 ✗ return self;
108 }
109
110 /**
111 * shumate_vector_value_new_boolean:
112 * @boolean: a boolean value
113 *
114 * Creates a new [struct@VectorValue] with a boolean value.
115 *
116 * Returns: (transfer full): a new [struct@VectorValue] with the given boolean value
117 * Since: 1.6
118 */
119 ShumateVectorValue *
120 ✗ shumate_vector_value_new_boolean (gboolean boolean)
121 {
122 ✗ ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
123 ✗ shumate_vector_value_set_boolean (self, boolean);
124 ✗ return self;
125 }
126
127 /**
128 * shumate_vector_value_new_color:
129 * @color: a [struct@Gdk.RGBA]
130 *
131 * Creates a new [struct@VectorValue] with a color value.
132 *
133 * Returns: (transfer full): a new [struct@VectorValue] with the given color value
134 * Since: 1.6
135 */
136 ShumateVectorValue *
137 ✗ shumate_vector_value_new_color (const GdkRGBA *color)
138 {
139 ✗ ShumateVectorValue *self = g_new0 (ShumateVectorValue, 1);
140 ✗ shumate_vector_value_set_color (self, color);
141 ✗ return self;
142 }
143
144 gboolean
145 1142 shumate_vector_value_set_from_json_literal (ShumateVectorValue *self, JsonNode *node, GError **error)
146 {
147
2/2
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 6 taken 1136 times.
1142 if (JSON_NODE_HOLDS_NULL (node))
148 {
149 6 shumate_vector_value_unset (self);
150 6 return TRUE;
151 }
152
2/2
✓ Branch 7 → 8 taken 1062 times.
✓ Branch 7 → 16 taken 74 times.
1136 else if (JSON_NODE_HOLDS_VALUE (node))
153 {
154 1062 g_auto(GValue) gvalue = G_VALUE_INIT;
155
156 1062 json_node_get_value (node, &gvalue);
157
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 14 taken 1062 times.
1062 if (!shumate_vector_value_set_from_g_value (self, &gvalue))
158 {
159 ✗ g_set_error (error,
160 SHUMATE_STYLE_ERROR,
161 SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
162 "Unsupported literal value in expression");
163 ✗ return FALSE;
164 }
165
166 return TRUE;
167 }
168
1/2
✓ Branch 17 → 18 taken 74 times.
✗ Branch 17 → 30 not taken.
74 else if (JSON_NODE_HOLDS_ARRAY (node))
169 {
170 74 g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
171 74 JsonArray *array = json_node_get_array (node);
172
173 74 shumate_vector_value_start_array (self);
174
175
2/2
✓ Branch 27 → 22 taken 178 times.
✓ Branch 27 → 28 taken 74 times.
252 for (int i = 0, n = json_array_get_length (array); i < n; i ++)
176 {
177
1/2
✓ Branch 24 → 25 taken 178 times.
✗ Branch 24 → 28 not taken.
178 if (!shumate_vector_value_set_from_json_literal (&value, json_array_get_element (array, i), error))
178 return FALSE;
179
180 178 shumate_vector_value_array_append (self, &value);
181 }
182
183 return TRUE;
184 }
185 ✗ else if (JSON_NODE_HOLDS_OBJECT (node))
186 {
187 ✗ g_set_error (error,
188 SHUMATE_STYLE_ERROR,
189 SHUMATE_STYLE_ERROR_UNSUPPORTED,
190 "Object literals are not supported");
191 ✗ return FALSE;
192 }
193 else
194 {
195 ✗ g_warn_if_reached ();
196 ✗ return FALSE;
197 }
198 }
199
200 gboolean
201 1138 shumate_vector_value_set_from_g_value (ShumateVectorValue *self, const GValue *value)
202 {
203 2276 g_auto(GValue) tmp = G_VALUE_INIT;
204
205
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1138 times.
1138 if (value == NULL)
206 ✗ shumate_vector_value_unset (self);
207
2/2
✓ Branch 5 → 6 taken 562 times.
✓ Branch 5 → 10 taken 576 times.
1138 else if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_DOUBLE))
208 {
209 562 g_value_init (&tmp, G_TYPE_DOUBLE);
210 562 g_value_transform (value, &tmp);
211 562 shumate_vector_value_set_number (self, g_value_get_double (&tmp));
212 }
213
2/2
✓ Branch 11 → 12 taken 96 times.
✓ Branch 11 → 16 taken 480 times.
576 else if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_BOOLEAN))
214 {
215 96 g_value_init (&tmp, G_TYPE_BOOLEAN);
216 96 g_value_transform (value, &tmp);
217 96 shumate_vector_value_set_boolean (self, g_value_get_boolean (&tmp));
218 }
219
2/2
✓ Branch 17 → 18 taken 478 times.
✓ Branch 17 → 22 taken 2 times.
480 else if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING))
220 {
221 478 g_value_init (&tmp, G_TYPE_STRING);
222 478 g_value_transform (value, &tmp);
223 478 shumate_vector_value_set_string (self, g_value_get_string (&tmp));
224 }
225 else
226 return FALSE;
227
228 return TRUE;
229 }
230
231
232 /**
233 * shumate_vector_value_free:
234 * @self: a [struct@VectorValue]
235 *
236 * Frees a [struct@VectorValue].
237 *
238 * Since: 1.6
239 */
240 void
241 300 shumate_vector_value_free (ShumateVectorValue *self)
242 {
243 300 shumate_vector_value_unset (self);
244
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 300 times.
300 g_free (self);
245 300 }
246
247
248 /**
249 * shumate_vector_value_unset:
250 * @self: a [struct@VectorValue]
251 *
252 * Sets @self to a null value.
253 *
254 * Since: 1.6
255 */
256 void
257 14048 shumate_vector_value_unset (ShumateVectorValue *self)
258 {
259
5/5
✓ Branch 2 → 3 taken 1502 times.
✓ Branch 2 → 5 taken 240 times.
✓ Branch 2 → 7 taken 2 times.
✓ Branch 2 → 11 taken 2 times.
✓ Branch 2 → 13 taken 12302 times.
14048 switch (self->type)
260 {
261 1502 case SHUMATE_VECTOR_VALUE_TYPE_STRING:
262
1/2
✓ Branch 3 → 4 taken 1502 times.
✗ Branch 3 → 13 not taken.
1502 g_clear_pointer (&self->string, g_free);
263 break;
264 240 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
265
1/2
✓ Branch 5 → 6 taken 240 times.
✗ Branch 5 → 13 not taken.
240 g_clear_pointer (&self->array, g_ptr_array_unref);
266 break;
267 2 case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
268
1/2
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 9 not taken.
2 g_clear_object (&self->image);
269
1/2
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 13 not taken.
2 g_clear_pointer (&self->image_name, g_free);
270 break;
271 2 case SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING:
272
1/2
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
2 g_clear_pointer (&self->formatted_string, g_ptr_array_unref);
273 break;
274 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
275 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
276 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
277 case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
278 case SHUMATE_VECTOR_VALUE_TYPE_COLLATOR:
279 break;
280 }
281
282 14048 self->type = SHUMATE_VECTOR_VALUE_TYPE_NULL;
283 14048 }
284
285
286 /**
287 * shumate_vector_value_is_null:
288 * @self: a [struct@VectorValue]
289 *
290 * Checks if @self is a null value.
291 *
292 * Returns: %TRUE if @self is a null value, %FALSE otherwise
293 *
294 * Since: 1.6
295 */
296 gboolean
297 34 shumate_vector_value_is_null (ShumateVectorValue *self)
298 {
299 34 return self->type == SHUMATE_VECTOR_VALUE_TYPE_NULL;
300 }
301
302
303 void
304 2718 shumate_vector_value_copy (ShumateVectorValue *self, ShumateVectorValue *out)
305 {
306 2718 shumate_vector_value_unset (out);
307 2718 *out = *self;
308
309
3/5
✓ Branch 3 → 4 taken 868 times.
✓ Branch 3 → 13 taken 142 times.
✗ Branch 3 → 15 not taken.
✗ Branch 3 → 25 not taken.
✓ Branch 3 → 27 taken 1708 times.
2718 switch (self->type)
310 {
311 868 case SHUMATE_VECTOR_VALUE_TYPE_STRING:
312
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 868 times.
868 out->string = g_strdup (self->string);
313 868 break;
314 142 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
315 142 out->array = g_ptr_array_ref (self->array);
316 142 break;
317 ✗ case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
318 ✗ out->image = g_object_ref (self->image);
319 ✗ out->image_name = g_strdup (self->image_name);
320 ✗ break;
321 ✗ case SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING:
322 ✗ out->formatted_string = g_ptr_array_ref (self->formatted_string);
323 ✗ break;
324 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
325 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
326 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
327 case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
328 case SHUMATE_VECTOR_VALUE_TYPE_COLLATOR:
329 break;
330 }
331 2718 }
332
333 void
334 6 shumate_vector_value_steal (ShumateVectorValue *self, ShumateVectorValue *out)
335 {
336 6 *out = *self;
337 6 self->type = SHUMATE_VECTOR_VALUE_TYPE_NULL;
338 6 }
339
340
341 /**
342 * shumate_vector_value_dup:
343 * @self: a [struct@VectorValue]
344 *
345 * Creates a duplicate of @self.
346 *
347 * Returns: (transfer full): a new [struct@VectorValue] which is a duplicate of @self
348 *
349 * Since: 1.6
350 */
351 ShumateVectorValue *
352 30 shumate_vector_value_dup (ShumateVectorValue *self)
353 {
354 30 ShumateVectorValue *new_value = g_new0 (ShumateVectorValue, 1);
355 30 shumate_vector_value_copy (self, new_value);
356 30 return new_value;
357 }
358
359 /**
360 * shumate_vector_value_get_value_type:
361 * @self: a [struct@VectorValue]
362 *
363 * Gets the type of value stored in @self.
364 *
365 * Returns: the type of @self
366 *
367 * Since: 1.6
368 */
369 ShumateVectorValueType
370 ✗ shumate_vector_value_get_value_type (ShumateVectorValue *self)
371 {
372 ✗ return self->type;
373 }
374
375 /**
376 * shumate_vector_value_set_number:
377 * @self: a [struct@VectorValue]
378 * @number: a number value
379 *
380 * Sets @self to a number value.
381 *
382 * Since: 1.6
383 */
384 void
385 756 shumate_vector_value_set_number (ShumateVectorValue *self, double number)
386 {
387 756 shumate_vector_value_unset (self);
388 756 self->type = SHUMATE_VECTOR_VALUE_TYPE_NUMBER;
389 756 self->number = number;
390 756 }
391
392
393 /**
394 * shumate_vector_value_get_number:
395 * @self: a [struct@VectorValue]
396 * @number: (out): a location to store the number value
397 *
398 * Gets the number value of @self.
399 *
400 * Returns: %TRUE if @self is a number value and @number was set, %FALSE otherwise
401 * Since: 1.6
402 */
403 gboolean
404 576 shumate_vector_value_get_number (ShumateVectorValue *self, double *number)
405 {
406
2/2
✓ Branch 2 → 3 taken 426 times.
✓ Branch 2 → 4 taken 150 times.
576 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_NUMBER)
407 return FALSE;
408
409 426 *number = self->number;
410 426 return TRUE;
411 }
412
413
414 /**
415 * shumate_vector_value_set_boolean:
416 * @self: a [struct@VectorValue]
417 * @boolean: a boolean value
418 *
419 * Sets @self to a boolean value.
420 *
421 * Since: 1.6
422 */
423 void
424 486 shumate_vector_value_set_boolean (ShumateVectorValue *self, gboolean boolean)
425 {
426 486 shumate_vector_value_unset (self);
427 486 self->type = SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN;
428 486 self->boolean = boolean;
429 486 }
430
431
432 /**
433 * shumate_vector_value_get_boolean:
434 * @self: a [struct@VectorValue]
435 * @boolean: (out): a location to store the boolean value
436 *
437 * Gets the boolean value of @self.
438 *
439 * Returns: %TRUE if @self is a boolean value and @boolean was set, %FALSE otherwise
440 * Since: 1.6
441 */
442 gboolean
443 498 shumate_vector_value_get_boolean (ShumateVectorValue *self, gboolean *boolean)
444 {
445
2/2
✓ Branch 2 → 3 taken 416 times.
✓ Branch 2 → 4 taken 82 times.
498 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN)
446 return FALSE;
447
448 416 *boolean = self->boolean;
449 416 return TRUE;
450 }
451
452
453 /**
454 * shumate_vector_value_set_string:
455 * @self: a [struct@VectorValue]
456 * @string: a string value
457 *
458 * Sets @self to a string value.
459 *
460 * Since: 1.6
461 */
462 void
463 634 shumate_vector_value_set_string (ShumateVectorValue *self, const char *string)
464 {
465 634 shumate_vector_value_unset (self);
466 634 self->type = SHUMATE_VECTOR_VALUE_TYPE_STRING;
467
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 634 times.
634 self->string = g_strdup (string);
468 634 self->color_state = COLOR_UNSET;
469 634 }
470
471
472 /**
473 * shumate_vector_value_get_string:
474 * @self: a [struct@VectorValue]
475 * @string: (out) (transfer none) (nullable): a location to store the string value
476 *
477 * Gets the string value of @self.
478 *
479 * Returns: %TRUE if @self is a string value and @string was set, %FALSE otherwise
480 * Since: 1.6
481 */
482 gboolean
483 288 shumate_vector_value_get_string (ShumateVectorValue *self, const char **string)
484 {
485
2/2
✓ Branch 2 → 3 taken 162 times.
✓ Branch 2 → 4 taken 126 times.
288 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_STRING)
486 return FALSE;
487
488 162 *string = self->string;
489 162 return TRUE;
490 }
491
492
493 /**
494 * shumate_vector_value_set_color:
495 * @self: a [struct@VectorValue]
496 * @color: a [struct@Gdk.RGBA]
497 *
498 * Sets @self to a color value.
499 *
500 * Since: 1.6
501 */
502 void
503 30 shumate_vector_value_set_color (ShumateVectorValue *self, const GdkRGBA *color)
504 {
505 30 shumate_vector_value_unset (self);
506 30 self->type = SHUMATE_VECTOR_VALUE_TYPE_COLOR;
507 30 self->color = *color;
508 30 }
509
510
511 /**
512 * shumate_vector_value_get_color:
513 * @self: a [struct@VectorValue]
514 * @color: (out): a location to store the color value
515 *
516 * Gets the color value of @self.
517 *
518 * If @self is a string value, it will attempt to parse the string as a color.
519 *
520 * Returns: %TRUE if @self is a color value and @color was set, %FALSE otherwise
521 * Since: 1.6
522 */
523 gboolean
524 82 shumate_vector_value_get_color (ShumateVectorValue *self, GdkRGBA *color)
525 {
526
2/2
✓ Branch 2 → 3 taken 54 times.
✓ Branch 2 → 10 taken 28 times.
82 if (self->type == SHUMATE_VECTOR_VALUE_TYPE_STRING)
527 {
528
2/2
✓ Branch 3 → 4 taken 50 times.
✓ Branch 3 → 8 taken 4 times.
54 if (self->color_state == COLOR_UNSET)
529 {
530
2/2
✓ Branch 5 → 6 taken 46 times.
✓ Branch 5 → 7 taken 4 times.
50 if (gdk_rgba_parse (&self->color, self->string))
531 46 self->color_state = COLOR_SET;
532 else
533 4 self->color_state = COLOR_INVALID;
534 }
535
536
2/2
✓ Branch 8 → 9 taken 48 times.
✓ Branch 8 → 12 taken 6 times.
54 if (self->color_state == COLOR_SET)
537 {
538 48 *color = self->color;
539 48 return TRUE;
540 }
541 else
542 return FALSE;
543 }
544
545
2/2
✓ Branch 10 → 11 taken 8 times.
✓ Branch 10 → 12 taken 20 times.
28 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_COLOR)
546 return FALSE;
547
548 8 *color = self->color;
549 8 return TRUE;
550 }
551
552
553 /**
554 * shumate_vector_value_start_array:
555 * @self: a [struct@VectorValue]
556 *
557 * Sets @self to an empty array value.
558 *
559 * Since: 1.6
560 */
561 void
562 98 shumate_vector_value_start_array (ShumateVectorValue *self)
563 {
564 98 shumate_vector_value_unset (self);
565 98 self->type = SHUMATE_VECTOR_VALUE_TYPE_ARRAY;
566 98 self->array = g_ptr_array_new_with_free_func ((GDestroyNotify)shumate_vector_value_free);
567 98 }
568
569
570 /**
571 * shumate_vector_value_array_append:
572 * @self: an array [struct@VectorValue]
573 * @element: a [struct@VectorValue] to append to the array
574 *
575 * Appends @element to the array value of @self. The value of @element is copied.
576 *
577 * Since: 1.6
578 */
579 void
580 224 shumate_vector_value_array_append (ShumateVectorValue *self, ShumateVectorValue *element)
581 {
582 448 g_autoptr(ShumateVectorValue) copy = g_new0 (ShumateVectorValue, 1);
583
584
1/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 224 times.
✗ Branch 5 → 8 not taken.
✗ Branch 5 → 9 not taken.
224 g_return_if_fail (self->type == SHUMATE_VECTOR_VALUE_TYPE_ARRAY);
585
586 224 shumate_vector_value_copy (element, copy);
587 224 g_ptr_array_add (self->array, g_steal_pointer (&copy));
588 }
589
590
591 GPtrArray *
592 42 shumate_vector_value_get_array (ShumateVectorValue *self)
593 {
594
2/2
✓ Branch 2 → 3 taken 32 times.
✓ Branch 2 → 4 taken 10 times.
42 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_ARRAY)
595 return NULL;
596
597 32 return self->array;
598 }
599
600
601 void
602 2 shumate_vector_value_set_image (ShumateVectorValue *self,
603 ShumateVectorSprite *image,
604 const char *image_name)
605 {
606
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 g_assert (SHUMATE_IS_VECTOR_SPRITE (image));
607
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 9 not taken.
2 g_assert (image_name != NULL);
608
609 2 shumate_vector_value_unset (self);
610 2 self->type = SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE;
611 2 self->image = g_object_ref (image);
612
1/2
✗ Branch 8 → 10 not taken.
✓ Branch 8 → 12 taken 2 times.
2 self->image_name = g_strdup (image_name);
613 2 }
614
615 gboolean
616 ✗ shumate_vector_value_get_image (ShumateVectorValue *self, ShumateVectorSprite **image)
617 {
618 ✗ if (self->type != SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE)
619 return FALSE;
620
621 ✗ *image = self->image;
622 ✗ return TRUE;
623 }
624
625 void
626 2 shumate_vector_value_set_formatted (ShumateVectorValue *self,
627 GPtrArray *format_parts)
628 {
629 2 shumate_vector_value_unset (self);
630 2 self->type = SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING;
631 2 self->formatted_string = g_ptr_array_ref (format_parts);
632 2 }
633
634 gboolean
635 2 shumate_vector_value_get_formatted (ShumateVectorValue *self,
636 GPtrArray **format_parts)
637 {
638
1/2
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
2 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING)
639 return FALSE;
640
641 2 *format_parts = self->formatted_string;
642 2 return TRUE;
643 }
644
645 void
646 20 shumate_vector_format_part_free (ShumateVectorFormatPart *format_part)
647 {
648
2/2
✓ Branch 2 → 3 taken 18 times.
✓ Branch 2 → 4 taken 2 times.
20 g_clear_pointer (&format_part->string, g_free);
649
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 20 times.
20 g_clear_object (&format_part->sprite);
650
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 20 times.
20 g_free (format_part);
651 20 }
652
653 void
654 12 shumate_vector_value_set_collator (ShumateVectorValue *self,
655 ShumateVectorCollator *collator)
656 {
657 12 shumate_vector_value_unset (self);
658 12 self->type = SHUMATE_VECTOR_VALUE_TYPE_COLLATOR;
659 12 self->collator = *collator;
660 12 }
661
662 gboolean
663 10 shumate_vector_value_get_collator (ShumateVectorValue *self,
664 ShumateVectorCollator *collator)
665 {
666
1/2
✓ Branch 2 → 3 taken 10 times.
✗ Branch 2 → 4 not taken.
10 if (self->type != SHUMATE_VECTOR_VALUE_TYPE_COLLATOR)
667 return FALSE;
668
669 10 *collator = self->collator;
670 10 return TRUE;
671 }
672
673
674 /**
675 * shumate_vector_value_hash:
676 * @self: a [struct@VectorValue]
677 *
678 * Calculates a hash value for @self.
679 *
680 * Returns: a hash value for @self
681 * Since: 1.6
682 */
683 gint
684 64 shumate_vector_value_hash (ShumateVectorValue *self)
685 {
686
3/8
✓ Branch 2 → 3 taken 16 times.
✓ Branch 2 → 5 taken 4 times.
✓ Branch 2 → 6 taken 44 times.
✗ Branch 2 → 8 not taken.
✗ Branch 2 → 11 not taken.
✗ Branch 2 → 13 not taken.
✗ Branch 2 → 15 not taken.
✗ Branch 2 → 16 not taken.
64 switch (self->type)
687 {
688 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
689 return 0;
690 16 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
691 16 return g_double_hash (&self->number);
692 4 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
693 4 return !!self->boolean;
694 44 case SHUMATE_VECTOR_VALUE_TYPE_STRING:
695 44 return g_str_hash (self->string);
696 ✗ case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
697 ✗ return gdk_rgba_hash (&self->color);
698 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
699 {
700 guint hash = 0;
701
702 ✗ for (int i = 0; i < self->array->len; i ++)
703 ✗ hash ^= shumate_vector_value_hash (g_ptr_array_index (self->array, i));
704
705 ✗ return hash;
706 }
707 ✗ case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
708 ✗ return g_str_hash (self->image_name);
709 case SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING:
710 case SHUMATE_VECTOR_VALUE_TYPE_COLLATOR:
711 /* Not supported */
712 return 0;
713 ✗ default:
714 ✗ g_assert_not_reached ();
715 }
716 }
717
718
719 /**
720 * shumate_vector_value_equal:
721 * @a: (nullable): a [struct@VectorValue]
722 * @b: (nullable): a [struct@VectorValue]
723 *
724 * Compares two [struct@VectorValue]s for equality.
725 *
726 * Either argument may be `NULL`, which is treated as equal to a [struct@VectorValue] of type [enum@Shumate.VectorValueType.NULL].
727 *
728 * Returns: %TRUE if @a and @b are equal, %FALSE otherwise
729 * Since: 1.6
730 */
731 gboolean
732 392 shumate_vector_value_equal (ShumateVectorValue *a, ShumateVectorValue *b)
733 {
734
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 390 times.
392 if (a == NULL && b == NULL)
735 return TRUE;
736
2/2
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 386 times.
390 else if (a == NULL)
737 4 return b->type == SHUMATE_VECTOR_VALUE_TYPE_NULL;
738
2/2
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 8 taken 382 times.
386 else if (b == NULL)
739 4 return a->type == SHUMATE_VECTOR_VALUE_TYPE_NULL;
740
741
2/2
✓ Branch 8 → 9 taken 362 times.
✓ Branch 8 → 23 taken 20 times.
382 if (a->type != b->type)
742 return FALSE;
743
744
6/9
✓ Branch 9 → 3 taken 14 times.
✓ Branch 9 → 10 taken 146 times.
✓ Branch 9 → 11 taken 26 times.
✓ Branch 9 → 12 taken 138 times.
✓ Branch 9 → 14 taken 10 times.
✓ Branch 9 → 15 taken 28 times.
✗ Branch 9 → 20 not taken.
✗ Branch 9 → 22 not taken.
✗ Branch 9 → 23 not taken.
362 switch (a->type)
745 {
746 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
747 return TRUE;
748 146 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
749 146 return a->number == b->number;
750 26 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
751 26 return a->boolean == b->boolean;
752 138 case SHUMATE_VECTOR_VALUE_TYPE_STRING:
753 138 return g_strcmp0 (a->string, b->string) == 0;
754 10 case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
755 10 return gdk_rgba_equal (&a->color, &b->color);
756 28 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
757
2/2
✓ Branch 15 → 19 taken 26 times.
✓ Branch 15 → 23 taken 2 times.
28 if (a->array->len != b->array->len)
758 return FALSE;
759
760
2/2
✓ Branch 19 → 3 taken 26 times.
✓ Branch 19 → 16 taken 44 times.
70 for (int i = 0; i < a->array->len; i ++)
761
1/2
✓ Branch 17 → 18 taken 44 times.
✗ Branch 17 → 23 not taken.
44 if (!shumate_vector_value_equal (g_ptr_array_index (a->array, i), g_ptr_array_index (b->array, i)))
762 return FALSE;
763
764 return TRUE;
765 ✗ case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
766 ✗ return g_strcmp0 (a->image_name, b->image_name) == 0;
767 case SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING:
768 case SHUMATE_VECTOR_VALUE_TYPE_COLLATOR:
769 /* Not supported */
770 return FALSE;
771 ✗ default:
772 ✗ g_assert_not_reached ();
773 }
774 }
775
776 static JsonNode *
777 20 shumate_vector_value_as_json (ShumateVectorValue *value)
778 {
779 20 JsonNode *node;
780
781
5/5
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 5 taken 4 times.
✓ Branch 2 → 9 taken 4 times.
✓ Branch 2 → 12 taken 6 times.
✓ Branch 2 → 23 taken 4 times.
20 switch (value->type)
782 {
783 2 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
784 2 node = json_node_new (JSON_NODE_NULL);
785 2 return node;
786 4 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
787 4 node = json_node_new (JSON_NODE_VALUE);
788
2/2
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 8 taken 2 times.
4 if (fmod (value->number, 1) == 0)
789 2 json_node_set_int (node, value->number);
790 else
791 2 json_node_set_double (node, value->number);
792 return node;
793 4 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
794 4 node = json_node_new (JSON_NODE_VALUE);
795 4 json_node_set_boolean (node, value->boolean);
796 4 return node;
797 6 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
798 {
799 6 g_autoptr(JsonBuilder) builder = json_builder_new ();
800 6 json_builder_begin_array (builder);
801
2/2
✓ Branch 18 → 15 taken 16 times.
✓ Branch 18 → 19 taken 6 times.
28 for (int i = 0; i < value->array->len; i ++)
802 {
803 16 ShumateVectorValue *child = g_ptr_array_index (value->array, i);
804 16 json_builder_add_value (builder, shumate_vector_value_as_json (child));
805 }
806
807 6 json_builder_end_array (builder);
808
1/2
✓ Branch 21 → 22 taken 6 times.
✗ Branch 21 → 28 not taken.
6 return json_builder_get_root (builder);
809 }
810 4 default:
811 {
812 4 g_autofree char *string = shumate_vector_value_as_string (value);
813 4 node = json_node_new (JSON_NODE_VALUE);
814 4 json_node_set_string (node, string);
815 4 return node;
816 }
817 }
818 }
819
820
821 char *
822 82 shumate_vector_value_as_string (ShumateVectorValue *self)
823 {
824
7/10
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 5 taken 16 times.
✓ Branch 2 → 15 taken 6 times.
✓ Branch 2 → 21 taken 48 times.
✓ Branch 2 → 29 taken 4 times.
✓ Branch 2 → 39 taken 4 times.
✗ Branch 2 → 43 not taken.
✓ Branch 2 → 51 taken 2 times.
✗ Branch 2 → 70 not taken.
✗ Branch 2 → 72 not taken.
82 switch (self->type)
825 {
826 case SHUMATE_VECTOR_VALUE_TYPE_NULL:
827 2 return g_strdup ("");
828 16 case SHUMATE_VECTOR_VALUE_TYPE_NUMBER:
829 /* printf produces nan, inf, and -inf, but the spec says we should act like ECMAScript
830 which uses NaN, -Infinity, and Infinity */
831
2/2
✓ Branch 5 → 6 taken 8 times.
✓ Branch 5 → 7 taken 8 times.
16 if (G_UNLIKELY (isnan (self->number)))
832 8 return g_strdup ("NaN");
833
2/2
✓ Branch 6 → 9 taken 4 times.
✓ Branch 6 → 10 taken 4 times.
8 else if (G_UNLIKELY (isinf (self->number)))
834 {
835
2/2
✓ Branch 9 → 11 taken 2 times.
✓ Branch 9 → 13 taken 2 times.
4 if (self->number < 0)
836 2 return g_strdup ("-Infinity");
837 else
838 2 return g_strdup ("Infinity");
839 }
840 else
841 4 return g_strdup_printf ("%g", self->number);
842 6 case SHUMATE_VECTOR_VALUE_TYPE_BOOLEAN:
843
2/2
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 17 taken 4 times.
6 return g_strdup (self->boolean ? "true" : "false");
844 48 case SHUMATE_VECTOR_VALUE_TYPE_STRING:
845
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 48 times.
48 return g_strdup (self->string);
846 4 case SHUMATE_VECTOR_VALUE_TYPE_COLOR:
847 /* gdk_rgba_to_string() produces `rgb(...)` when alpha is ~1, which is
848 not consistent with the MapLibre spec */
849 4 return g_strdup_printf (
850 "rgba(%d,%d,%d,%g)",
851 4 (int)round (255 * CLAMP (self->color.red, 0, 1)),
852
1/2
✓ Branch 36 → 37 taken 4 times.
✗ Branch 36 → 38 not taken.
4 (int)round (255 * CLAMP (self->color.green, 0, 1)),
853
2/4
✓ Branch 32 → 33 taken 4 times.
✗ Branch 32 → 34 not taken.
✓ Branch 34 → 35 taken 4 times.
✗ Branch 34 → 36 not taken.
8 (int)round (255 * CLAMP (self->color.blue, 0, 1)),
854
2/4
✓ Branch 29 → 30 taken 4 times.
✗ Branch 29 → 32 not taken.
✓ Branch 30 → 31 taken 4 times.
✗ Branch 30 → 32 not taken.
4 CLAMP (self->color.alpha, 0, 1)
855 );
856 4 case SHUMATE_VECTOR_VALUE_TYPE_ARRAY:
857 {
858 4 g_autoptr(JsonNode) node = shumate_vector_value_as_json (self);
859
1/2
✓ Branch 41 → 42 taken 4 times.
✗ Branch 41 → 73 not taken.
4 return json_to_string (node, FALSE);
860 }
861 ✗ case SHUMATE_VECTOR_VALUE_TYPE_RESOLVED_IMAGE:
862 ✗ return g_strdup (self->image_name);
863 2 case SHUMATE_VECTOR_VALUE_TYPE_FORMATTED_STRING:
864 {
865 2 g_autoptr(GString) result = g_string_new ("");
866
867
2/2
✓ Branch 66 → 53 taken 8 times.
✓ Branch 66 → 67 taken 2 times.
12 for (int i = 0; i < self->formatted_string->len; i ++)
868 {
869 8 ShumateVectorFormatPart *part = g_ptr_array_index (self->formatted_string, i);
870
1/2
✓ Branch 53 → 54 taken 8 times.
✗ Branch 53 → 65 not taken.
8 if (!part->sprite)
871
1/2
✓ Branch 54 → 55 taken 8 times.
✗ Branch 54 → 56 not taken.
16 g_string_append (result, part->string);
872 }
873
874 2 return g_string_free (g_steal_pointer (&result), FALSE);
875 }
876 case SHUMATE_VECTOR_VALUE_TYPE_COLLATOR:
877 /* Not supported */
878 ✗ return g_strdup ("");
879 ✗ default:
880 ✗ g_assert_not_reached ();
881 }
882 }
883