Skip to content

StrIterPeek

Description

Read the current character into *out without advancing. Propagating alias for IterPeekAt(mi, 0, out); see IterPeekAt for the full contract.

Usage example (Cross-references)

Usage examples (Cross-references)
        char    fc        = 0;
    
        while (StrIterPeek(&fsi, &fc)) {
            if (fc != '{') {
                LOG_FATAL("buf_read_fmt: stray '{c}' in binary fmt; only {​{<Nr}} / {​{>Nr}} allowed", (u32)(u8)fc);
            Zstr    spec_start     = (Zstr)StrIterPos(&fsi);
            char    sc             = 0;
            while (StrIterPeek(&fsi, &sc) && sc != '}') {
                StrIterMustNext(&fsi);
            }
        StrIter fsi       = StrIterFromZstr(fmtstr);
        char    fc        = 0;
        while (StrIterPeek(&fsi, &fc)) {
            if (fc != '{') {
                LOG_FATAL("buf_*_fmt: stray '{c}' in binary fmt; only {​{<Nr}} / {​{>Nr}} allowed", (u32)(u8)fc);
            Zstr    spec_start     = (Zstr)StrIterPos(&fsi);
            char    sc             = 0;
            while (StrIterPeek(&fsi, &sc) && sc != '}') {
                StrIterMustNext(&fsi);
            }
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
            StrIter saved = si;
            Zstr    start = StrIterDataAt(&si, StrIterIndex(&si));
            while (StrIterPeek(&si, &c) && !IS_SPACE(c)) {
                StrIterMustNext(&si);
            }
        bool    has_decimal = false;
    
        while (StrIterPeek(&si, &c)) {
            // A second '.' ends the number; the parser proper rejects
            // multi-dot mantissas, so stopping here keeps the rejected tail
                StrIterMustNext(&si);
    
                if (StrIterPeek(&si, &c) && (c == '+' || c == '-')) {
                    StrIterMustNext(&si);
                }
                }
    
                if (!StrIterPeek(&si, &c) || !IS_DIGIT(c)) {
                    StrIterMustPrev(&si);
                    break;
                }
    
                while (StrIterPeek(&si, &c) && IS_DIGIT(c)) {
                    StrIterMustNext(&si);
                }
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
        StrIter saved = si;
    
        while (StrIterPeek(&si, &c)) {
            if (!is_valid_number_char(c, StrIterIndex(&si) == StrIterIndex(&saved), false)) {
                break;
            char    c  = 0;                                                                                                \
                                                                                                                           \
            while (StrIterPeek(&si, &c) && IS_SPACE(c)) {                                                                  \
                StrIterMustNext(&si);                                                                                      \
            }                                                                                                              \
                                                                                                                           \
            StrIter saved = si;                                                                                            \
            while (StrIterPeek(&si, &c)) {                                                                                 \
                if (!is_valid_number_char(c, StrIterIndex(&si) == StrIterIndex(&saved), false)) {                          \
                    break;                                                                                                 \
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
            StrIter hex_saved = si;
    
            while (StrIterPeek(&si, &c) && IS_XDIGIT(c)) {
                StrIterMustNext(&si);
            }
            StrIter oct_saved = si;
    
            while (StrIterPeek(&si, &c) && c >= '0' && c <= '7') {
                StrIterMustNext(&si);
            }
        StrIter bin_saved = si;
    
        while (StrIterPeek(&si, &c) && (c == '0' || c == '1')) {
            StrIterMustNext(&si);
        }
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
    
        char d0 = 0;
        (void)StrIterPeek(&si, &d0);
        if (d0 == '+') {
            StrIterMustNext(&si);
        }
    
        while (StrIterPeek(&si, &c) && int_fmt_digit_matches_radix(c, radix)) {
            StrIterMustNext(&si);
        }
    
        char trailing = 0;
        if (StrIterPeek(&si, &trailing) && trailing == '_') {
            LOG_ERROR("Int reads do not accept digit separators");
            return start;
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
        char    c  = 0;
    
        while (StrIterPeek(&si, &c) && IS_SPACE(c)) {
            StrIterMustNext(&si);
        }
            StrIter saved = si;
            Zstr    start = StrIterDataAt(&si, StrIterIndex(&si));
            while (StrIterPeek(&si, &c) && !IS_SPACE(c)) {
                StrIterMustNext(&si);
            }
        bool    has_decimal = false;
    
        while (StrIterPeek(&si, &c)) {
            if (c == '.') {
                if (has_decimal)
                StrIterMustNext(&si);
    
                if (StrIterPeek(&si, &c) && (c == '+' || c == '-')) {
                    StrIterMustNext(&si);
                }
                }
    
                if (!StrIterPeek(&si, &c) || !IS_DIGIT(c)) {
                    StrIterMustPrev(&si);
                    break;
                }
    
                while (StrIterPeek(&si, &c) && IS_DIGIT(c)) {
                    StrIterMustNext(&si);
                }
        u64     v  = 0;
        char    c;
        while (StrIterPeek(&si, &c) && c >= '0' && c <= '9') {
            u64 d = (u64)(c - '0');
            if (v > (~(u64)0 - d) / 10)
        int  consumed = 0;
        char c;
        while (StrIterPeek(si, &c)) {
            int d = hex_digit_value(c);
            if (d < 0)
    static bool expect_char(StrIter *si, char want) {
        char c;
        if (!StrIterPeek(si, &c) || c != want)
            return false;
        StrIterMustNext(si);
    static void skip_ws(StrIter *si) {
        char c;
        while (StrIterPeek(si, &c) && (c == ' ' || c == '\t')) {
            StrIterMustNext(si);
        }
    static void skip_token(StrIter *si) {
        char c;
        while (StrIterPeek(si, &c) && c != ' ' && c != '\t' && c != '\n') {
            StrIterMustNext(si);
        }
        size path_start_pos = StrIterIndex(si);
        char c;
        while (StrIterPeek(si, &c) && c != '\n') {
            StrIterMustNext(si);
        }
                // Skip past whatever line we couldn't parse.
                char c;
                while (StrIterPeek(&si, &c) && c != '\n') {
                    StrIterMustNext(&si);
                }
    static void skip_hspace_iter(StrIter *si) {
        char c;
        while (StrIterPeek(si, &c) && is_hspace(c)) {
            StrIterMustNext(si);
        }
    static void skip_to_eol_iter(StrIter *si) {
        char c;
        while (StrIterPeek(si, &c) && c != '\n') {
            StrIterMustNext(si);
        }
    
            // Comment / blank line -> eat the whole line.
            if (!StrIterPeek(&si, &c) || c == '#' || c == '\n' || c == '\r') {
                skip_to_eol_iter(&si);
                continue;
            // First token: IP literal.
            size ip_start = StrIterIndex(&si);
            while (StrIterPeek(&si, &c) && !is_hspace(c) && c != '\n') {
                StrIterMustNext(&si);
            }
    
            // Subsequent tokens: name + aliases.
            while (StrIterPeek(&si, &c) && c != '\n') {
                skip_hspace_iter(&si);
                if (!StrIterPeek(&si, &c) || c == '\n' || c == '#') {
            while (StrIterPeek(&si, &c) && c != '\n') {
                skip_hspace_iter(&si);
                if (!StrIterPeek(&si, &c) || c == '\n' || c == '#') {
                    break;
                }
                }
                size nm_start = StrIterIndex(&si);
                while (StrIterPeek(&si, &c) && !is_hspace(c) && c != '\n' && c != '#') {
                    StrIterMustNext(&si);
                }
            skip_hspace_iter(&si);
    
            if (!StrIterPeek(&si, &c) || c == '#' || c == ';' || c == '\n' || c == '\r') {
                skip_to_eol_iter(&si);
                continue;
    
                size ip_start = StrIterIndex(&si);
                while (StrIterPeek(&si, &c) && !is_hspace(c) && c != '\n' && c != '#') {
                    StrIterMustNext(&si);
                }
    static StrIter kvconfig_consume_line_end(StrIter si) {
        char c;
        if (StrIterPeek(&si, &c) && c == '\r') {
            StrIterMustNext(&si);
        }
            StrIterMustNext(&si);
        }
        if (StrIterPeek(&si, &c) && c == '\n') {
            StrIterMustNext(&si);
        }
    StrIter KvConfigSkipWhitespace(StrIter si) {
        char c;
        while (StrIterPeek(&si, &c) && kvconfig_is_space(c)) {
            StrIterMustNext(&si);
        }
    StrIter KvConfigSkipLine(StrIter si) {
        char c;
        while (StrIterPeek(&si, &c) && c != '\n') {
            StrIterMustNext(&si);
        }
    
        char c;
        while (StrIterPeek(&si, &c)) {
            if (c == '=' || c == ':' || kvconfig_is_space(c) || c == '\n' || kvconfig_is_comment_start(c)) {
                break;
    
        char c;
        if (!StrIterPeek(&si, &c) || c == '\n' || kvconfig_is_comment_start(c)) {
            return si;
        }
            StrIterMustNext(&si);
    
            while (StrIterPeek(&si, &c)) {
                if (c == quote) {
                    StrIterMustNext(&si);
                if (c == '\\') {
                    StrIterMustNext(&si);
                    if (!StrIterPeek(&si, &c)) {
                        LOG_ERROR("Unexpected end of quoted config value");
                        StrClear(value);
        }
    
        while (StrIterPeek(&si, &c) && c != '\n') {
            if (kvconfig_is_comment_start(c) && StrLen(value) > 0 &&
                kvconfig_is_space(StrCharAt(value, StrLen(value) - 1))) {
    
        char c;
        if (!StrIterPeek(&si, &c) || (c != '=' && c != ':')) {
            LOG_ERROR("Expected '=' or ':' after config key");
            StrClear(key);
    
        si = KvConfigSkipWhitespace(si);
        if (!StrIterPeek(&si, &c)) {
            // EOF after value is fine - last line without newline.
            return si;
    
        char c;
        while (StrIterPeek(&si, &c)) {
            Str     key   = StrInit(MapAllocator(cfg));
            Str     value = StrInit(MapAllocator(cfg));
            StrIter read_si;
    
            while (StrIterPeek(&si, &c)) {
                if (c == '\n') {
                    StrIterMustNext(&si);
                    si = KvConfigSkipWhitespace(si);
                    char c2;
                    if (!StrIterPeek(&si, &c2) || c2 == '\n') {
                        si = kvconfig_consume_line_end(si);
                        continue;
            }
    
            if (!StrIterPeek(&si, &c)) {
                StrDeinit(&key);
                StrDeinit(&value);
        // starting of an object
        char c;
        if (!StrIterPeek(&si, &c) || c != '{') {
            LOG_ERROR("Invalid object start. Expected '{'.");
            return saved_si;
    
        // while not at the end of object.
        while (StrIterPeek(&si, &c) && c != '}') {
            if (expect_comma) {
                if (c != ',') {
            si = JSkipWhitespace(si);
    
            if (!StrIterPeek(&si, &c) || c != ':') {
                LOG_ERROR("Expected ':' after key string. Failed to read JSON");
                StrDeinit(&key);
        }
    
        if (!StrIterPeek(&si, &c) || c != '}') {
            LOG_ERROR("Expected end of object '}' but found '{c}'", c);
            DefaultAllocatorDeinit(&scratch);
    
        char c;
        if (!StrIterPeek(&si, &c) || c != '[') {
            LOG_ERROR("Invalid array start. Expected '['.");
            return saved_si;
    
        // while not at the end of array.
        while (StrIterPeek(&si, &c) && c != ']') {
            if (expect_comma) {
                if (c != ',') {
    
        // end of array
        if (!StrIterPeek(&si, &c) || c != ']') {
            LOG_ERROR("Invalid end of array. Expected ']'.");
            return saved_si;
    StrIter JSkipWhitespace(StrIter si) {
        char c;
        while (StrIterPeek(&si, &c)) {
            switch (c) {
                case ' ' :
        // string start
        char c;
        if (StrIterPeek(&si, &c) && c == '"') {
            StrIterMustNext(&si);
    
            // while a printable character
            while (StrIterPeek(&si, &c)) {
                // three cases
                // - end of string (return)
                    case '\\' :
                        StrIterMustNext(&si);
                        if (!StrIterPeek(&si, &c)) {
                            LOG_ERROR("Unexpected end of string.");
                            StrClear(str);
        bool is_neg = false;
        char c;
        if (StrIterPeek(&si, &c) && c == '-') {
            is_neg = true;
            StrIterMustNext(&si);
        bool is_parsing         = true;
    
        while (is_parsing && StrIterPeek(&si, &c)) {
            switch (c) {
                case 'E' :
        char c;
        if (StrIterRemainingLength(&si) >= 4) {
            if (StrIterPeek(&si, &c) && c == 't') {
                Zstr pos = StrIterPos(&si);
                if (pos && ZstrCompareN(pos, "true", 4) == 0) {
    
            if (StrIterRemainingLength(&si) >= 5) {
                if (StrIterPeek(&si, &c) && c == 'f') {
                    Zstr pos = StrIterPos(&si);
                    if (pos && ZstrCompareN(pos, "false", 5) == 0) {
        char c;
        if (StrIterRemainingLength(&si) >= 4) {
            if (StrIterPeek(&si, &c) && c == 'n') {
                Zstr pos = StrIterPos(&si);
                if (pos && ZstrCompareN(pos, "null", 4) == 0) {
    
        char c;
        if (!StrIterPeek(&si, &c)) {
            LOG_ERROR("Failed to read value. Invalid JSON");
            return si;
        u64     total_bytes = 0;
        char    c;
        while (StrIterPeek(&si, &c)) {
            // Find next dot or end-of-string.
            size seg_start = StrIterIndex(&si);
            // Find next dot or end-of-string.
            size seg_start = StrIterIndex(&si);
            while (StrIterPeek(&si, &c) && c != '.') {
                StrIterMustNext(&si);
            }
                return false;
            }
            if (StrIterPeek(&si, &c) && c == '.') {
                StrIterMustNext(&si);
            }
            si                     = JSkipWhitespace(si);                                                                  \
            char UNPL(jr_c);                                                                                               \
            if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != '{') {                                                     \
                LOG_ERROR("Invalid object start. Expected '{'.");                                                          \
                si = UNPL(saved_si);                                                                                       \
            bool    UNPL(expect_comma) = false;                                                                            \
            bool    UNPL(failed)       = false;                                                                            \
            while (StrIterPeek(&si, &UNPL(jr_c)) && UNPL(jr_c) != '}') {                                                   \
                if (UNPL(expect_comma)) {                                                                                  \
                    if (UNPL(jr_c) != ',') {                                                                               \
                si = UNPL(read_si);                                                                                        \
                si = JSkipWhitespace(si);                                                                                  \
                if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != ':') {                                                 \
                    LOG_ERROR("Expected ':' after key string. Failed to read JSON");                                       \
                    StrDeinit(&key);                                                                                       \
            }                                                                                                              \
            if (!UNPL(failed)) {                                                                                           \
                if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != '}') {                                                 \
                    LOG_ERROR("Expected end of object '}' but found '{c}'", UNPL(jr_c));                                   \
                    UNPL(failed) = true;                                                                                   \
    
        char c = '\0';
        if (!StrIterPeek(&si, &c) || c != '{') {
            WriteFmt("[DEBUG] Peek check failed: expected '{', got '{c}'\n", c);
            success = false;
            /* starting of an array */                                                                                     \
            char UNPL(jr_c);                                                                                               \
            if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != '[') {                                                     \
                LOG_ERROR("Invalid array start. Expected '['.");                                                           \
                si = UNPL(saved_si);                                                                                       \
                                                                                                                           \
            /* while not at the end of array. */                                                                           \
            while (StrIterPeek(&si, &UNPL(jr_c)) && UNPL(jr_c) != ']') {                                                   \
                if (UNPL(expect_comma)) {                                                                                  \
                    if (UNPL(jr_c) != ',') {                                                                               \
            /* end of array */                                                                                             \
            if (!UNPL(failed)) {                                                                                           \
                if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != ']') {                                                 \
                    LOG_ERROR("Invalid end of array. Expected ']'.");                                                      \
                    UNPL(failed) = true;                                                                                   \
            /* starting of an object */                                                                                    \
            char UNPL(jr_c);                                                                                               \
            if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != '{') {                                                     \
                LOG_ERROR("Invalid object start. Expected '{'.");                                                          \
                si = UNPL(saved_si);                                                                                       \
                                                                                                                           \
            /* while not at the end of object. */                                                                          \
            while (StrIterPeek(&si, &UNPL(jr_c)) && UNPL(jr_c) != '}') {                                                   \
                if (UNPL(expect_comma)) {                                                                                  \
                    if (UNPL(jr_c) != ',') {                                                                               \
                                                                                                                           \
                                                                                                                           \
                if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != ':') {                                                 \
                    LOG_ERROR("Expected ':' after key string. Failed to read JSON");                                       \
                    StrDeinit(&key);                                                                                       \
                                                                                                                           \
            if (!UNPL(failed)) {                                                                                           \
                if (!StrIterPeek(&si, &UNPL(jr_c)) || UNPL(jr_c) != '}') {                                                 \
                    LOG_ERROR("Expected end of object '}' but found '{c}'", UNPL(jr_c));                                   \
                    UNPL(failed) = true;                                                                                   \
Last updated on