Skip to content

ZstrLen

Description

Get length of a null-terminated string.

Parameters

Name Direction Description
str in Null-terminated string.

Success

Returns number of characters before null terminator.

Failure

Aborts via LOG_FATAL when str is NULL.

Usage example (Cross-references)

Usage examples (Cross-references)
    #include <Misra/Std/Zstr.h>
    
    size ZstrLen(Zstr str) {
        if (!str) {
            LOG_FATAL("Invalid arguments");
            LOG_FATAL("Invalid arguments");
        }
        return zstr_dup_n(src, ZstrLen(src), alloc);
    }
        }
    
        *dst = zstr_dup_n(*src, ZstrLen(*src), (Allocator *)alloc);
        return *dst != NULL;
    }
            LOG_FATAL("Invalid arguments");
        }
        return ZstrFindSubstringN(haystack, needle, ZstrLen(needle));
    }
            return haystack;
        }
        size haystack_len = ZstrLen(haystack);
        if (needle_len > haystack_len) {
            return NULL;
        Zstr p         = fmtstr;
        Zstr in        = input;
        u64  rem_p     = ZstrLen(fmtstr);
        u64  rem_in    = ZstrLen(in);
        u64  arg_index = 0; // Current argument index
        Zstr in        = input;
        u64  rem_p     = ZstrLen(fmtstr);
        u64  rem_in    = ZstrLen(in);
        u64  arg_index = 0; // Current argument index
            dot = ZstrFindChar(body, '.');
            if (!dot) {
                if (!StrPushBackMany(&result, body, ZstrLen(body))) {
                    goto fail;
                }
    
            prefix = (u64)(dot - body);
            frac   = (u64)ZstrLen(dot + 1);
    
            if (!StrPushBackMany(&result, body, prefix)) {
                // Precision truncates -- see the Str path above for the
                // precision-0 carve-out.
                size len = ZstrLen(xs);
                if (fmt_info->flags & FMT_FLAG_HAS_PRECISION) {
                    if (fmt_info->precision == 0) {
                                            .precision    = 6,
                                            .flags        = FMT_FLAG_NONE,
                                            .max_read_len = (u32)ZstrLen(i),
                                 };
        default_fmt.flags &= ~FMT_FLAG_CHAR;
        default_fmt.flags &= ~FMT_FLAG_CHAR;
        if (!default_fmt.max_read_len) {
            default_fmt.max_read_len = (u32)ZstrLen(i);
        }
            LOG_FATAL("str is NULL");
        }
        return bitvec_try_from_str_impl(out, str, (u64)ZstrLen(str), alloc);
    }
            LOG_FATAL("Invalid arguments");
        }
        return float_try_from_str_impl(out, text, (size)ZstrLen(text));
    }
    
    StrIters str_split_to_iters_zstr(Str *s, Zstr key) {
        return str_split_to_iters_impl(s, key, ZstrLen(key));
    }
    
    Strs str_split_zstr(Str *s, Zstr key) {
        return str_split_impl(s, key, ZstrLen(key));
    }
        }
    
        return str_index_of_cstr(s, key, ZstrLen(key));
    }
    bool str_starts_with_zstr(const Str *s, Zstr prefix) {
        ValidateStr(s);
        return starts_with(s->data, s->length, prefix, ZstrLen(prefix));
    }
    bool str_ends_with_zstr(const Str *s, Zstr suffix) {
        ValidateStr(s);
        return ends_with(s->data, s->length, suffix, ZstrLen(suffix));
    }
    void str_replace_zstr(Str *s, Zstr match, Zstr replacement, size count) {
        ValidateStr(s);
        str_replace_cstr(s, match, ZstrLen(match), replacement, ZstrLen(replacement), count);
    }
        }
    
        len = (u64)ZstrLen(decimal);
        if (len > 0 && decimal[0] == '+') {
            start = 1;
            LOG_FATAL("Invalid arguments");
        }
        len = (u64)ZstrLen(digits);
        if (len > 0 && digits[0] == '+') {
            start = 1;
        }
    
        len = (u64)ZstrLen(binary);
        if (len >= 2 && binary[0] == '0' && (binary[1] == 'b' || binary[1] == 'B')) {
            start = 2;
        }
    
        len = (u64)ZstrLen(octal);
        if (len >= 2 && octal[0] == '0' && (octal[1] == 'o' || octal[1] == 'O')) {
            start = 2;
        }
    
        len = (u64)ZstrLen(hex);
        return int_try_from_str_radix_impl(out, hex, len, 0, 16, false);
    }
        MemSet(&entry, 0, sizeof(entry));
    
        if (!StrTryInitFromCstr(&entry.module_path, module_path, ZstrLen(module_path), self->allocator)) {
            return NULL;
        }
            // split_host_port NUL-terminates; record the textual length so the
            // Str is internally consistent before any read via StrBegin.
            StrResize(&host, ZstrLen(host_data));
    
            u16 port = 0;
                    break;
                }
                StrResize(&host, ZstrLen(host_data));
                port = FROM_BIG_ENDIAN2(sa->sin_port);
                StrAppendFmt(&out, "{}:{}", (Zstr)host_data, (u32)port);
                    break;
                }
                StrResize(&host, ZstrLen(host_data));
                port = FROM_BIG_ENDIAN2(sa->sin6_port);
                StrAppendFmt(&out, "[{}]:{}", (Zstr)host_data, (u32)port);
        Zstr        exe = _dyld_get_image_name(0);
        if (exe) {
            *exe_path = StrInitFromCstr(exe, ZstrLen(exe), alloc);
            return exe_path;
        }
        HANDLE hFind = INVALID_HANDLE_VALUE;
        StrInitStack(search_path, MAX_PATH) {
            size path_len = ZstrLen(path);
            if (path_len + 3 > MAX_PATH) {
                LOG_ERROR("dir_get_contents: path too long for MAX_PATH");
                }
    
                direntry.name = StrInitFromCstr(findFileData.cFileName, ZstrLen(findFileData.cFileName), alloc);
                VecPushBack(&dc, direntry);
            } while (FindNextFile(hFind, &findFileData) != 0);
    #    else
                // Linux name is null-terminated; compute length.
                size name_len = ZstrLen(nm);
    #    endif
                // Skip "." and "..".
            LOG_FATAL("DirCreateAll: NULL path");
        }
        size n = ZstrLen(path);
        if (n == 0) {
            return 1;
    
        bool ok        = true;
        size path_len  = ZstrLen(path);
        bool trail_sep = (path_len > 0 && path[path_len - 1] == '/');
        for (size i = 0; i < VecLen(&dc); ++i) {
        MemSet(&entry, 0, sizeof(entry));
    
        if (!StrTryInitFromCstr(&entry.module_path, module_path, ZstrLen(module_path), self->allocator)) {
            return NULL;
        }
            return;
        }
        u64 len = ZstrLen(name);
        while (len > 0 && name[len - 1] == '.') {
            --len;
        // `Str` below holds 256 to keep the bound check and the buffer
        // aligned with one literal.
        if (ZstrLen(hostname) >= 256) {
            LOG_ERROR("DnsResolve: hostname \"{}\" exceeds 255 bytes", hostname);
            return false;
        // never contain colons and the IPv6 case was eliminated by the
        // SocketAddrParse attempt above.
        u64 spec_len = ZstrLen(spec);
        u64 colon_at = spec_len;
        for (u64 i = spec_len; i > 0; --i) {
        }
    
        lookup = StrInitFromCstr(key, ZstrLen(key), MapAllocator(cfg));
        value  = kvconfig_get_ptr_str(cfg, &lookup);
        StrDeinit(&lookup);
                    size_t total_len = 0;
                    VecForeach(vec, str) {
                        total_len += ZstrLen(str);
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachIdx(vec, str, idx) {
                        total_len += ZstrLen(str) + idx;
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachPtr(vec, str_ptr) {
                        total_len += ZstrLen(*str_ptr);
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachPtrIdx(vec, str_ptr, idx) {
                        total_len += ZstrLen(*str_ptr) + idx;
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachReverse(vec, str) {
                        total_len += ZstrLen(str);
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachReverseIdx(vec, str, idx) {
                        total_len += ZstrLen(str) + idx;
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachPtrReverse(vec, str_ptr) {
                        total_len += ZstrLen(*str_ptr);
                    }
                    (void)total_len; // Suppress unused variable warning
                    size_t total_len = 0;
                    VecForeachPtrReverseIdx(vec, str_ptr, idx) {
                        total_len += ZstrLen(*str_ptr) + idx;
                    }
                    (void)total_len; // Suppress unused variable warning
                        size_t total_len = 0;
                        VecForeachInRange(vec, str, start, end) {
                            total_len += ZstrLen(str);
                        }
                        (void)total_len; // Suppress unused variable warning
                        size_t total_len = 0;
                        VecForeachInRangeIdx(vec, str, idx, start, end) {
                            total_len += ZstrLen(str) + idx;
                        }
                        (void)total_len; // Suppress unused variable warning
                        size_t total_len = 0;
                        VecForeachPtrInRange(vec, str_ptr, start, end) {
                            total_len += ZstrLen(*str_ptr);
                        }
                        (void)total_len; // Suppress unused variable warning
                        size_t total_len = 0;
                        VecForeachPtrInRangeIdx(vec, str_ptr, idx, start, end) {
                            total_len += ZstrLen(*str_ptr) + idx;
                        }
                        (void)total_len; // Suppress unused variable warning
        MemCopy(&cv[4], kGuid, 16);
        wr_u32(&cv[20], kAge);
        u64 path_len = ZstrLen(pdb_path);
        MemCopy(&cv[24], pdb_path, path_len + 1);
    }
    
        // Compute S_PUB32 record size based on function name length.
        u64 name_len    = ZstrLen(func_name);
        u16 rec_body    = (u16)(2 + 4 + 4 + 2 + (u16)(name_len + 1)); // kind+flags+off+seg+name
        u32 symrec_size = (u32)(2 + rec_body);                        // includes the rec_len field itself
            char *dot_pos = ZstrFindChar(StrBegin(&s), '.');
            if (dot_pos) {
                size decimal_places = ZstrLen(dot_pos + 1);
                // Allow for trailing zeros being omitted in some cases
                result = result && (decimal_places <= precision);
    
        Zstr payload = "hello from socket test";
        size n       = (size)ZstrLen(payload);
        if (SocketSend(&client, payload, n) != (i64)n) {
            SocketClose(&server);
            return false;
        }
        size n       = ZstrLen(text);
        i64  written = FileWrite(&f, text, (u64)n);
        bool ok      = (written == (i64)n);
        FileClose(&f);
    
        bool result = (got == (i64)ZstrLen("hello from file")) && (StrLen(&body) == (size)ZstrLen("hello from file")) &&
                      ZstrCompare(StrBegin(&body), "hello from file") == 0;
    
        Zstr expected = "this is longer than the initial buffer";
        bool result   = (got == (i64)ZstrLen(expected)) && (StrLen(&body) == (size)ZstrLen(expected)) &&
                      ZstrCompare(StrBegin(&body), expected) == 0 && StrCapacity(&body) >= StrLen(&body) + 1;
        // Copy name
        if (src->name) {
            size name_len = ZstrLen(src->name);
            dst->name     = fixture_malloc(name_len + 1);
            if (!dst->name)
    
        if (name) {
            size name_len = ZstrLen(name);
            item.name     = (char *)fixture_malloc(name_len + 1);
            if (item.name) {
    
        // Check that it's initialized correctly
        bool result = (StrLen(&s) == ZstrLen(test_str) && ZstrCompare(StrBegin(&s), test_str) == 0);
    
        StrDeinit(&s);
        ValidateStr(&s);
    
        bool result = (StrLen(&s) == ZstrLen(test_str) && ZstrCompare(StrBegin(&s), test_str) == 0);
    
        StrDeinit(&s);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        Str src = StrInitFromCstr("Hello, World!", ZstrLen("Hello, World!"), &alloc);
    
        Str  dup    = StrInitFromStr(&src, &alloc);
        wr_u32(&cv[20], 0x0000002a); // Age
        // PDB path, NUL-terminated.
        u64 path_len = ZstrLen(kPdbPath);
        MemCopy(&cv[24], kPdbPath, path_len + 1);
    }
    /// TAGS: StrIter, Construct, Zstr
    ///
    #define StrIterFromZstr(s) ((StrIter) {.data = (s), .length = ZstrLen((s)), .pos = 0, .alignment = 1, .dir = 1})
    
    ///
    ///
    #define StrInitFromZstr(...)       OVERLOAD(StrInitFromZstr, __VA_ARGS__)
    #define StrInitFromZstr_1(zstr)    StrInitFromCstr_2((zstr), ZstrLen(zstr))
    #define StrInitFromZstr_2(zstr, a) StrInitFromCstr_3((zstr), ZstrLen(zstr), (a))
    #define StrInitFromZstr(...)       OVERLOAD(StrInitFromZstr, __VA_ARGS__)
    #define StrInitFromZstr_1(zstr)    StrInitFromCstr_2((zstr), ZstrLen(zstr))
    #define StrInitFromZstr_2(zstr, a) StrInitFromCstr_3((zstr), ZstrLen(zstr), (a))
    
    ///
    #define StrInsertMany(...) OVERLOAD(StrInsertMany, __VA_ARGS__)
    #define StrInsertMany_3(str, zstr, idx)                                                                            \
        _Generic((zstr), Zstr: VecInsertRangeR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))), char *: VecInsertRangeR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))))
    #define StrInsertMany_4(str, cstr, cstr_len, idx)                                                                  \
        _Generic((cstr), Zstr: VecInsertRangeR((str), (Zstr)(cstr), (idx), (cstr_len)), char *: VecInsertRangeR((str), (Zstr)(cstr), (idx), (cstr_len)))
    #define StrMustInsertMany(...) OVERLOAD(StrMustInsertMany, __VA_ARGS__)
    #define StrMustInsertMany_3(str, zstr, idx)                                                                        \
        _Generic((zstr), Zstr: VecMustInsertRangeR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))), char *: VecMustInsertRangeR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))))
    #define StrMustInsertMany_4(str, cstr, cstr_len, idx)                                                              \
        _Generic((cstr), Zstr: VecMustInsertRangeR((str), (Zstr)(cstr), (idx), (cstr_len)), char *: VecMustInsertRangeR((str), (Zstr)(cstr), (idx), (cstr_len)))
    #define StrInsertManyFast(...) OVERLOAD(StrInsertManyFast, __VA_ARGS__)
    #define StrInsertManyFast_3(str, zstr, idx)                                                                        \
        _Generic((zstr), Zstr: VecInsertRangeFastR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))), char *: VecInsertRangeFastR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))))
    #define StrInsertManyFast_4(str, cstr, cstr_len, idx)                                                              \
        _Generic((cstr), Zstr: VecInsertRangeFastR((str), (Zstr)(cstr), (idx), (cstr_len)), char *: VecInsertRangeFastR((str), (Zstr)(cstr), (idx), (cstr_len)))
    #define StrMustInsertManyFast(...) OVERLOAD(StrMustInsertManyFast, __VA_ARGS__)
    #define StrMustInsertManyFast_3(str, zstr, idx)                                                                    \
        _Generic((zstr), Zstr: VecMustInsertRangeFastR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))), char *: VecMustInsertRangeFastR((str), (Zstr)(zstr), (idx), ZstrLen((Zstr)(zstr))))
    #define StrMustInsertManyFast_4(str, cstr, cstr_len, idx)                                                          \
        _Generic((cstr), Zstr: VecMustInsertRangeFastR((str), (Zstr)(cstr), (idx), (cstr_len)), char *: VecMustInsertRangeFastR((str), (Zstr)(cstr), (idx), (cstr_len)))
    #define StrPushBackMany(...) OVERLOAD(StrPushBackMany, __VA_ARGS__)
    #define StrPushBackMany_2(str, zstr)                                                                               \
        _Generic((zstr), Zstr: VecPushBackArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecPushBackArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrPushBackMany_3(str, cstr, cstr_len)                                                                     \
        _Generic((cstr), Zstr: VecPushBackArrR((str), (Zstr)(cstr), (cstr_len)), char *: VecPushBackArrR((str), (Zstr)(cstr), (cstr_len)))
    #define StrMustPushBackMany(...) OVERLOAD(StrMustPushBackMany, __VA_ARGS__)
    #define StrMustPushBackMany_2(str, zstr)                                                                           \
        _Generic((zstr), Zstr: VecMustPushBackArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecMustPushBackArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrMustPushBackMany_3(str, cstr, cstr_len)                                                                 \
        _Generic((cstr), Zstr: VecMustPushBackArrR((str), (Zstr)(cstr), (cstr_len)), char *: VecMustPushBackArrR((str), (Zstr)(cstr), (cstr_len)))
    #define StrPushFrontMany(...) OVERLOAD(StrPushFrontMany, __VA_ARGS__)
    #define StrPushFrontMany_2(str, zstr)                                                                              \
        _Generic((zstr), Zstr: VecPushFrontArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecPushFrontArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrPushFrontMany_3(str, cstr, cstr_len)                                                                    \
        _Generic((cstr), Zstr: VecPushFrontArrR((str), (Zstr)(cstr), (cstr_len)), char *: VecPushFrontArrR((str), (Zstr)(cstr), (cstr_len)))
    #define StrMustPushFrontMany(...) OVERLOAD(StrMustPushFrontMany, __VA_ARGS__)
    #define StrMustPushFrontMany_2(str, zstr)                                                                          \
        _Generic((zstr), Zstr: VecMustPushFrontArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecMustPushFrontArrR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrMustPushFrontMany_3(str, cstr, cstr_len)                                                                \
        _Generic((cstr), Zstr: VecMustPushFrontArrR((str), (Zstr)(cstr), (cstr_len)), char *: VecMustPushFrontArrR((str), (Zstr)(cstr), (cstr_len)))
    #define StrPushFrontManyFast(...) OVERLOAD(StrPushFrontManyFast, __VA_ARGS__)
    #define StrPushFrontManyFast_2(str, zstr)                                                                          \
        _Generic((zstr), Zstr: VecPushFrontArrFastR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecPushFrontArrFastR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrPushFrontManyFast_3(str, cstr, cstr_len)                                                                \
        _Generic((cstr), Zstr: VecPushFrontArrFastR((str), (Zstr)(cstr), (cstr_len)), char *: VecPushFrontArrFastR((str), (Zstr)(cstr), (cstr_len)))
    #define StrMustPushFrontManyFast(...) OVERLOAD(StrMustPushFrontManyFast, __VA_ARGS__)
    #define StrMustPushFrontManyFast_2(str, zstr)                                                                      \
        _Generic((zstr), Zstr: VecMustPushFrontArrFastR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))), char *: VecMustPushFrontArrFastR((str), (Zstr)(zstr), ZstrLen((Zstr)(zstr))))
    #define StrMustPushFrontManyFast_3(str, cstr, cstr_len)                                                            \
        _Generic((cstr), Zstr: VecMustPushFrontArrFastR((str), (Zstr)(cstr), (cstr_len)), char *: VecMustPushFrontArrFastR((str), (Zstr)(cstr), (cstr_len)))
Last updated on