StrInitFromZstr

Table of Contents

StrInitFromZstr

Description

Initializes a Str object from a null-terminated C-style string (zstr). This macro calculates the length of zstr using strlen and then calls StrInitFromCstr to create the Str object.

Parameters

NameDirectionDescription
zstrinPointer to the null-terminated C-style string to initialize from.

Success

Returns a newly created Str object with its data field pointing to a newly allocated memory containing a copy of zstr. The length and capacity fields are set to the length of zstr. copy_init and copy_deinit are set to NULL, and alignment is set to 1.

Failure

Returns a Str object with data set to NULL if memory allocation using strndup (called internally by StrInitFromCstr) fails. In such a case, length and capacity will likely be uninitialized or zero. It’s crucial to check the data field for NULL after using this macro to handle potential memory allocation errors.

Usage example (Cross-references)

    char *env_var = getenv(name);
    if (env_var) {
    *value = StrInitFromZstr(env_var);
    return value;
    }
    strerror_r(eno, buf, 1023);
    #endif
    *err_str = StrInitFromZstr(buf);
    return err_str;
    }
    }
    
    direntry.name = StrInitFromZstr(findFileData.cFileName); // Copy file name
    VecPushBack(&dc, direntry);
    } while (FindNextFile(hFind, &findFileData) != 0);
    return NULL;
    }
    *exe_path = StrInitFromZstr(buffer);
    return exe_path;
    #else
    if (len != -1) {
    buffer[len] = '\0';
    *exe_path   = StrInitFromZstr(buffer);
    return exe_path;
    }
    u32 bsize = sizeof(buffer);
    if (_NSGetExecutablePath(buffer, &bsize) == 0) {
    *exe_path = StrInitFromZstr(buffer);
    return exe_path;
    }
    
    // Test decimal conversion
    Str  s       = StrInitFromZstr("12345");
    u64  value   = 0;
    bool success = StrToU64(&s, &value, NULL);
    // Test hexadecimal conversion with explicit base
    StrDeinit(&s);
    s                     = StrInitFromZstr("ABCD"); // No 0x prefix when base is explicitly 16
    StrParseConfig config = {.base = 16};
    success               = StrToU64(&s, &value, &config);
    // Test hexadecimal conversion (auto-detect base with 0)
    StrDeinit(&s);
    s       = StrInitFromZstr("0xABCD");
    success = StrToU64(&s, &value, NULL);
    result  = result && (success && value == 0xABCD);
    // Test binary conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("0b101010");
    success = StrToU64(&s, &value, NULL);
    result  = result && (success && value == 42);
    // Test octal conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("0o52");
    success = StrToU64(&s, &value, NULL);
    result  = result && (success && value == 42);
    // Test zero
    StrDeinit(&s);
    s       = StrInitFromZstr("0");
    success = StrToU64(&s, &value, NULL);
    result  = result && (success && value == 0);
    // Test invalid input
    StrDeinit(&s);
    s       = StrInitFromZstr("not a number");
    success = StrToU64(&s, &value, NULL);
    result  = result && (!success);
    // Test negative number (should fail for unsigned)
    StrDeinit(&s);
    s       = StrInitFromZstr("-123");
    success = StrToU64(&s, &value, NULL);
    result  = result && (!success);
    
    // Test positive decimal conversion
    Str  s       = StrInitFromZstr("12345");
    i64  value   = 0;
    bool success = StrToI64(&s, &value, NULL);
    // Test negative decimal conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("-12345");
    success = StrToI64(&s, &value, NULL);
    result  = result && (success && value == -12345);
    // Test hexadecimal conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("0xABCD");
    success = StrToI64(&s, &value, NULL);
    result  = result && (success && value == 0xABCD);
    // Test binary conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("0b101010");
    success = StrToI64(&s, &value, NULL);
    result  = result && (success && value == 42);
    // Test zero
    StrDeinit(&s);
    s       = StrInitFromZstr("0");
    success = StrToI64(&s, &value, NULL);
    result  = result && (success && value == 0);
    // Test invalid input
    StrDeinit(&s);
    s       = StrInitFromZstr("not a number");
    success = StrToI64(&s, &value, NULL);
    result  = result && (!success);
    
    // Test integer conversion
    Str  s       = StrInitFromZstr("123");
    f64  value   = 0.0;
    bool success = StrToF64(&s, &value, NULL);
    // Test fractional conversion
    StrDeinit(&s);
    s       = StrInitFromZstr("123.456");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && fabs(value - 123.456) < 0.0001);
    // Test negative number
    StrDeinit(&s);
    s       = StrInitFromZstr("-123.456");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && fabs(value - (-123.456)) < 0.0001);
    // Test scientific notation
    StrDeinit(&s);
    s       = StrInitFromZstr("1.23e2");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && fabs(value - 123.0) < 0.0001);
    // Test zero
    StrDeinit(&s);
    s       = StrInitFromZstr("0");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && fabs(value) < 0.0001);
    // Test infinity
    StrDeinit(&s);
    s       = StrInitFromZstr("inf");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && isinf(value) && value > 0);
    // Test negative infinity
    StrDeinit(&s);
    s       = StrInitFromZstr("-inf");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && isinf(value) && value < 0);
    // Test NaN
    StrDeinit(&s);
    s       = StrInitFromZstr("nan");
    success = StrToF64(&s, &value, NULL);
    result  = result && (success && isnan(value));
    // Test invalid input
    StrDeinit(&s);
    s       = StrInitFromZstr("not a number");
    success = StrToF64(&s, &value, NULL);
    result  = result && (!success);
    
    for (size_t i = 0; i < sizeof(prefix_tests) / sizeof(prefix_tests[0]); i++) {
    Str            test_str = StrInitFromZstr(prefix_tests[i].input);
    u64            value    = 0;
    StrParseConfig config   = {.base = prefix_tests[i].base};
    strcpy(long_number, "12345678901234567890123456789012345678901234567890");
    
    Str  long_str   = StrInitFromZstr(long_number);
    u64  long_value = 0;
    bool success    = StrToU64(&long_str, &long_value, NULL);
    StrReadFmt(z, "{}", s);
    
    Str expected = StrInitFromZstr("Hello");
    success      = success && (StrCmp(&s, &expected) == 0);
    StrDeinit(&expected);
    StrReadFmt(z, "{s}", s);
    
    expected = StrInitFromZstr("Hello, World!");
    success  = success && (StrCmp(&s, &expected) == 0);
    StrDeinit(&expected);
    success = success && (num == 42);
    
    Str expected = StrInitFromZstr("Alice");
    success      = success && (StrCmp(&name, &expected) == 0);
    StrDeinit(&expected);
    success = success && double_equals(val, 3.14);
    
    expected = StrInitFromZstr("Bob");
    success  = success && (StrCmp(&name, &expected) == 0);
    StrDeinit(&expected);
    z           = "Hello";
    StrReadFmt(z, "{c}", str_val);
    Str  expected = StrInitFromZstr("Hello");
    bool str_pass = (StrCmp(&str_val, &expected) == 0);
    WriteFmt("str_val test: comparing with 'Hello', pass = {}\n", str_pass ? "true" : "false");
    z       = "\"World\"";
    StrReadFmt(z, "{cs}", str_val);
    expected             = StrInitFromZstr("World");
    bool quoted_str_pass = (StrCmp(&str_val, &expected) == 0);
    WriteFmt("quoted str_val test: comparing with 'World', pass = {}\n", quoted_str_pass ? "true" : "false");
    
    // Should read "hello" (stops at first space)
    Str  expected   = StrInitFromZstr("hello world");
    bool test1_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'hello', Pass: {}\n\n", test1_pass ? "true" : "false");
    
    // Should read "hello" (stops at first space)
    Str  expected   = StrInitFromZstr("hello");
    bool test1_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'hello', Pass: {}\n\n", test1_pass ? "true" : "false");
    
    // Should read "HELLO" (stops at first space)
    Str  expected   = StrInitFromZstr("HELLO WORLD");
    bool test2_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'HELLO', Pass: {}\n\n", test2_pass ? "true" : "false");
    
    // Should read "mixed case" (converts the entire quoted string)
    Str  expected   = StrInitFromZstr("mixed case");
    bool test3_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'mixed case', Pass: {}\n\n", test3_pass ? "true" : "false");
    
    // Should read "ABC123XYZ" (only letters are converted, numbers unchanged)
    Str  expected   = StrInitFromZstr("ABC123XYZ");
    bool test4_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'ABC123XYZ', Pass: {}\n\n", test4_pass ? "true" : "false");
    
    // Should read "Hello" (stops at first space, no case conversion)
    Str  expected   = StrInitFromZstr("Hello World");
    bool test5_pass = (StrCmp(&result, &expected) == 0);
    WriteFmt("Expected: 'Hello World', Pass: {}\n\n", test5_pass ? "true" : "false");
    
    // Add some strings
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr("World");
    // Add some strings
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr("World");
    
    VecPushBack(&sv, s1);
    
    // Test Str object
    Str s = StrInitFromZstr("World");
    StrWriteFmt(&output, "{}", s);
    success = success && (ZstrCompare(output.data, "World") == 0);
    
    // Test with Str object
    Str s = StrInitFromZstr("MiXeD CaSe");
    
    // Test with :c (preserve case)
    WriteFmt("Testing StrFirst\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Get the first character
    WriteFmt("Testing StrLast\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Get the last character
    WriteFmt("Testing StrBegin\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Get a pointer to the first character using StrBegin
    WriteFmt("Testing StrEnd\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Get a pointer to one past the last character using StrEnd
    WriteFmt("Testing StrCharAt\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Access characters at different indices
    WriteFmt("Testing StrCharPtrAt\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Access character pointers at different indices
    WriteFmt("Testing StrPopBack\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Pop a character from the back
    WriteFmt("Testing StrPopFront\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Pop a character from the front
    WriteFmt("Testing StrRemove\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Remove a character from the middle
    WriteFmt("Testing StrRemoveRange\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Create a buffer to store the removed characters
    WriteFmt("Testing StrDeleteLastChar\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Delete the last character
    WriteFmt("Testing StrDelete\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Delete a character from the middle
    WriteFmt("Testing StrDeleteRange\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Delete a range of characters
    WriteFmt("Testing StrForeachIdx\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character with its index
    WriteFmt("Testing StrForeachReverseIdx\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character in reverse with its index
    WriteFmt("Testing StrForeachPtrIdx\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character pointer with its index
    WriteFmt("Testing StrForeachReversePtrIdx\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character pointer in reverse with its index
    WriteFmt("Testing StrForeach\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character
    WriteFmt("Testing StrForeachReverse\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character in reverse
    WriteFmt("Testing StrForeachPtr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character pointer
    WriteFmt("Testing StrForeachPtrReverse\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Build a new string by iterating through each character pointer in reverse
    WriteFmt("Testing StrForeachInRangeIdx\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Build a new string by iterating through a range of characters with indices
    WriteFmt("Testing StrForeachInRange\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Build a new string by iterating through a range of characters
    WriteFmt("Testing StrForeachPtrInRangeIdx\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Build a new string by iterating through a range of character pointers with indices
    WriteFmt("Testing StrForeachPtrInRange\n");
    
    Str s = StrInitFromZstr("Hello World");
    
    // Build a new string by iterating through a range of character pointers
    WriteFmt("Testing StrForeachInRangeIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Hello World!"); // 12 characters
    
    // Use StrForeachInRangeIdx which captures the 'end' parameter at the start
    WriteFmt("Testing StrForeachInRangeIdx with character deletion where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Programming"); // 11 characters
    
    // Use StrForeachInRangeIdx with a fixed range that will become invalid
    WriteFmt("Testing StrForeachReverseIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Beautiful Weather"); // 17 characters
    
    // StrForeachReverseIdx (VecForeachReverseIdx) has explicit bounds checking: if ((idx) >= (v)->length) LOG_FATAL(...)
    WriteFmt("Testing StrForeachPtrIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Programming Test"); // 16 characters
    
    // StrForeachPtrIdx (VecForeachPtrIdx) has explicit bounds checking: if ((idx) >= (v)->length) LOG_FATAL(...)
    WriteFmt("Testing StrForeachReversePtrIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Excellent Example"); // 17 characters
    
    // StrForeachReversePtrIdx (VecForeachPtrReverseIdx) has explicit bounds checking: if ((idx) >= (v)->length) LOG_FATAL(...)
    WriteFmt("Testing StrForeachPtrInRangeIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Comprehensive Testing Framework"); // 31 characters
    
    // Use StrForeachPtrInRangeIdx with a fixed range that becomes invalid when we modify the string
    WriteFmt("Testing basic StrForeachIdx where idx goes out of bounds\n");
    
    Str s = StrInitFromZstr("Testing Basic"); // 13 characters
    
    // Basic StrForeachIdx (VecForeachIdx) now has explicit bounds checking: if ((idx) >= (v)->length) LOG_FATAL(...)
    // Test StrInitFromZstr function
    bool test_str_init_from_zstr(void) {
    WriteFmt("Testing StrInitFromZstr\n");
    
    const char *test_str = "Hello, World!";
    
    const char *test_str = "Hello, World!";
    Str         s        = StrInitFromZstr(test_str);
    
    // Validate the string
    WriteFmt("Testing StrInitFromStr\n");
    
    Str src = StrInitFromZstr("Hello, World!");
    Str dst = StrInitFromStr(&src);
    WriteFmt("Testing StrDup\n");
    
    Str src = StrInitFromZstr("Hello, World!");
    Str dst = StrDup(&src);
    WriteFmt("Testing StrInitCopy\n");
    
    Str src = StrInitFromZstr("Hello, World!");
    Str dst = StrInit();
    WriteFmt("Testing StrDeinit\n");
    
    Str s = StrInitFromZstr("Hello, World!");
    
    // Validate the string before deinit
    WriteFmt("Testing StrCmp and StrCmpCstr\n");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr("Hello");
    Str s3 = StrInitFromZstr("World");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr("Hello");
    Str s3 = StrInitFromZstr("World");
    Str s4 = StrInitFromZstr("Hello World");
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr("Hello");
    Str s3 = StrInitFromZstr("World");
    Str s4 = StrInitFromZstr("Hello World");
    Str s2 = StrInitFromZstr("Hello");
    Str s3 = StrInitFromZstr("World");
    Str s4 = StrInitFromZstr("Hello World");
    
    // Test StrCmp with equal strings
    WriteFmt("Testing StrFindStr, StrFindZstr, and StrFindCstr\n");
    
    Str haystack = StrInitFromZstr("Hello World");
    Str needle1  = StrInitFromZstr("World");
    Str needle2  = StrInitFromZstr("Hello");
    
    Str haystack = StrInitFromZstr("Hello World");
    Str needle1  = StrInitFromZstr("World");
    Str needle2  = StrInitFromZstr("Hello");
    Str needle3  = StrInitFromZstr("NotFound");
    Str haystack = StrInitFromZstr("Hello World");
    Str needle1  = StrInitFromZstr("World");
    Str needle2  = StrInitFromZstr("Hello");
    Str needle3  = StrInitFromZstr("NotFound");
    Str needle1  = StrInitFromZstr("World");
    Str needle2  = StrInitFromZstr("Hello");
    Str needle3  = StrInitFromZstr("NotFound");
    
    // Test StrFindStr with match at end
    WriteFmt("Testing StrStartsWith and StrEndsWith variants\n");
    
    Str s      = StrInitFromZstr("Hello World");
    Str prefix = StrInitFromZstr("Hello");
    Str suffix = StrInitFromZstr("World");
    
    Str s      = StrInitFromZstr("Hello World");
    Str prefix = StrInitFromZstr("Hello");
    Str suffix = StrInitFromZstr("World");
    Str s      = StrInitFromZstr("Hello World");
    Str prefix = StrInitFromZstr("Hello");
    Str suffix = StrInitFromZstr("World");
    
    // Test StrStartsWith
    
    // Test StrReplaceZstr
    Str s1 = StrInitFromZstr("Hello World");
    StrReplaceZstr(&s1, "World", "Universe", 1);
    bool result = (ZstrCompare(s1.data, "Hello Universe") == 0);
    // Test multiple replacements
    StrDeinit(&s1);
    s1 = StrInitFromZstr("Hello Hello Hello");
    StrReplaceZstr(&s1, "Hello", "Hi", 2);
    result = result && (ZstrCompare(s1.data, "Hi Hi Hello") == 0);
    // Test StrReplaceCstr - use the full "World" string instead of just "Wo"
    StrDeinit(&s1);
    s1 = StrInitFromZstr("Hello World");
    StrReplaceCstr(&s1, "World", 5, "Universe", 8, 1);
    result = result && (ZstrCompare(s1.data, "Hello Universe") == 0);
    // Test StrReplace
    StrDeinit(&s1);
    s1          = StrInitFromZstr("Hello World");
    Str find    = StrInitFromZstr("World");
    Str replace = StrInitFromZstr("Universe");
    StrDeinit(&s1);
    s1          = StrInitFromZstr("Hello World");
    Str find    = StrInitFromZstr("World");
    Str replace = StrInitFromZstr("Universe");
    StrReplace(&s1, &find, &replace, 1);
    s1          = StrInitFromZstr("Hello World");
    Str find    = StrInitFromZstr("World");
    Str replace = StrInitFromZstr("Universe");
    StrReplace(&s1, &find, &replace, 1);
    result = result && (ZstrCompare(s1.data, "Hello Universe") == 0);
    
    // Test StrSplit
    Str  s     = StrInitFromZstr("Hello,World,Test");
    Strs split = StrSplit(&s, ",");
    
    // Test StrLStrip
    Str  s1       = StrInitFromZstr("  Hello  ");
    Str  stripped = StrLStrip(&s1, NULL);
    bool result   = (ZstrCompare(stripped.data, "Hello  ") == 0);
    // Test with custom strip characters
    StrDeinit(&s1);
    s1 = StrInitFromZstr("***Hello***");
    
    stripped = StrLStrip(&s1, "*");
    WriteFmt("Testing StrInsertCharAt\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Insert a character in the middle
    WriteFmt("Testing StrInsertCstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Insert a string in the middle
    WriteFmt("Testing StrInsertZstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Insert a string in the middle
    WriteFmt("Testing StrInsert\n");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    // Insert s2 into s1 in the middle
    WriteFmt("Testing StrPushCstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Push a string at position 2
    WriteFmt("Testing StrPushZstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Push a string at position 2
    WriteFmt("Testing StrPushBackCstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Push a string at the back
    WriteFmt("Testing StrPushBackZstr\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Push a string at the back
    WriteFmt("Testing StrPushFrontCstr\n");
    
    Str s = StrInitFromZstr("World");
    
    // Push a string at the front
    WriteFmt("Testing StrPushFrontZstr\n");
    
    Str s = StrInitFromZstr("World");
    
    // Push a string at the front
    WriteFmt("Testing StrPushBack\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Push characters at the back
    WriteFmt("Testing StrPushFront\n");
    
    Str s = StrInitFromZstr("World");
    
    // Push characters at the front
    WriteFmt("Testing StrMergeL\n");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    // Merge s2 into s1 (L-value semantics)
    WriteFmt("Testing StrMergeR\n");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    // Merge s2 into s1 (R-value semantics)
    WriteFmt("Testing StrMerge\n");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    Str s1 = StrInitFromZstr("Hello");
    Str s2 = StrInitFromZstr(" World");
    
    // Merge s2 into s1
    WriteFmt("Testing StrAppendf\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Append formatted string
    WriteFmt("Testing StrSwapCharAt\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Swap 'H' and 'o'
    WriteFmt("Testing StrResize\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Initial length should be 5
    WriteFmt("Testing StrClear\n");
    
    Str s = StrInitFromZstr("Hello, World!");
    
    // Initial length should be 13
    WriteFmt("Testing StrReverse\n");
    
    Str s = StrInitFromZstr("Hello");
    
    // Reverse the string
    // Test with an even-length string
    StrDeinit(&s);
    s = StrInitFromZstr("abcd");
    
    // Reverse the string
    // Test with a single-character string
    StrDeinit(&s);
    s = StrInitFromZstr("a");
    
    // Reverse the string
    bool enabled;
    Str  message;
    } original = {42, 25.5, true, StrInitFromZstr("hello world")};
    
    // Write to JSON
    } original = {
    StrInit(),
    StrInitFromZstr("hello"),
    StrInitFromZstr("hello world with spaces"),
    StrInitFromZstr("special: !@#$%^&*()")
    StrInit(),
    StrInitFromZstr("hello"),
    StrInitFromZstr("hello world with spaces"),
    StrInitFromZstr("special: !@#$%^&*()")
    };
    StrInitFromZstr("hello"),
    StrInitFromZstr("hello world with spaces"),
    StrInitFromZstr("special: !@#$%^&*()")
    };
    
    // Create strings and push them properly
    Str str1 = StrInitFromZstr("first");
    Str str2 = StrInitFromZstr("second");
    Str str3 = StrInitFromZstr("");
    // Create strings and push them properly
    Str str1 = StrInitFromZstr("first");
    Str str2 = StrInitFromZstr("second");
    Str str3 = StrInitFromZstr("");
    Str str4 = StrInitFromZstr("last");
    Str str1 = StrInitFromZstr("first");
    Str str2 = StrInitFromZstr("second");
    Str str3 = StrInitFromZstr("");
    Str str4 = StrInitFromZstr("last");
    Str str2 = StrInitFromZstr("second");
    Str str3 = StrInitFromZstr("");
    Str str4 = StrInitFromZstr("last");
    
    VecPushBack(&original_strings, str1);
    
    // Original data
    TestPerson original_person = {12345, StrInitFromZstr("John Doe"), 30, true, 75000.50};
    
    // Write to JSON
    ComplexData original    = {0};
    original.user.id        = 999;
    original.user.name      = StrInitFromZstr("Complex User");
    original.user.age       = 25;
    original.user.is_active = true;
    original.config.debug_mode = false;
    original.config.timeout    = 30;
    original.config.log_level  = StrInitFromZstr("INFO");
    original.config.features   = VecInitWithDeepCopyT(original.config.features, NULL, StrDeinit);
    
    // Create strings and push them properly
    Str feature1 = StrInitFromZstr("auth");
    Str feature2 = StrInitFromZstr("logging");
    // Create strings and push them properly
    Str feature1 = StrInitFromZstr("auth");
    Str feature2 = StrInitFromZstr("logging");
    
    VecPushBack(&original.config.features, feature1);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"name\": \"Alice\", \"city\": \"New York\"}");
    StrIter si      = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"count\": 42, \"score\": 95.5, \"year\": 2024}");
    StrIter si      = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"enabled\": true, \"visible\": false}");
    StrIter si      = StrIterFromStr(json);
    bool success = true;
    Str  json =
    StrInitFromZstr("{\"id\": 1001, \"name\": \"Bob\", \"age\": 25, \"is_active\": true, \"salary\": 50000.0}");
    StrIter si = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"debug_mode\": false, \"timeout\": 30, \"log_level\": \"INFO\"}");
    StrIter si      = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"languages\": [\"C\", \"Python\", \"Rust\"]}");
    StrIter si      = StrIterFromStr(json);
    bool success = true;
    Str  json =
    StrInitFromZstr("{\"user\": {\"name\": \"Charlie\", \"email\": \"charlie@example.com\"}, \"active\": true}");
    StrIter si = StrIterFromStr(json);
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"id\": 12345, \"name\": \"Laptop\", \"price\": 999.99, \"tags\": [\"electronics\", \"computers\", "
    "\"portable\"]}"
    bool compare_json_output(const Str *output, const char *expected) {
    // Create a copy of expected without spaces for comparison
    Str expected_str   = StrInitFromZstr(expected);
    Str output_clean   = StrInit();
    Str expected_clean = StrInit();
    Str  json    = StrInit();
    
    Str name = StrInitFromZstr("Alice");
    Str city = StrInitFromZstr("New York");
    
    Str name = StrInitFromZstr("Alice");
    Str city = StrInitFromZstr("New York");
    
    JW_OBJ(json, {
    Str  json    = StrInit();
    
    Person person = {1001, StrInitFromZstr("Bob"), 25, true, 50000.0};
    
    JW_OBJ(json, {
    Str  json    = StrInit();
    
    Config config = {false, 30, StrInitFromZstr("INFO")};
    
    JW_OBJ(json, {
    
    // Create strings and push them properly
    Str lang1 = StrInitFromZstr("C");
    Str lang2 = StrInitFromZstr("Python");
    Str lang3 = StrInitFromZstr("Rust");
    // Create strings and push them properly
    Str lang1 = StrInitFromZstr("C");
    Str lang2 = StrInitFromZstr("Python");
    Str lang3 = StrInitFromZstr("Rust");
    Str lang1 = StrInitFromZstr("C");
    Str lang2 = StrInitFromZstr("Python");
    Str lang3 = StrInitFromZstr("Rust");
    
    VecPushBack(&languages, lang1);
    bool active;
    } data = {
    {StrInitFromZstr("Charlie"), StrInitFromZstr("charlie@example.com")},
    true
    };
    SimpleProduct product = {0};
    product.id            = 12345;
    product.name          = StrInitFromZstr("Laptop");
    product.price         = 999.99;
    product.tags          = VecInitWithDeepCopyT(product.tags, NULL, StrDeinit);
    
    // Create strings and push them properly
    Str tag1 = StrInitFromZstr("electronics");
    Str tag2 = StrInitFromZstr("computers");
    Str tag3 = StrInitFromZstr("portable");
    // Create strings and push them properly
    Str tag1 = StrInitFromZstr("electronics");
    Str tag2 = StrInitFromZstr("computers");
    Str tag3 = StrInitFromZstr("portable");
    Str tag1 = StrInitFromZstr("electronics");
    Str tag2 = StrInitFromZstr("computers");
    Str tag3 = StrInitFromZstr("portable");
    
    VecPushBack(&product.tags, tag1);
    WriteFmt("Testing basic iterator functionality\n");
    
    Str     json = StrInitFromZstr("{\"test\": \"value\"}");
    StrIter si   = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"id\": 12345, \"name\": \"test\", \"active\": true, \"score\": 98.5}");
    StrIter si      = StrIterFromStr(json);
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"user\": {\"id\": 123, \"profile\": {\"name\": \"Alice\", \"age\": 30}}, \"status\": \"active\"}"
    );
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"company\": {\"departments\": {\"engineering\": {\"head\": \"John\", \"count\": 25, \"budget\": 150000.0}}, "
    "\"name\": \"TechCorp\"}}"
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"functions\": {\"12345\": {\"67890\": {\"distance\": 0.85, \"name\": \"main\"}}, \"54321\": {\"98765\": "
    "{\"distance\": 0.92, \"name\": \"helper\"}}}}"
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"status\": true, \"message\": \"Success\", \"data\": {\"12345\": {\"67890\": {\"distance\": 0.85, "
    "\"nearest_neighbor_analysis_id\": 999, \"nearest_neighbor_binary_id\": 888, "
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"id\": 12345, \"name\": \"test_func\", \"size\": 1024, \"vaddr\": 4096}");
    StrIter si      = StrIterFromStr(json);
    
    bool    success = true;
    Str     json    = StrInitFromZstr("{\"id\": 54321, \"name\": \"test_model\"}");
    StrIter si      = StrIterFromStr(json);
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"binary_id\": 888, \"binary_name\": \"test_binary\", \"analysis_id\": 999, \"sha256\": \"abc123\", "
    "\"created_at\": \"2024-04-01\", \"model_id\": 12345, \"model_name\": \"test_model\", \"owned_by\": \"user1\"}"
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"status\": true, \"message\": \"Success\", \"data\": {\"12345\": {\"67890\": {\"distance\": 0.85, "
    "\"nearest_neighbor_analysis_id\": 999, \"nearest_neighbor_binary_id\": 888, "
    
    bool success = true;
    Str  json    = StrInitFromZstr(
    "{\"status\": true, \"message\": \"Success\", \"data\": {\"12345\": {\"67890\": {\"distance\": 0.85, "
    "\"nearest_neighbor_analysis_id\": 999, \"nearest_neighbor_binary_id\": 888, "
    
    // Test completely empty object
    Str     json1 = StrInitFromZstr("{}");
    StrIter si1   = StrIterFromStr(json1);
    
    // Test empty object with whitespace
    Str     json2 = StrInitFromZstr("  {   }  ");
    StrIter si2   = StrIterFromStr(json2);
    
    // Test completely empty array
    Str     json1 = StrInitFromZstr("{\"items\":[]}");
    StrIter si1   = StrIterFromStr(json1);
    
    // Test empty array with whitespace
    Str     json2 = StrInitFromZstr("{\"data\": [  ] }");
    StrIter si2   = StrIterFromStr(json2);
    bool success = true;
    
    Str     json = StrInitFromZstr("{\"name\":\"\",\"description\":\"\"}");
    StrIter si   = StrIterFromStr(json);
    bool success = true;
    
    Str     json = StrInitFromZstr("{\"temp\":-25,\"balance\":-1000.50,\"delta\":-0.001}");
    StrIter si   = StrIterFromStr(json);
    bool success = true;
    
    Str json = StrInitFromZstr(
    "{\"big_int\":9223372036854775807,\"big_float\":1.7976931348623157e+308,\"small_float\":2.2250738585072014e-"
    "308}"
    bool success = true;
    
    Str     json = StrInitFromZstr("{\"int_zero\":0,\"float_zero\":0.0,\"bool_false\":false}");
    StrIter si   = StrIterFromStr(json);
    
    // Test with various special characters that might be problematic
    Str json = StrInitFromZstr(
    "{\"path\":\"C:\\\\Program Files\\\\App\",\"message\":\"Hello, "
    "\\\"World\\\"!\",\"data\":\"line1\\nline2\\ttab\"}"
    
    Str json =
    StrInitFromZstr("{\"escaped\":\"\\\"quotes\\\"\",\"backslash\":\"\\\\\",\"newline\":\"\\n\",\"tab\":\"\\t\"}");
    StrIter si = StrIterFromStr(json);
    
    // Test with lots of different whitespace patterns
    Str     json = StrInitFromZstr("  {\n\t\"name\"  :  \"test\"  ,\n  \"value\": 42\t,\"flag\"\n:\ntrue\n}\t");
    StrIter si   = StrIterFromStr(json);
    bool success = true;
    
    Str     json = StrInitFromZstr("{\"outer\":{},\"list\":[],\"deep\":{\"inner\":{}}}");
    StrIter si   = StrIterFromStr(json);
    bool success = true;
    
    Str     json = StrInitFromZstr("{\"empty_obj\":{},\"filled_obj\":{\"x\":1},\"empty_arr\":[],\"filled_arr\":[1,2]}");
    StrIter si   = StrIterFromStr(json);
    
    // Using smaller values that are safer to work with
    Str     json = StrInitFromZstr("{\"max_int\":2147483647,\"min_int\":-2147483648,\"one\":1,\"minus_one\":-1}");
    StrIter si   = StrIterFromStr(json);
    bool success = true;
    
    Str json   = StrInitFromZstr("{\"tiny\":0.000001,\"huge\":999999.999999,\"zero\":0.0,\"negative_tiny\":-0.000001}");
    StrIter si = StrIterFromStr(json);
    bool compare_json_output(const Str *output, const char *expected) {
    // Create a copy of expected without spaces for comparison
    Str expected_str   = StrInitFromZstr(expected);
    Str output_clean   = StrInit();
    Str expected_clean = StrInit();
    
    // Note: These are the actual characters, not escape sequences
    Str path    = StrInitFromZstr("C:\\Program Files\\App");
    Str message = StrInitFromZstr("Hello, \"World\"!");
    Str data    = StrInitFromZstr("line1\nline2\ttab");
    // Note: These are the actual characters, not escape sequences
    Str path    = StrInitFromZstr("C:\\Program Files\\App");
    Str message = StrInitFromZstr("Hello, \"World\"!");
    Str data    = StrInitFromZstr("line1\nline2\ttab");
    Str path    = StrInitFromZstr("C:\\Program Files\\App");
    Str message = StrInitFromZstr("Hello, \"World\"!");
    Str data    = StrInitFromZstr("line1\nline2\ttab");
    
    JW_OBJ(json, {
    
    // These contain actual special characters that should be escaped
    Str quotes    = StrInitFromZstr("\"quotes\"");
    Str backslash = StrInitFromZstr("\\");
    Str newline   = StrInitFromZstr("\n");
    // These contain actual special characters that should be escaped
    Str quotes    = StrInitFromZstr("\"quotes\"");
    Str backslash = StrInitFromZstr("\\");
    Str newline   = StrInitFromZstr("\n");
    Str tab       = StrInitFromZstr("\t");
    Str quotes    = StrInitFromZstr("\"quotes\"");
    Str backslash = StrInitFromZstr("\\");
    Str newline   = StrInitFromZstr("\n");
    Str tab       = StrInitFromZstr("\t");
    Str backslash = StrInitFromZstr("\\");
    Str newline   = StrInitFromZstr("\n");
    Str tab       = StrInitFromZstr("\t");
    
    JW_OBJ(json, {
    
    // Single string
    Str single_str = StrInitFromZstr("hello");
    JW_OBJ(json2, { JW_STR_KV(json2, "text", single_str); });
    // Helper function to compare JSON output (removes whitespace for comparison)
    bool compare_json_output(const Str *output, const char *expected) {
    Str expected_str   = StrInitFromZstr(expected);
    Str output_clean   = StrInit();
    Str expected_clean = StrInit();
    Str status;
    } data = {
    {123, {StrInitFromZstr("Alice"), 30}},
    StrInitFromZstr("active")
    };
    } data = {
    {123, {StrInitFromZstr("Alice"), 30}},
    StrInitFromZstr("active")
    };
    } company;
    } data = {
    {{{StrInitFromZstr("John"), 25, 150000.0}}, StrInitFromZstr("TechCorp")}
    };
    Str  json    = StrInit();
    
    ApiResponse response = {true, StrInitFromZstr("Success"), VecInitWithDeepCopy(NULL, AnnSymbolDeinit)};
    
    // Add sample data
    // Add sample data
    AnnSymbol sym             = {0};
    sym.analysis_name         = StrInitFromZstr("test_analysis");
    sym.function_name         = StrInitFromZstr("main_func");
    sym.sha256                = StrInitFromZstr("abc123");
    AnnSymbol sym             = {0};
    sym.analysis_name         = StrInitFromZstr("test_analysis");
    sym.function_name         = StrInitFromZstr("main_func");
    sym.sha256                = StrInitFromZstr("abc123");
    sym.function_mangled_name = StrInitFromZstr("_Z4main");
    sym.analysis_name         = StrInitFromZstr("test_analysis");
    sym.function_name         = StrInitFromZstr("main_func");
    sym.sha256                = StrInitFromZstr("abc123");
    sym.function_mangled_name = StrInitFromZstr("_Z4main");
    sym.source_function_id    = 12345;
    sym.function_name         = StrInitFromZstr("main_func");
    sym.sha256                = StrInitFromZstr("abc123");
    sym.function_mangled_name = StrInitFromZstr("_Z4main");
    sym.source_function_id    = 12345;
    sym.target_function_id    = 67890;
    Vec(FunctionInfo) functions = VecInitWithDeepCopy(NULL, FunctionInfoDeinit);
    
    FunctionInfo func1 = {12345, StrInitFromZstr("test_func"), 1024, 4096};
    FunctionInfo func2 = {54321, StrInitFromZstr("helper_func"), 512, 8192};
    VecPushBack(&functions, func1);
    
    FunctionInfo func1 = {12345, StrInitFromZstr("test_func"), 1024, 4096};
    FunctionInfo func2 = {54321, StrInitFromZstr("helper_func"), 512, 8192};
    VecPushBack(&functions, func1);
    VecPushBack(&functions, func2);
    SearchResult result = {0};
    result.binary_id    = 888;
    result.binary_name  = StrInitFromZstr("test_binary");
    result.analysis_id  = 999;
    result.sha256       = StrInitFromZstr("abc123");
    result.binary_name  = StrInitFromZstr("test_binary");
    result.analysis_id  = 999;
    result.sha256       = StrInitFromZstr("abc123");
    result.tags         = VecInitWithDeepCopyT(result.tags, NULL, StrDeinit);
    
    // Create strings and push them properly
    Str tag1 = StrInitFromZstr("malware");
    Str tag2 = StrInitFromZstr("x86");
    // Create strings and push them properly
    Str tag1 = StrInitFromZstr("malware");
    Str tag2 = StrInitFromZstr("x86");
    
    VecPushBack(&result.tags, tag1);
    VecPushBack(&result.tags, tag2);
    
    result.created_at = StrInitFromZstr("2024-04-01");
    result.model_id   = 12345;
    result.model_name = StrInitFromZstr("test_model");
    result.created_at = StrInitFromZstr("2024-04-01");
    result.model_id   = 12345;
    result.model_name = StrInitFromZstr("test_model");
    result.owned_by   = StrInitFromZstr("user1");
    result.model_id   = 12345;
    result.model_name = StrInitFromZstr("test_model");
    result.owned_by   = StrInitFromZstr("user1");
    
    JW_OBJ(json, {
    
    AnnSymbol sym1             = {0};
    sym1.analysis_name         = StrInitFromZstr("analysis1");
    sym1.function_name         = StrInitFromZstr("func1");
    sym1.sha256                = StrInitFromZstr("hash1");
    AnnSymbol sym1             = {0};
    sym1.analysis_name         = StrInitFromZstr("analysis1");
    sym1.function_name         = StrInitFromZstr("func1");
    sym1.sha256                = StrInitFromZstr("hash1");
    sym1.function_mangled_name = StrInitFromZstr("_Z5func1");
    sym1.analysis_name         = StrInitFromZstr("analysis1");
    sym1.function_name         = StrInitFromZstr("func1");
    sym1.sha256                = StrInitFromZstr("hash1");
    sym1.function_mangled_name = StrInitFromZstr("_Z5func1");
    sym1.source_function_id    = 111;
    sym1.function_name         = StrInitFromZstr("func1");
    sym1.sha256                = StrInitFromZstr("hash1");
    sym1.function_mangled_name = StrInitFromZstr("_Z5func1");
    sym1.source_function_id    = 111;
    sym1.target_function_id    = 222;
    
    AnnSymbol sym2             = {0};
    sym2.analysis_name         = StrInitFromZstr("analysis2");
    sym2.function_name         = StrInitFromZstr("func2");
    sym2.sha256                = StrInitFromZstr("hash2");
    AnnSymbol sym2             = {0};
    sym2.analysis_name         = StrInitFromZstr("analysis2");
    sym2.function_name         = StrInitFromZstr("func2");
    sym2.sha256                = StrInitFromZstr("hash2");
    sym2.function_mangled_name = StrInitFromZstr("_Z5func2");
    sym2.analysis_name         = StrInitFromZstr("analysis2");
    sym2.function_name         = StrInitFromZstr("func2");
    sym2.sha256                = StrInitFromZstr("hash2");
    sym2.function_mangled_name = StrInitFromZstr("_Z5func2");
    sym2.source_function_id    = 333;
    sym2.function_name         = StrInitFromZstr("func2");
    sym2.sha256                = StrInitFromZstr("hash2");
    sym2.function_mangled_name = StrInitFromZstr("_Z5func2");
    sym2.source_function_id    = 333;
    sym2.target_function_id    = 444;
    
    // Create strings for the nested structure
    Str deep_message = StrInitFromZstr("deep");
    Str test_name    = StrInitFromZstr("test");
    // Create strings for the nested structure
    Str deep_message = StrInitFromZstr("deep");
    Str test_name    = StrInitFromZstr("test");
    
    JW_OBJ(json, {
    
    // Create strings and push them properly
    Str str1 = StrInitFromZstr("a");
    Str str2 = StrInitFromZstr("b");
    Str str3 = StrInitFromZstr("c");
    // Create strings and push them properly
    Str str1 = StrInitFromZstr("a");
    Str str2 = StrInitFromZstr("b");
    Str str3 = StrInitFromZstr("c");
    Str str1 = StrInitFromZstr("a");
    Str str2 = StrInitFromZstr("b");
    Str str3 = StrInitFromZstr("c");
    
    VecPushBack(&strings, str1);
    if (zstr) {
    StrDeinit(str);
    *str = StrInitFromZstr(zstr);
    free(zstr);
    }

Share :