diff options
-rw-r--r-- | codegen/valaccodecontrolflowmodule.vala | 34 | ||||
-rw-r--r-- | tests/control-flow/foreach.c-expected | 32 | ||||
-rw-r--r-- | tests/control-flow/foreach.vala | 12 | ||||
-rw-r--r-- | vala/valaforeachstatement.vala | 2 |
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); } |