summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederik Zipp <fzipp@gmx.de>2010-08-01 12:54:37 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2023-01-11 19:54:08 +0100
commit58dcad084f427585994ab66904436e1bd0e0b2a1 (patch)
tree7e065d02ee93732615fbf1272630eb8685e9d50d
parent4bdb3e7301c59a32216ff383c23a4bdcf70fa268 (diff)
downloadvala-58dcad084f427585994ab66904436e1bd0e0b2a1.tar.gz
codegen: Add foreach support for strings
Fixes https://gitlab.gnome.org/GNOME/vala/issues/108
-rw-r--r--codegen/valaccodecontrolflowmodule.vala34
-rw-r--r--tests/control-flow/foreach.c-expected32
-rw-r--r--tests/control-flow/foreach.vala12
-rw-r--r--vala/valaforeachstatement.vala2
4 files changed, 80 insertions, 0 deletions
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index 9ecbced2f..9a68579b3 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -442,6 +442,40 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
stmt.body.emit (this);
ccode.close ();
+ } else if (stmt.collection.value_type.compatible (string_type)) {
+ // iterating over a string
+
+ var validate = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_validate"));
+ validate.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
+ validate.add_argument (new CCodeConstant ("-1"));
+ validate.add_argument (new CCodeConstant ("NULL"));
+ var cassert = new CCodeFunctionCall (new CCodeIdentifier ("_vala_warn_if_fail"));
+ cassert.add_argument (validate);
+ cassert.add_argument (new CCodeConstant ("\"Invalid UTF-8 string\""));
+ requires_assert = true;
+ ccode.add_expression (cassert);
+
+ var iterator_variable = new LocalVariable (collection_type, "%s_iter".printf (stmt.variable_name));
+ visit_local_variable (iterator_variable);
+ var string_iter = get_variable_cname (get_local_cname (iterator_variable));
+
+ var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (string_iter)), new CCodeConstant ("'\\0'"));
+ var next_char_call = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_next_char"));
+ next_char_call.add_argument (get_variable_cexpression (string_iter));
+
+ ccode.open_for (new CCodeAssignment (get_variable_cexpression (string_iter), get_variable_cexpression (collection_backup.name)),
+ ccond,
+ new CCodeAssignment (get_variable_cexpression (string_iter), next_char_call));
+
+ var element_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_get_char"));
+ element_expr.add_argument (get_variable_cexpression (string_iter));
+
+ visit_local_variable (stmt.element_variable);
+ ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
+
+ stmt.body.emit (this);
+
+ ccode.close ();
} else {
Report.error (stmt.source_reference, "internal error: unsupported collection type");
stmt.error = true;
diff --git a/tests/control-flow/foreach.c-expected b/tests/control-flow/foreach.c-expected
index c402e1c12..3263a32ef 100644
--- a/tests/control-flow/foreach.c-expected
+++ b/tests/control-flow/foreach.c-expected
@@ -46,6 +46,7 @@ static void _vala_GValue_free_function_content_of (gpointer data);
VALA_EXTERN void test_foreach_multidim_array (void);
VALA_EXTERN void test_foreach_const_array (void);
VALA_EXTERN void test_foreach_slice_array (void);
+VALA_EXTERN void test_foreach_string (void);
static void _vala_main (void);
const gint FOO[6] = {1, 2, 3, 4, 5, 6};
@@ -669,6 +670,36 @@ test_foreach_slice_array (void)
foo = (g_free (foo), NULL);
}
+void
+test_foreach_string (void)
+{
+ guint i = 0U;
+ gchar* s = NULL;
+ gchar* _tmp0_;
+ const gchar* _tmp1_;
+ i = (guint) 0;
+ _tmp0_ = g_strdup ("abc àçêö 你好");
+ s = _tmp0_;
+ _tmp1_ = s;
+ {
+ const gchar* c_collection = NULL;
+ const gchar* c_iter = NULL;
+ c_collection = _tmp1_;
+ _vala_warn_if_fail (g_utf8_validate (c_collection, -1, NULL), "Invalid UTF-8 string");
+ for (c_iter = c_collection; (*c_iter) != '\0'; c_iter = g_utf8_next_char (c_iter)) {
+ gunichar c = 0U;
+ c = g_utf8_get_char (c_iter);
+ {
+ guint _tmp2_;
+ _tmp2_ = i;
+ i = _tmp2_ + 1;
+ }
+ }
+ }
+ _vala_assert (i == ((guint) 11), "i == 11");
+ _g_free0 (s);
+}
+
static void
_vala_main (void)
{
@@ -679,6 +710,7 @@ _vala_main (void)
test_foreach_const_array ();
test_foreach_multidim_array ();
test_foreach_slice_array ();
+ test_foreach_string ();
}
int
diff --git a/tests/control-flow/foreach.vala b/tests/control-flow/foreach.vala
index 8689a18ad..83cef663a 100644
--- a/tests/control-flow/foreach.vala
+++ b/tests/control-flow/foreach.vala
@@ -173,6 +173,17 @@ void test_foreach_slice_array () {
assert (result == "2345");
}
+void test_foreach_string () {
+ uint i = 0;
+ string s = "abc àçêö 你好"; // Ni hao
+
+ foreach (unichar c in s) {
+ i++;
+ }
+
+ assert (i == 11);
+}
+
void main () {
test_foreach_gvaluearray ();
test_foreach_garray ();
@@ -181,4 +192,5 @@ void main () {
test_foreach_const_array ();
test_foreach_multidim_array ();
test_foreach_slice_array ();
+ test_foreach_string ();
}
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 84370e5b0..69d49eccb 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -194,6 +194,8 @@ public class Vala.ForeachStatement : Block {
return check_without_iterator (context, collection_type, collection_type.get_type_arguments ().get (0));
} else if (context.profile == Profile.GOBJECT && collection_type.compatible (context.analyzer.gvaluearray_type)) {
return check_without_iterator (context, collection_type, context.analyzer.gvalue_type);
+ } else if (context.profile == Profile.GOBJECT && collection_type.compatible (context.analyzer.string_type)) {
+ return check_without_iterator (context, collection_type, context.analyzer.unichar_type);
} else {
return check_with_iterator (context, collection_type);
}