StringZilla is not a drop-in replacement for the C Standard Library.
It’s designed to be a safer and more modern alternative.
Conceptually:
- LibC strings are expected to be null-terminated, so to use the efficient LibC implementations on slices of larger strings, you’d have to copy them, which is more expensive than the original string operation.
- LibC functionality is asymmetric — you can find the first and the last occurrence of a character within a string, but you can’t find the last occurrence of a substring.
- LibC function names are typically very short and cryptic.
- LibC lacks crucial functionality like hashing and doesn’t provide primitives for less critical but relevant operations like fuzzy matching.
Something has to be said about its support for UTF-8.
Aside from a single-byte char type, LibC provides wchar_t:
- The size of
wchar_t is not consistent across platforms.
On Windows, it’s typically 16 bits (suitable for UTF-16), while on Unix-like systems, it’s usually 32 bits (suitable for UTF-32).
This inconsistency can lead to portability issues when writing cross-platform code. wchar_t is designed to represent wide characters in a fixed-width format (UTF-16 or UTF-32).
In contrast, UTF-8 is a variable-length encoding, where each character can take from 1 to 4 bytes.
This fundamental difference means that wchar_t and UTF-8 are incompatible.
StringZilla partially addresses those issues.
STRINGZILLA_DEBUG:
For maximal performance, the C library does not perform any bounds checking in Release builds.
In C++, bounds checking happens only in places where the STL std::string would do it.
If you want to enable more aggressive bounds-checking, define STRINGZILLA_DEBUG before including the header.
If not explicitly set, it will be inferred from the build type.
STRINGZILLA_TARGET_GOLDMONT, STRINGZILLA_TARGET_WESTMERE, STRINGZILLA_TARGET_HASWELL, STRINGZILLA_TARGET_SKYLAKE, STRINGZILLA_TARGET_ICELAKE, STRINGZILLA_TARGET_NEON, STRINGZILLA_TARGET_NEONAES, STRINGZILLA_TARGET_NEONSHA, STRINGZILLA_TARGET_SVE, STRINGZILLA_TARGET_SVE2, STRINGZILLA_TARGET_SVE2AES, STRINGZILLA_TARGET_V128, STRINGZILLA_TARGET_V128RELAXED, STRINGZILLA_TARGET_RVV, STRINGZILLA_TARGET_LOONGSONASX, STRINGZILLA_TARGET_POWERVSX:
One can explicitly enable or disable individual SIMD families for compatibility or benchmarking purposes.
In header-only use the defaults are inferred from the compiler’s predefined macros under your own -march flags; LASX and POWER9 need your -mlasx and -mcpu=power9, as their intrinsics headers hide without them.
The CMake build, which every binding goes through, resolves them from the probes/ sources instead — compiling each capability’s probe, which calls one of its kernels, to learn whether the toolchain builds them — so the libraries carry every compilable capability.
The same names work as CMake cache options (-D STRINGZILLA_TARGET_SVE2=0) and as Cargo environment variables (STRINGZILLA_TARGET_SVE2=0 cargo build); an explicit 1 keeps a capability only where its probe compiles.
STRINGZILLA_TARGET_CUDA, STRINGZILLA_TARGET_ROCM, STRINGZILLA_TARGET_METAL:
Compile the GPU kernels of one vendor: CUDA wherever the unit is compiled as CUDA, by nvcc or by Clang, ROCm wherever it is compiled as HIP, and Metal wherever the build links Metal and Foundation, as STRINGZILLA_METAL_ARCH does.
The Metal kernels travel as embedded source and compile on the device at first use.
Each defaults to 1 wherever its vendor is present, and setting it to 0 keeps the host API while dropping that vendor’s kernels.
STRINGZILLA_HEADER_ONLY:
By default, the headers declare the StringZilla library, which compiles every capability once and dispatches among them at runtime, as the shared library and every binding do.
Set it to 1 to inline the kernels your compiler flags enable instead, calling them by name; the dispatch points and finders then report sz_missing_library_k.
STRINGZILLA_ALLOW_MISALIGNED_LOADS:
Default is platform-dependent: enabled on x86 (where unaligned accesses are fast), disabled on others by default.
When enabled, many byte-level operations use word-sized loads, which can significantly accelerate the serial (SWAR) backend.
Consider enabling it explicitly if you are targeting platforms that support fast unaligned loads.
STRINGZILLA_WITH_LIBC:
Both the library and the C headers can be built without LibC.
This may affect the type resolution system on obscure hardware platforms.
STRINGZILLA_WITH_STL:
When using the C++ interface one can disable implicit conversions from std::string to sz::string_t and back.
If not needed, the <string> and <string_view> headers will be excluded, reducing compilation time.
STRINGZILLA_BUILD_SHARED, STRINGZILLA_BUILD_TEST, STRINGZILLA_BUILD_BENCH, STRINGZILLA_MARCH for CMake users:
When compiling the tests and benchmarks, you can explicitly set the target hardware architecture.
It’s synonymous to GCC’s -march flag and is used to enable/disable the appropriate instruction sets.
You can also disable the shared library build, if you don’t need it.