diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 714b8af8f..429540171 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2146,9 +2146,8 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta gb_internal bool check_single_target_feature_is_valid(String const &feature_list, String const &feature) { String_Iterator it = {feature_list, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (str == feature) { return true; } @@ -2160,8 +2159,8 @@ gb_internal bool check_single_target_feature_is_valid(String const &feature_list gb_internal bool check_target_feature_is_valid(String const &feature, TargetArchKind arch, String *invalid) { String feature_list = target_features_list[arch]; String_Iterator it = {feature, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { String feature_str = str; if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { feature_str = substring(feature_str, 1, feature_str.len); @@ -2169,7 +2168,6 @@ gb_internal bool check_target_feature_is_valid(String const &feature, TargetArch return false; } } - if (feature_str == "") break; if (!check_single_target_feature_is_valid(feature_list, feature_str)) { if (invalid) *invalid = str; return false; @@ -2181,10 +2179,8 @@ gb_internal bool check_target_feature_is_valid(String const &feature, TargetArch gb_internal bool check_target_feature_is_valid_globally(String const &feature, String *invalid) { String_Iterator it = {feature, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; - + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { bool valid = false; for (int arch = TargetArch_Invalid; arch < TargetArch_COUNT; arch += 1) { if (check_target_feature_is_valid(str, cast(TargetArchKind)arch, invalid)) { @@ -2208,15 +2204,19 @@ gb_internal bool check_target_feature_is_valid_for_target_arch(String const &fea gb_internal bool check_target_feature_is_enabled(String const &feature, String *not_enabled) { String_Iterator it = {feature, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { String feature_str = str; bool want_enabled = true; if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { want_enabled = feature_str[0] == '+'; feature_str = substring(feature_str, 1, feature_str.len); } - if (feature_str == "") break; + if (feature_str == "") { + // a bare sign names no feature, which cannot be enabled + if (not_enabled) *not_enabled = str; + return false; + } String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); String minus_str = concatenate_strings(temporary_allocator(), make_string_c("-"), feature_str); @@ -2240,9 +2240,8 @@ gb_internal bool check_target_feature_is_enabled(String const &feature, String * gb_internal bool check_target_feature_is_superset_of(String const &superset, String const &of, String *missing) { String_Iterator it = {of, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (!check_single_target_feature_is_valid(superset, str)) { if (missing) *missing = str; return false; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index e770ed90d..6ff3d182a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3164,10 +3164,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { gbString llvm_features = gb_string_make(temporary_allocator(), ""); String_Iterator it = {build_context.target_features_string, 0}; + String str = {}; bool first = true; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + while (string_split_iterator_next(&it, ',', &str)) { if (!first) { llvm_features = gb_string_appendc(llvm_features, ","); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 42c2f8653..f7e4ebe69 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -226,10 +226,9 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i gbString feature_str = gb_string_make(temporary_allocator(), ""); String_Iterator it = {pt->Proc.enable_target_feature, 0}; + String str = {}; bool first = true; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + while (string_split_iterator_next(&it, ',', &str)) { bool add_prefix = !(string_starts_with(str, '+') || string_starts_with(str, '-')); if (!first) { feature_str = gb_string_appendc(feature_str, ","); diff --git a/src/main.cpp b/src/main.cpp index 84ec22bdf..8785be9c0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1455,12 +1455,8 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); String val = value.value_string; String_Iterator it = {val, 0}; - for (;;) { - String pkg = string_split_iterator(&it, ','); - if (pkg.len == 0) { - break; - } - + String pkg = {}; + while (string_split_iterator_next(&it, ',', &pkg)) { pkg = string_trim_whitespace(pkg); if (!string_is_valid_identifier(pkg)) { gb_printf_err("-%.*s '%.*s' must be a valid identifier\n", LIT(name), LIT(pkg)); @@ -1478,12 +1474,8 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); String val = value.value_string; String_Iterator it = {val, 0}; - for (;;) { - String attr = string_split_iterator(&it, ','); - if (attr.len == 0) { - break; - } - + String attr = {}; + while (string_split_iterator_next(&it, ',', &attr)) { attr = string_trim_whitespace(attr); if (!string_is_valid_identifier(attr)) { gb_printf_err("-%.*s '%.*s' must be a valid identifier\n", LIT(name), LIT(attr)); @@ -4166,9 +4158,8 @@ int main(int arg_count, char const **arg_ptr) { } else { String march_list = target_microarch_list[build_context.metrics.arch]; String_Iterator it = {march_list, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (str == build_context.microarch) { // Found matching microarch print_microarch_list = false; @@ -4193,9 +4184,8 @@ int main(int arg_count, char const **arg_ptr) { String march_list = target_microarch_list[build_context.metrics.arch]; String_Iterator it = {march_list, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (str == default_march) { gb_printf("\t%.*s (default)\n", LIT(str)); } else { @@ -4209,9 +4199,8 @@ int main(int arg_count, char const **arg_ptr) { String default_features = get_default_features(); { String_Iterator it = {default_features, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { string_set_add(&build_context.target_features_set, str); } } @@ -4231,10 +4220,8 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.target_features_string.len != 0) { String_Iterator target_it = {build_context.target_features_string, 0}; - for (;;) { - String item = string_split_iterator(&target_it, ','); - if (item == "") break; - + String item = {}; + while (string_split_iterator_next(&target_it, ',', &item)) { String stripped_item = item; if (*stripped_item.text == '+' || *stripped_item.text == '-') { stripped_item.text++; @@ -4251,9 +4238,8 @@ int main(int arg_count, char const **arg_ptr) { String feature_list = target_features_list[build_context.metrics.arch]; String_Iterator it = {feature_list, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (check_single_target_feature_is_valid(default_features, str)) { if (has_ansi_terminal_colours()) { gb_printf("\t%.*s\x1b[38;5;244m (implied by target microarch %.*s)\x1b[0m\n", LIT(str), LIT(march)); diff --git a/src/string.cpp b/src/string.cpp index 76d03d55f..97588a5df 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -293,6 +293,20 @@ gb_internal String string_split_iterator(String_Iterator *it, const char sep) { return substring(it->str, start, end); } +// NOTE: `string_split_iterator` returns a zero-length `String` both for an empty element and at +// exhaustion, so a loop that stops on an empty result stops at the first empty element instead. +// This skips empty elements and stops only once the iterator is exhausted. +gb_internal bool string_split_iterator_next(String_Iterator *it, char const sep, String *str_) { + while (it->pos < it->str.len) { + String str = string_split_iterator(it, sep); + if (str.len != 0) { + *str_ = str; + return true; + } + } + return false; +} + gb_internal gb_inline bool is_separator(u8 const &ch) { return (ch == '/' || ch == '\\'); } diff --git a/src/types.cpp b/src/types.cpp index d12d8dbee..cf0927cdd 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3640,9 +3640,8 @@ gb_internal int matched_target_features(TypeProc *t) { int matches = 0; String_Iterator it = {t->require_target_feature, 0}; - for (;;) { - String str = string_split_iterator(&it, ','); - if (str == "") break; + String str = {}; + while (string_split_iterator_next(&it, ',', &str)) { if (check_target_feature_is_valid_for_target_arch(str, nullptr)) { matches += 1; }