[libshumate] vector: Add string format expressions
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libshumate] vector: Add string format expressions
- Date: Thu, 23 Jun 2022 21:16:32 +0000 (UTC)
commit cc45563e8c91a909084c4e87c4bda5c52bcc12f6
Author: James Westman <james jwestman net>
Date: Wed Dec 22 21:34:14 2021 -0600
vector: Add string format expressions
shumate/meson.build | 2 +
.../shumate-vector-expression-format-private.h | 29 +++++
shumate/vector/shumate-vector-expression-format.c | 123 +++++++++++++++++++++
shumate/vector/shumate-vector-expression.c | 7 +-
shumate/vector/shumate-vector-value-private.h | 2 +
shumate/vector/shumate-vector-value.c | 21 ++++
tests/vector-expression.c | 31 ++++++
7 files changed, 214 insertions(+), 1 deletion(-)
---
diff --git a/shumate/meson.build b/shumate/meson.build
index 5ee22be..7f387fd 100644
--- a/shumate/meson.build
+++ b/shumate/meson.build
@@ -34,6 +34,7 @@ libshumate_private_h = [
'vector/shumate-vector-background-layer-private.h',
'vector/shumate-vector-expression-private.h',
'vector/shumate-vector-expression-filter-private.h',
+ 'vector/shumate-vector-expression-format-private.h',
'vector/shumate-vector-expression-interpolate-private.h',
'vector/shumate-vector-expression-literal-private.h',
'vector/shumate-vector-fill-layer-private.h',
@@ -156,6 +157,7 @@ if get_option('vector_renderer')
'vector/shumate-vector-expression.c',
'vector/shumate-vector-expression-interpolate.c',
'vector/shumate-vector-expression-filter.c',
+ 'vector/shumate-vector-expression-format.c',
'vector/shumate-vector-expression-literal.c',
'vector/shumate-vector-fill-layer.c',
'vector/shumate-vector-layer.c',
diff --git a/shumate/vector/shumate-vector-expression-format-private.h
b/shumate/vector/shumate-vector-expression-format-private.h
new file mode 100644
index 0000000..18f6fe5
--- /dev/null
+++ b/shumate/vector/shumate-vector-expression-format-private.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "shumate-vector-expression-private.h"
+
+G_BEGIN_DECLS
+
+#define SHUMATE_TYPE_VECTOR_EXPRESSION_FORMAT (shumate_vector_expression_format_get_type())
+G_DECLARE_FINAL_TYPE (ShumateVectorExpressionFormat, shumate_vector_expression_format, SHUMATE,
VECTOR_EXPRESSION_FORMAT, ShumateVectorExpression)
+
+ShumateVectorExpression *shumate_vector_expression_format_new (const char *format, GError **error);
+
+G_END_DECLS
diff --git a/shumate/vector/shumate-vector-expression-format.c
b/shumate/vector/shumate-vector-expression-format.c
new file mode 100644
index 0000000..0826d22
--- /dev/null
+++ b/shumate/vector/shumate-vector-expression-format.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 James Westman <james jwestman net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "shumate-vector-renderer.h"
+#include "shumate-vector-expression-format-private.h"
+#include "shumate-vector-value-private.h"
+
+struct _ShumateVectorExpressionFormat
+{
+ ShumateVectorExpression parent_instance;
+
+ /* A list of format segments. Even-indexed segments are literals, every
+ * other segment is a variable. */
+ char **format;
+};
+
+G_DEFINE_TYPE (ShumateVectorExpressionFormat, shumate_vector_expression_format,
SHUMATE_TYPE_VECTOR_EXPRESSION)
+
+
+ShumateVectorExpression *
+shumate_vector_expression_format_new (const char *format, GError **error)
+{
+ g_autoptr(ShumateVectorExpressionFormat) self = g_object_new (SHUMATE_TYPE_VECTOR_EXPRESSION_FORMAT, NULL);
+ int balance = 0;
+
+ /* Ensure the braces in the format string are balanced and not nested */
+ for (int i = 0, n = strlen (format); i < n; i ++)
+ {
+ if (format[i] == '{')
+ balance ++;
+ else if (format[i] == '}')
+ balance --;
+
+ if (balance != 0 && balance != 1)
+ {
+ g_set_error (error,
+ SHUMATE_STYLE_ERROR,
+ SHUMATE_STYLE_ERROR_INVALID_EXPRESSION,
+ "Format string `%s` is nested or unbalanced",
+ format);
+ return NULL;
+ }
+ }
+
+ self->format = g_strsplit_set (format, "{}", 0);
+
+ return (ShumateVectorExpression *)g_steal_pointer (&self);
+}
+
+static void
+shumate_vector_expression_format_finalize (GObject *object)
+{
+ ShumateVectorExpressionFormat *self = (ShumateVectorExpressionFormat *)object;
+
+ g_clear_pointer (&self->format, g_strfreev);
+
+ G_OBJECT_CLASS (shumate_vector_expression_format_parent_class)->finalize (object);
+}
+
+
+static gboolean
+shumate_vector_expression_format_eval (ShumateVectorExpression *expr,
+ ShumateVectorRenderScope *scope,
+ ShumateVectorValue *out)
+{
+ ShumateVectorExpressionFormat *self = (ShumateVectorExpressionFormat *)expr;
+ g_autoptr(GString) string = g_string_new ("");
+ ShumateVectorValue value = SHUMATE_VECTOR_VALUE_INIT;
+ char *variable_val;
+ int i = 0;
+
+ while (TRUE)
+ {
+ if (self->format[i] == NULL)
+ break;
+
+ g_string_append (string, self->format[i]);
+ i ++;
+
+ if (self->format[i] == NULL)
+ break;
+
+ shumate_vector_render_scope_get_variable (scope, self->format[i], &value);
+ variable_val = shumate_vector_value_as_string (&value);
+ g_string_append (string, variable_val);
+ g_free (variable_val);
+ shumate_vector_value_unset (&value);
+ i ++;
+ }
+
+ shumate_vector_value_set_string (out, string->str);
+ return TRUE;
+}
+
+
+static void
+shumate_vector_expression_format_class_init (ShumateVectorExpressionFormatClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ShumateVectorExpressionClass *expr_class = SHUMATE_VECTOR_EXPRESSION_CLASS (klass);
+
+ object_class->finalize = shumate_vector_expression_format_finalize;
+ expr_class->eval = shumate_vector_expression_format_eval;
+}
+
+static void
+shumate_vector_expression_format_init (ShumateVectorExpressionFormat *self)
+{
+}
diff --git a/shumate/vector/shumate-vector-expression.c b/shumate/vector/shumate-vector-expression.c
index 42d04b1..b31ac54 100644
--- a/shumate/vector/shumate-vector-expression.c
+++ b/shumate/vector/shumate-vector-expression.c
@@ -19,6 +19,7 @@
#include "shumate-vector-renderer.h"
#include "shumate-vector-expression-private.h"
#include "shumate-vector-expression-filter-private.h"
+#include "shumate-vector-expression-format-private.h"
#include "shumate-vector-expression-interpolate-private.h"
#include "shumate-vector-expression-literal-private.h"
#include "shumate-vector-value-private.h"
@@ -36,6 +37,7 @@ shumate_vector_expression_from_json (JsonNode *json, GError **error)
{
g_auto(GValue) gvalue = G_VALUE_INIT;
g_auto(ShumateVectorValue) value = SHUMATE_VECTOR_VALUE_INIT;
+ const char *string;
json_node_get_value (json, &gvalue);
if (!shumate_vector_value_set_from_g_value (&value, &gvalue))
@@ -47,7 +49,10 @@ shumate_vector_expression_from_json (JsonNode *json, GError **error)
return NULL;
}
- return shumate_vector_expression_literal_new (&value);
+ if (shumate_vector_value_get_string (&value, &string))
+ return shumate_vector_expression_format_new (string, error);
+ else
+ return shumate_vector_expression_literal_new (&value);
}
else if (JSON_NODE_HOLDS_OBJECT (json))
return shumate_vector_expression_interpolate_from_json_obj (json_node_get_object (json), error);
diff --git a/shumate/vector/shumate-vector-value-private.h b/shumate/vector/shumate-vector-value-private.h
index 33ad778..0676a1e 100644
--- a/shumate/vector/shumate-vector-value-private.h
+++ b/shumate/vector/shumate-vector-value-private.h
@@ -61,3 +61,5 @@ void shumate_vector_value_set_color (ShumateVectorValue *self, GdkRGBA *color);
gboolean shumate_vector_value_get_color (ShumateVectorValue *self, GdkRGBA *color);
gboolean shumate_vector_value_equal (ShumateVectorValue *a, ShumateVectorValue *b);
+
+char *shumate_vector_value_as_string (ShumateVectorValue *self);
diff --git a/shumate/vector/shumate-vector-value.c b/shumate/vector/shumate-vector-value.c
index 4d1751e..6f5f8d4 100644
--- a/shumate/vector/shumate-vector-value.c
+++ b/shumate/vector/shumate-vector-value.c
@@ -234,3 +234,24 @@ shumate_vector_value_equal (ShumateVectorValue *a, ShumateVectorValue *b)
g_assert_not_reached ();
}
}
+
+
+char *
+shumate_vector_value_as_string (ShumateVectorValue *self)
+{
+ switch (self->type)
+ {
+ case TYPE_NULL:
+ return g_strdup ("");
+ case TYPE_NUMBER:
+ return g_strdup_printf ("%f", self->number);
+ case TYPE_BOOLEAN:
+ return g_strdup (self->boolean ? "true" : "false");
+ case TYPE_STRING:
+ return g_strdup (self->string);
+ case TYPE_COLOR:
+ return gdk_rgba_to_string (&self->color);
+ default:
+ g_assert_not_reached ();
+ }
+}
diff --git a/tests/vector-expression.c b/tests/vector-expression.c
index c9b33e7..1f319f5 100644
--- a/tests/vector-expression.c
+++ b/tests/vector-expression.c
@@ -224,6 +224,36 @@ test_vector_expression_filter_errors (void)
}
+static void
+test_vector_expression_format ()
+{
+ GError *error = NULL;
+ g_autoptr(GBytes) vector_data = NULL;
+ gconstpointer data;
+ gsize len;
+ ShumateVectorRenderScope scope;
+ g_autoptr(JsonNode) node = json_from_string ("\"{name}\"", NULL);
+ g_autoptr(ShumateVectorExpression) expression;
+
+ expression = shumate_vector_expression_from_json (node, &error);
+ g_assert_no_error (error);
+
+ vector_data = g_resources_lookup_data ("/org/gnome/shumate/Tests/0.pbf", G_RESOURCE_LOOKUP_FLAGS_NONE,
NULL);
+ g_assert_no_error (error);
+
+ data = g_bytes_get_data (vector_data, &len);
+ scope.tile = vector_tile__tile__unpack (NULL, len, data);
+ g_assert_nonnull (scope.tile);
+
+ scope.zoom_level = 10;
+
+ g_assert_true (shumate_vector_render_scope_find_layer (&scope, "helloworld"));
+ scope.feature = scope.layer->features[0];
+
+ g_assert_cmpstr (shumate_vector_expression_eval_string (expression, &scope, NULL), ==, "Hello, world!");
+}
+
+
int
main (int argc, char *argv[])
{
@@ -236,6 +266,7 @@ main (int argc, char *argv[])
g_test_add_func ("/vector/expression/basic-filter", test_vector_expression_basic_filter);
g_test_add_func ("/vector/expression/feature-filter", test_vector_expression_feature_filter);
g_test_add_func ("/vector/expression/filter-errors", test_vector_expression_filter_errors);
+ g_test_add_func ("/vector/expression/format", test_vector_expression_format);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]