Skip to main content

SIMD-accelerated string search, sort, hashes, fingerprints, & edit distances

Project description

StringZilla 🦖

StringZilla banner

The world wastes a minimum of $100M annually due to inefficient string operations. A typical codebase processes strings character by character, resulting in too many branches and data-dependencies, neglecting 90% of modern CPU's potential. LibC is different. It attempts to leverage SIMD instructions to boost some operations, and is often used by higher-level languages, runtimes, and databases. But it isn't perfect. 1️⃣ First, even on common hardware, including over a billion 64-bit ARM CPUs, common functions like strstr and memmem only achieve 1/3 of the CPU's thoughput. 2️⃣ Second, SIMD coverage is inconsistent: acceleration in forward scans does not guarantee speed in the reverse-order search. 3️⃣ At last, most high-level languages can't always use LibC, as the strings are often not NULL-terminated or may contain the Unicode "Zero" character in the middle of the string. That's why StringZilla was created. To provide predictably high performance, portable to any modern platform, operating system, and programming language.

StringZilla Python installs StringZilla Rust installs GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status StringZilla code size

StringZilla is the GodZilla of string libraries, using SIMD and SWAR to accelerate string operations on modern CPUs. It is up to 10x faster than the default and even other SIMD-accelerated string libraries in C, C++, Python, and other languages, while covering broad functionality. It accelerates exact and fuzzy string matching, edit distance computations, sorting, lazily-evaluated ranges to avoid memory allocations, and even random-string generators.

  • 🐂 C : Upgrade LibC's <string.h> to <stringzilla.h> in C 99
  • 🐉 C++: Upgrade STL's <string> to <stringzilla.hpp> in C++ 11
  • 🐍 Python: Upgrade your str to faster Str
  • 🍎 Swift: Use the String+StringZilla extension
  • 🦀 Rust: Use the StringZilla traits crate
  • 🐚 Shell: Accelerate common CLI tools with sz_ prefix
  • 📚 Researcher? Jump to Algorithms & Design Decisions
  • 💡 Thinking to contribute? Look for "good first issues"
  • 🤝 And check the guide to setup the environment
  • Want more bindings or features? Let me know!

Who is this for?

  • For data-engineers parsing large datasets, like the CommonCrawl, RedPajama, or LAION.
  • For software engineers optimizing strings in their apps and services.
  • For bioinformaticians and search engineers looking for edit-distances for USearch.
  • For DBMS devs, optimizing LIKE, ORDER BY, and GROUP BY operations.
  • For hardware designers, needing a SWAR baseline for strings-processing functionality.
  • For students studying SIMD/SWAR applications to non-data-parallel operations.

Performance

C C++ Python StringZilla
find the first occurrence of a random word from text, ≅ 5 bytes long
strstr 1
x86: 7.4 · arm: 2.0 GB/s
.find
x86: 2.9 · arm: 1.6 GB/s
.find
x86: 1.1 · arm: 0.6 GB/s
sz_find
x86: 10.6 · arm: 7.1 GB/s
find the last occurrence of a random word from text, ≅ 5 bytes long
.rfind
x86: 0.5 · arm: 0.4 GB/s
.rfind
x86: 0.9 · arm: 0.5 GB/s
sz_rfind
x86: 10.8 · arm: 6.7 GB/s
split lines separated by \n or \r 2
strcspn 1
x86: 5.42 · arm: 2.19 GB/s
.find_first_of
x86: 0.59 · arm: 0.46 GB/s
re.finditer
x86: 0.06 · arm: 0.02 GB/s
sz_find_charset
x86: 4.08 · arm: 3.22 GB/s
find the last occurrence of any of 6 whitespaces 2
.find_last_of
x86: 0.25 · arm: 0.25 GB/s
sz_rfind_charset
x86: 0.43 · arm: 0.23 GB/s
Random string from a given alphabet, 20 bytes long 5
rand() % n
x86: 18.0 · arm: 9.4 MB/s
uniform_int_distribution
x86: 47.2 · arm: 20.4 MB/s
join(random.choices(...))
x86: 13.3 · arm: 5.9 MB/s
sz_generate
x86: 56.2 · arm: 25.8 MB/s
Get sorted order, ≅ 8 million English words 6
qsort_r
x86: 3.55 · arm: 5.77 s
std::sort
x86: 2.79 · arm: 4.02 s
numpy.argsort
x86: 7.58 · arm: 13.00 s
sz_sort
x86: 1.91 · arm: 2.37 s
Levenshtein edit distance, ≅ 5 bytes long
via jellyfish 3
x86: 1,550 · arm: 2,220 ns
sz_edit_distance
x86: 99 · arm: 180 ns
Needleman-Wunsch alignment scores, ≅ 10 K aminoacids long
via biopython 4
x86: 257 · arm: 367 ms
sz_alignment_score
x86: 73 · arm: 177 ms

StringZilla has a lot of functionality, most of which is covered by benchmarks across C, C++, Python and other languages. You can find those in the ./scripts directory, with usage notes listed in the CONTRIBUTING.md file. Notably, if the CPU supports misaligned loads, even the 64-bit SWAR backends are faster than either standard library.

Most benchmarks were conducted on a 1 GB English text corpus, with an average word length of 5 characters. The code was compiled with GCC 12, using glibc v2.35. The benchmarks performed on Arm-based Graviton3 AWS c7g instances and r7iz Intel Sapphire Rapids. Most modern Arm-based 64-bit CPUs will have similar relative speedups. Variance withing x86 CPUs will be larger. 1 Unlike other libraries, LibC requires strings to be NULL-terminated. 2 Six whitespaces in the ASCII set are: \t\n\v\f\r. Python's and other standard libraries have specialized functions for those. 3 Most Python libraries for strings are also implemented in C. 4 Unlike the rest of BioPython, the alignment score computation is implemented in C. 5 All modulo operations were conducted with uint8_t to allow compilers more optimization opportunities. The C++ STL and StringZilla benchmarks used a 64-bit Mersenne Twister as the generator. For C, C++, and StringZilla, an in-place update of the string was used. In Python every string had to be allocated as a new object, which makes it less fair. 6 Contrary to the popular opinion, Python's default sorted function works faster than the C and C++ standard libraries. That holds for large lists or tuples of strings, but fails as soon as you need more complex logic, like sorting dictionaries by a string key, or producing the "sorted order" permutation. The latter is very common in database engines and is most similar to numpy.argsort. Current StringZilla solution can be at least 4x faster without loss of generality.

Functionality

StringZilla is compatible with most modern CPUs, and provides a broad range of functionality.

  • works on both Little-Endian and Big-Endian architectures.
  • works on 32-bit and 64-bit hardware architectures.
  • compatible with ASCII and UTF-8 encoding.

Not all features are available across all bindings. Consider contributing, if you need a feature that's not yet implemented.

Maturity C 99 C++ 11 Python Swift Rust
Substring Search 🌳
Character Set Search 🌳
Edit Distances 🧐
Small String Class 🧐
Sorting & Sequence Operations 🚧
Lazy Ranges, Compressed Arrays 🧐
Hashes & Fingerprints 🚧

🌳 parts are used in production. 🧐 parts are in beta. 🚧 parts are under active development, and are likely to break in subsequent releases. ✅ are implemented. ⚪ are considered. ❌ are not intended.

Quick Start: Python 🐍

Python bindings are available on PyPI, and can be installed with pip. You can immediately check the installed version and the used hardware capabilities with following commands:

pip install stringzilla
python -c "import stringzilla; print(stringzilla.__version__)"
python -c "import stringzilla; print(stringzilla.__capabilities__)"

Basic Usage

If you've ever used the Python str, bytes, bytearray, memoryview class, you'll know what to expect. StringZilla's Str class is a hybrid of those two, providing str-like interface to byte-arrays.

from stringzilla import Str, File

text_from_str = Str('some-string') # no copies, just a view
text_from_file = Str(File('some-file.txt')) # memory-mapped file

The File class memory-maps a file from persistent memory without loading its copy into RAM. The contents of that file would remain immutable, and the mapping can be shared by multiple Python processes simultaneously. A standard dataset pre-processing use case would be to map a sizeable textual dataset like Common Crawl into memory, spawn child processes, and split the job between them.

Basic Operations

  • Length: len(text) -> int
  • Indexing: text[42] -> str
  • Slicing: text[42:46] -> Str
  • Substring check: 'substring' in text -> bool
  • Hashing: hash(text) -> int
  • String conversion: str(text) -> str

Advanced Operations

import sys

x: bool = text.contains('substring', start=0, end=sys.maxsize)
x: int = text.find('substring', start=0, end=sys.maxsize)
x: int = text.count('substring', start=0, end=sys.maxsize, allowoverlap=False)
x: str = text.decode(encoding='utf-8', errors='strict')
x: Strs = text.split(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.splitlines(keeplinebreaks=False, maxsplit=sys.maxsize)

It's important to note, that the last function behavior is slightly different from Python's str.splitlines. The native version matches \n, \r, \v or \x0b, \f or \x0c, \x1c, \x1d, \x1e, \x85, \r\n, \u2028, \u2029, including 3x two-bytes-long runes. The StringZilla version matches only \n, \v, \f, \r, \x1c, \x1d, \x1e, \x85, avoiding two-byte-long runes.

Character Set Operations

Python strings don't natively support character set operations. This forces people to use regular expressions, which are slow and hard to read. To avoid the need for re.finditer, StringZilla provides the following interfaces:

x: int = text.find_first_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_of('chars', start=0, end=sys.maxsize)
x: int = text.find_first_not_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_not_of('chars', start=0, end=sys.maxsize)
x: Strs = text.split_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)

Collection-Level Operations

Once split into a Strs object, you can sort, shuffle, and reorganize the slices, with minimum memory footprint. If all the chunks are located in consecutive memory regions, the memory overhead can be as low as 4 bytes per chunk.

lines: Strs = text.split(separator='\n') # 4 bytes per line overhead for under 4 GB of text
batch: Strs = lines.sample(seed=42) # 10x faster than `random.choices`
lines.shuffle(seed=42) # or shuffle all lines in place and shard with slices
# WIP: lines.sort() # explodes to 16 bytes per line overhead for any length text
# WIP: sorted_order: tuple = lines.argsort() # similar to `numpy.argsort`

Working on RedPajama, addressing 20 Billion annotated english documents, one will need only 160 GB of RAM instead of Terabytes. Once loaded, the data will be memory-mapped, and can be reused between multiple Python processes without copies. And of course, you can use slices to navigate the dataset and shard it between multiple workers.

lines[::3] # every third line
lines[1::1] # every odd line
lines[:-100:-1] # last 100 lines in reverse order

Iterators and Memory Efficiency

Python's operations like split() and readlines() immediately materialize a list of copied parts. This can be very memory-inefficient for large datasets. StringZilla saves a lot of memory by viewing existing memory regions as substrings, but even more memory can be saved by using lazily evaluated iterators.

x: SplitIterator[Str] = text.split_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.split_charset_iter(separator='chars', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_charset_iter(separator='chars', keepseparator=False)

StringZilla can easily be 10x more memory efficient than native Python classes for tokenization. With lazy operations, it practically becomes free.

import stringzilla as sz
%load_ext memory_profiler

text = open("enwik9.txt", "r").read() # 1 GB, mean word length 7.73 bytes
%memit text.split() # increment: 8670.12 MiB (152 ms)
%memit sz.split(text) # increment: 530.75 MiB (25 ms)
%memit sum(1 for _ in sz.split_iter(text)) # increment: 0.00 MiB

Low-Level Python API

Aside from calling the methods on the Str and Strs classes, you can also call the global functions directly on str and bytes instances. Assuming StringZilla CPython bindings are implemented without any intermediate tools like SWIG or PyBind, the call latency should be similar to native classes.

import stringzilla as sz

contains: bool = sz.contains("haystack", "needle", start=0, end=sys.maxsize)
offset: int = sz.find("haystack", "needle", start=0, end=sys.maxsize)
count: int = sz.count("haystack", "needle", start=0, end=sys.maxsize, allowoverlap=False)

Edit Distances

assert sz.edit_distance("apple", "aple") == 1 # skip one ASCII character
assert sz.edit_distance("αβγδ", "αγδ") == 2 # skip two bytes forming one rune
assert sz.edit_distance_unicode("αβγδ", "αγδ") == 1 # one unicode rune

Several Python libraries provide edit distance computation. Most of them are implemented in C, but are not always as fast as StringZilla. Taking a 1'000 long proteins around 10'000 characters long, computing just a 100 distances:

Moreover, you can pass custom substitution matrices to compute the Needleman-Wunsch alignment scores. That task is very common in bioinformatics and computational biology. It's natively supported in BioPython, and its BLOSUM matrices can be converted to StringZilla's format. Alternatively, you can construct an arbitrary 256 by 256 cost matrix using NumPy. Depending on arguments, the result may be equal to the negative Levenshtein distance.

import numpy as np
import stringzilla as sz

costs = np.zeros((256, 256), dtype=np.int8)
costs.fill(-1)
np.fill_diagonal(costs, 0)

assert sz.alignment_score("first", "second", substitution_matrix=costs, gap_score=-1) == -sz.edit_distance(a, b)

Using the same proteins as for Levenshtein distance benchmarks:

§ Example converting from BioPython to StringZilla.
import numpy as np
from Bio import Align
from Bio.Align import substitution_matrices

aligner = Align.PairwiseAligner()
aligner.substitution_matrix = substitution_matrices.load("BLOSUM62")
aligner.open_gap_score = 1
aligner.extend_gap_score = 1

# Convert the matrix to NumPy
subs_packed = np.array(aligner.substitution_matrix).astype(np.int8)
subs_reconstructed = np.zeros((256, 256), dtype=np.int8)

# Initialize all banned characters to a the largest possible penalty
subs_reconstructed.fill(127)
for packed_row, packed_row_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
    for packed_column, packed_column_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
        reconstructed_row = ord(packed_row_aminoacid)
        reconstructed_column = ord(packed_column_aminoacid)
        subs_reconstructed[reconstructed_row, reconstructed_column] = subs_packed[packed_row, packed_column]

# Let's pick two examples for of tri-peptides (made of 3 aminoacids)
glutathione = "ECG" # Need to rebuild human tissue?
thyrotropin_releasing_hormone = "QHP" # Or to regulate your metabolism?

assert sz.alignment_score(
    glutathione,
    thyrotropin_releasing_hormone, 
    substitution_matrix=subs_reconstructed, 
    gap_score=1) == aligner.score(glutathione, thyrotropin_releasing_hormone) # Equal to 6

Serialization

Filesystem

Similar to how File can be used to read a large file, other interfaces can be used to dump strings to disk faster. The Str class has write_to to write the string to a file, and offset_within to obtain integer offsets of substring view in larger string for navigation.

web_archieve = Str("<html>...</html><html>...</html>")
_, end_tag, next_doc = web_archieve.partition("</html>") # or use `find`
next_doc_offset = next_doc.offset_within(web_archieve)
web_archieve.write_to("next_doc.html") # no GIL, no copies, just a view

PyArrow

A Str is easy to cast to PyArrow buffers.

from pyarrow import foreign_buffer
from stringzilla import Str

original = "hello"
view = Str(native)
arrow = foreign_buffer(view.address, view.nbytes, view)

That means you can convert Str to pyarrow.Buffer and Strs to pyarrow.Array without extra copies.

Quick Start: C/C++ 🛠️

The C library is header-only, so you can just copy the stringzilla.h header into your project. Same applies to C++, where you would copy the stringzilla.hpp header. Alternatively, add it as a submodule, and include it in your build system.

git submodule add https://github.com/ashvardanian/stringzilla.git

Or using a pure CMake approach:

FetchContent_Declare(stringzilla GIT_REPOSITORY https://github.com/ashvardanian/stringzilla.git)
FetchContent_MakeAvailable(stringzilla)

Last, but not the least, you can also install it as a library, and link against it. This approach is worse for inlining, but brings dynamic runtime dispatch for the most advanced CPU features.

Basic Usage with C 99 and Newer

There is a stable C 99 interface, where all function names are prefixed with sz_. Most interfaces are well documented, and come with self-explanatory names and examples. In some cases, hardware specific overloads are available, like sz_find_avx512 or sz_find_neon. Both are companions of the sz_find, first for x86 CPUs with AVX-512 support, and second for Arm NEON-capable CPUs.

#include <stringzilla/stringzilla.h>

// Initialize your haystack and needle
sz_string_view_t haystack = {your_text, your_text_length};
sz_string_view_t needle = {your_subtext, your_subtext_length};

// Perform string-level operations
sz_size_t substring_position = sz_find(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_avx512(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_neon(haystack.start, haystack.length, needle.start, needle.length);

// Hash strings
sz_u64_t hash = sz_hash(haystack.start, haystack.length);

// Perform collection level operations
sz_sequence_t array = {your_order, your_count, your_get_start, your_get_length, your_handle};
sz_sort(&array, &your_config);
§ Mapping from LibC to StringZilla.

By design, StringZilla has a couple of notable differences from LibC:

  1. all strings are expected to have a length, and are not necessarily null-terminated.
  2. every operations has a reverse order counterpart.

That way sz_find and sz_rfind are similar to strstr and strrstr in LibC. Similarly, sz_find_byte and sz_rfind_byte replace memchr and memrchr. The sz_find_charset maps to strspn and strcspn, while sz_rfind_charset has no sibling in LibC.

LibC Functionality StringZilla Equivalents
memchr(haystack, needle, haystack_length), strchr sz_find_byte(haystack, haystack_length, needle)
memrchr(haystack, needle, haystack_length) sz_rfind_byte(haystack, haystack_length, needle)
memcmp, strcmp sz_order, sz_equal
strlen(haystack) sz_find_byte(haystack, haystack_length, needle)
strcspn(haystack, needles) sz_rfind_charset(haystack, haystack_length, needles_bitset)
strspn(haystack, needles) sz_find_charset(haystack, haystack_length, needles_bitset)
memmem(haystack, haystack_length, needle, needle_length), strstr sz_find(haystack, haystack_length, needle, needle_length)
memcpy(destination, source, destination_length) sz_copy(destination, source, destination_length)
memmove(destination, source, destination_length) sz_move(destination, source, destination_length)
memset(destination, value, destination_length) sz_fill(destination, destination_length, value)

Basic Usage with C++ 11 and Newer

There is a stable C++ 11 interface available in the ashvardanian::stringzilla namespace. It comes with two STL-like classes: string_view and string. The first is a non-owning view of a string, and the second is a mutable string with a Small String Optimization.

#include <stringzilla/stringzilla.hpp>

namespace sz = ashvardanian::stringzilla;

sz::string haystack = "some string";
sz::string_view needle = sz::string_view(haystack).substr(0, 4);

auto substring_position = haystack.find(needle); // Or `rfind`
auto hash = std::hash<sz::string_view>(haystack); // Compatible with STL's `std::hash`

haystack.end() - haystack.begin() == haystack.size(); // Or `rbegin`, `rend`
haystack.find_first_of(" \w\t") == 4; // Or `find_last_of`, `find_first_not_of`, `find_last_not_of`
haystack.starts_with(needle) == true; // Or `ends_with`
haystack.remove_prefix(needle.size()); // Why is this operation in-place?!
haystack.contains(needle) == true; // STL has this only from C++ 23 onwards
haystack.compare(needle) == 1; // Or `haystack <=> needle` in C++ 20 and beyond

StringZilla also provides string literals for automatic type resolution, similar to STL:

using sz::literals::operator""_sz;
using std::literals::operator""sv;

auto a = "some string"; // char const *
auto b = "some string"sv; // std::string_view
auto b = "some string"_sz; // sz::string_view

Memory Ownership and Small String Optimization

Most operations in StringZilla don't assume any memory ownership. But in addition to the read-only search-like operations StringZilla provides a minimalistic C and C++ implementations for a memory owning string "class". Like other efficient string implementations, it uses the Small String Optimization (SSO) to avoid heap allocations for short strings.

typedef union sz_string_t {
    struct internal {
        sz_ptr_t start;
        sz_u8_t length;
        char chars[SZ_STRING_INTERNAL_SPACE]; /// Ends with a null-terminator.
    } internal;

    struct external {
        sz_ptr_t start;
        sz_size_t length;        
        sz_size_t space; /// The length of the heap-allocated buffer.
        sz_size_t padding;
    } external;

} sz_string_t;

As one can see, a short string can be kept on the stack, if it fits within internal.chars array. Before 2015 GCC string implementation was just 8 bytes, and could only fit 7 characters. Different STL implementations today have different thresholds for the Small String Optimization. Similar to GCC, StringZilla is 32 bytes in size, and similar to Clang it can fit 22 characters on stack. Our layout might be preferential, if you want to avoid branches. If you use a different compiler, you may want to check it's SSO buffer size with a simple Gist.

libstdc++ in GCC 13 libc++ in Clang 17 StringZilla
sizeof(std::string) 32 24 32
Small String Capacity 15 22 22

This design has been since ported to many high-level programming languages. Swift, for example, can store 15 bytes in the String instance itself. StringZilla implements SSO at the C level, providing the sz_string_t union and a simple API for primary operations.

sz_memory_allocator_t allocator;
sz_string_t string;

// Init and make sure we are on stack
sz_string_init(&string);
sz_string_is_on_stack(&string); // == sz_true_k

// Optionally pre-allocate space on the heap for future insertions.
sz_string_grow(&string, 100, &allocator); // == sz_true_k

// Append, erase, insert into the string.
sz_string_expand(&string, 0, "_Hello_", 7, &allocator); // == sz_true_k
sz_string_expand(&string, SZ_SIZE_MAX, "world", 5, &allocator); // == sz_true_k
sz_string_erase(&string, 0, 1);

// Unpacking & introspection.
sz_ptr_t string_start;
sz_size_t string_length;
sz_size_t string_space;
sz_bool_t string_is_external;
sz_string_unpack(string, &string_start, &string_length, &string_space, &string_is_external);
sz_equal(string_start, "Hello_world", 11); // == sz_true_k

// Reclaim some memory.
sz_string_shrink_to_fit(&string, &allocator); // == sz_true_k
sz_string_free(&string, &allocator);

Unlike the conventional C strings, the sz_string_t is allowed to contain null characters. To safely print those, pass the string_length to printf as well.

printf("%.*s\n", (int)string_length, string_start);

What's Wrong with the C++ Standard Library?

C++ Code Evaluation Result Invoked Signature
"Loose"s.replace(2, 2, "vath"s, 1) "Loathe" 🤢 (pos1, count1, str2, pos2)
"Loose"s.replace(2, 2, "vath", 1) "Love" 🥰 (pos1, count1, str2, count2)

StringZilla is designed to be a drop-in replacement for the C++ Standard Templates Library. That said, some of the design decisions of STL strings are highly controversial, error-prone, and expensive. Most notably:

  1. Argument order for replace, insert, erase and similar functions is impossible to guess.
  2. Bounds-checking exceptions for substr-like functions are only thrown for one side of the range.
  3. Returning string copies in substr-like functions results in absurd volume of allocations.
  4. Incremental construction via push_back-like functions goes through too many branches.
  5. Inconsistency between string and string_view methods, like the lack of remove_prefix and remove_suffix.

Check the following set of asserts validating the std::string specification. It's not realistic to expect the average developer to remember the 14 overloads of std::string::replace.

using str = std::string;

assert(str("hello world").substr(6) == "world");
assert(str("hello world").substr(6, 100) == "world"); // 106 is beyond the length of the string, but its OK
assert_throws(str("hello world").substr(100), std::out_of_range);   // 100 is beyond the length of the string
assert_throws(str("hello world").substr(20, 5), std::out_of_range); // 20 is beyond the length of the string
assert_throws(str("hello world").substr(-1, 5), std::out_of_range); // -1 casts to unsigned without any warnings...
assert(str("hello world").substr(0, -1) == "hello world");          // -1 casts to unsigned without any warnings...

assert(str("hello").replace(1, 2, "123") == "h123lo");
assert(str("hello").replace(1, 2, str("123"), 1) == "h23lo");
assert(str("hello").replace(1, 2, "123", 1) == "h1lo");
assert(str("hello").replace(1, 2, "123", 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, str("123"), 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, 3, 'a') == "haaalo");
assert(str("hello").replace(1, 2, {'a', 'b'}) == "hablo");

To avoid those issues, StringZilla provides an alternative consistent interface. It supports signed arguments, and doesn't have more than 3 arguments per function or The standard API and our alternative can be conditionally disabled with SZ_SAFETY_OVER_COMPATIBILITY=1. When it's enabled, the subjectively risky overloads from the Standard will be disabled.

using str = sz::string;

str("a:b").front(1) == "a"; // no checks, unlike `substr`
str("a:b").back(-1) == "b"; // accepting negative indices
str("a:b").sub(1, -1) == ":"; // similar to Python's `"a:b"[1:-1]`
str("a:b").sub(-2, -1) == ":"; // similar to Python's `"a:b"[-2:-1]`
str("a:b").sub(-2, 1) == ""; // similar to Python's `"a:b"[-2:1]`
"a:b"_sz[{-2, -1}] == ":"; // works on views and overloads `operator[]`

Assuming StringZilla is a header-only library you can use the full API in some translation units and gradually transition to safer restricted API in others. Bonus - all the bound checking is branchless, so it has a constant cost and won't hurt your branch predictor.

Beyond the C++ Standard Library - Learning from Python

Python is arguably the most popular programming language for data science. In part, that's due to the simplicity of its standard interfaces. StringZilla brings some of that functionality to C++.

  • Content checks: isalnum, isalpha, isascii, isdigit, islower, isspace, isupper.
  • Trimming character sets: lstrip, rstrip, strip.
  • Trimming string matches: remove_prefix, remove_suffix.
  • Ranges of search results: splitlines, split, rsplit.
  • Number of non-overlapping substring matches: count.
  • Partitioning: partition, rpartition.

For example, when parsing documents, it is often useful to split it into substrings. Most often, after that, you would compute the length of the skipped part, the offset and the length of the remaining part. This results in a lot of pointer arithmetic and is error-prone. StringZilla provides a convenient partition function, which returns a tuple of three string views, making the code cleaner.

auto parts = haystack.partition(':'); // Matching a character
auto [before, match, after] = haystack.partition(':'); // Structure unpacking
auto [before, match, after] = haystack.partition(char_set(":;")); // Character-set argument
auto [before, match, after] = haystack.partition(" : "); // String argument
auto [before, match, after] = haystack.rpartition(sz::whitespaces); // Split around the last whitespace

Combining those with the split function, one can easily parse a CSV file or HTTP headers.

for (auto line : haystack.split("\r\n")) {
    auto [key, _, value] = line.partition(':');
    headers[key.strip()] = value.strip();
}

Some other extensions are not present in the Python standard library either. Let's go through the C++ functionality category by category.

Some of the StringZilla interfaces are not available even Python's native str class. Here is a sneak peek of the most useful ones.

text.hash(); // -> 64 bit unsigned integer 
text.ssize(); // -> 64 bit signed length to avoid `static_cast<std::ssize_t>(text.size())`
text.contains_only(" \w\t"); // == text.find_first_not_of(char_set(" \w\t")) == npos;
text.contains(sz::whitespaces); // == text.find(char_set(sz::whitespaces)) != npos;

// Simpler slicing than `substr`
text.front(10); // -> sz::string_view
text.back(10); // -> sz::string_view

// Safe variants, which clamp the range into the string bounds
using sz::string::cap;
text.front(10, cap) == text.front(std::min(10, text.size()));
text.back(10, cap) == text.back(std::min(10, text.size()));

// Character set filtering
text.lstrip(sz::whitespaces).rstrip(sz::newlines); // like Python
text.front(sz::whitespaces); // all leading whitespaces
text.back(sz::digits); // all numerical symbols forming the suffix

// Incremental construction
using sz::string::unchecked;
text.push_back('x'); // no surprises here
text.push_back('x', unchecked); // no bounds checking, Rust style
text.try_push_back('x'); // returns `false` if the string is full and the allocation failed

sz::concatenate(text, "@", domain, ".", tld); // No allocations

Splits and Ranges

One of the most common use cases is to split a string into a collection of substrings. Which would often result in StackOverflow lookups and snippets like the one below.

std::vector<std::string> lines = split(haystack, "\r\n"); // string delimiter
std::vector<std::string> words = split(lines, ' '); // character delimiter

Those allocate memory for each string and the temporary vectors. Each allocation can be orders of magnitude more expensive, than even serial for-loop over characters. To avoid those, StringZilla provides lazily-evaluated ranges, compatible with the Range-v3 library.

for (auto line : haystack.split("\r\n"))
    for (auto word : line.split(char_set(" \w\t.,;:!?")))
        std::cout << word << std::endl;

Each of those is available in reverse order as well. It also allows interleaving matches, if you want both inclusions of xx in xxx. Debugging pointer offsets is not a pleasant exercise, so keep the following functions in mind.

  • haystack.[r]find_all(needle, interleaving)
  • haystack.[r]find_all(char_set(""))
  • haystack.[r]split(needle)
  • haystack.[r]split(char_set(""))

For $N$ matches the split functions will report $N+1$ matches, potentially including empty strings. Ranges have a few convenience methods as well:

range.size(); // -> std::size_t
range.empty(); // -> bool
range.template to<std::set<std::sting>>(); 
range.template to<std::vector<std::sting_view>>(); 

Concatenating Strings without Allocations

Another common string operation is concatenation. The STL provides std::string::operator+ and std::string::append, but those are not very efficient, if multiple invocations are performed.

std::string name, domain, tld;
auto email = name + "@" + domain + "." + tld; // 4 allocations

The efficient approach would be to pre-allocate the memory and copy the strings into it.

std::string email;
email.reserve(name.size() + domain.size() + tld.size() + 2);
email.append(name), email.append("@"), email.append(domain), email.append("."), email.append(tld);

That's mouthful and error-prone. StringZilla provides a more convenient concatenate function, which takes a variadic number of arguments. It also overrides the operator| to concatenate strings lazily, without any allocations.

auto email = sz::concatenate(name, "@", domain, ".", tld);   // 0 allocations
auto email = name | "@" | domain | "." | tld;                // 0 allocations
sz::string email = name | "@" | domain | "." | tld;          // 1 allocations

Random Generation

Software developers often need to generate random strings for testing purposes. The STL provides std::generate and std::random_device, that can be used with StringZilla.

sz::string random_string(std::size_t length, char const *alphabet, std::size_t cardinality) {
    sz::string result(length, '\0');
    static std::random_device seed_source; // Too expensive to construct every time
    std::mt19937 generator(seed_source());
    std::uniform_int_distribution<std::size_t> distribution(0, cardinality);
    std::generate(result.begin(), result.end(), [&]() { return alphabet[distribution(generator)]; });
    return result;
}

Mouthful and slow. StringZilla provides a C native method - sz_generate and a convenient C++ wrapper - sz::generate. Similar to Python it also defines the commonly used character sets.

auto protein = sz::string::random(300, "ARNDCQEGHILKMFPSTWYV"); // static method
auto dna = sz::basic_string<custom_allocator>::random(3_000_000_000, "ACGT");

dna.randomize("ACGT"); // `noexcept` pre-allocated version
dna.randomize(&std::rand, "ACGT"); // pass any generator, like `std::mt19937`

char uuid[36];
sz::randomize(sz::string_span(uuid, 36), "0123456789abcdef-"); // Overwrite any buffer

Levenshtein Edit Distance and Alignment Scores

Levenshtein and Hamming edit distance are provided for both byte-strings and UTF-8 strings. The latter will output the distance in Unicode code points, not bytes. Needleman-Wunsch alignment scores are only defined for byte-strings.

// Count number of substitutions in same length strings
sz::hamming_distance(first, second[, upper_bound]) -> std::size_t;
sz::hamming_distance_utf8(first, second[, upper_bound]) -> std::size_t;

// Count number of insertions, deletions and substitutions
sz::edit_distance(first, second[, upper_bound[, allocator]]) -> std::size_t;
sz::edit_distance_utf8(first, second[, upper_bound[, allocator]]) -> std::size_t;

// Substitution-parametrized Needleman-Wunsch global alignment score
std::int8_t costs[256][256]; // Substitution costs matrix
sz::alignment_score(first, second, costs[, gap_score[, allocator]) -> std::ptrdiff_t;

Sorting in C and C++

LibC provides qsort and STL provides std::sort. Both have their quarks. The LibC standard has no way to pass a context to the comparison function, that's only possible with platform-specific extensions. Those have different arguments order on every OS.

// Linux: https://linux.die.net/man/3/qsort_r
void qsort_r(void *elements, size_t count, size_t element_width, 
    int (*compare)(void const *left, void const *right, void *context),
    void *context);
// MacOS and FreeBSD: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/qsort_r.3.html
void qsort_r(void *elements, size_t count, size_t element_width, 
    void *context,
    int (*compare)(void *context, void const *left, void const *right));
// Windows conflicts with ISO `qsort_s`: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170
void qsort_s(id *elements, size_t count, size_t element_width, 
    int (*compare)(void *context, void const *left, void const *right),
    void *context);

C++ generic algorithm is not perfect either. There is no guarantee in the standard that std::sort won't allocate any memory. If you are running on embedded, in real-time or on 100+ CPU cores per node, you may want to avoid that. StringZilla doesn't solve the general case, but hopes to improve the performance for strings. Use sz_sort, or the high-level sz::sorted_order, which can be used sort any collection of elements convertible to sz::string_view.

std::vector<std::string> data({"c", "b", "a"});
std::vector<std::size_t> order = sz::sorted_order(data); //< Simple shortcut

// Or, taking care of memory allocation:
sz::sorted_order(data.begin(), data.end(), order.data(), [](auto const &x) -> sz::string_view { return x; });

Standard C++ Containers with String Keys

The C++ Standard Templates Library provides several associative containers, often used with string keys.

std::map<std::string, int, std::less<std::string>> sorted_words;
std::unordered_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>> words;

The performance of those containers is often limited by the performance of the string keys, especially on reads. StringZilla can be used to accelerate containers with std::string keys, by overriding the default comparator and hash functions.

std::map<std::string, int, sz::string_view_less> sorted_words;
std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to> words;

Alternatively, a better approach would be to use the sz::string class as a key. The right hash function and comparator would be automatically selected and the performance gains would be more noticeable if the keys are short.

std::map<sz::string, int> sorted_words;
std::unordered_map<sz::string, int> words;

Compilation Settings and Debugging

SZ_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 SZ_DEBUG before including the header. If not explicitly set, it will be inferred from the build type.

SZ_USE_X86_AVX512, SZ_USE_X86_AVX2, SZ_USE_ARM_NEON:

One can explicitly disable certain families of SIMD instructions for compatibility purposes. Default values are inferred at compile time.

SZ_DYNAMIC_DISPATCH:

By default, StringZilla is a header-only library. But if you are running on different generations of devices, it makes sense to pre-compile the library for all supported generations at once, and dispatch at runtime. This flag does just that and is used to produce the stringzilla.so shared library, as well as the Python bindings.

SZ_USE_MISALIGNED_LOADS:

By default, StringZilla avoids misaligned loads. If supported, it replaces many byte-level operations with word-level ones. Going from char-like types to uint64_t-like ones can significantly accelerate the serial (SWAR) backend. So consider enabling it if you are building for some embedded device.

SZ_AVOID_LIBC and SZ_OVERRIDE_LIBC:

When using the C header-only library one can disable the use of LibC. This may affect the type resolution system on obscure hardware platforms. Moreover, one may let stringzilla override the common symbols like the memcpy and memset with its own implementations. In that case you can use the LD_PRELOAD trick to prioritize it's symbols over the ones from the LibC and accelerate existing string-heavy applications without recompiling them.

SZ_AVOID_STL and SZ_SAFETY_OVER_COMPATIBILITY:

When using the C++ interface one can disable implicit conversions from std::string to sz::string and back. If not needed, the <string> and <string_view> headers will be excluded, reducing compilation time. Moreover, if STL compatibility is a low priority, one can make the API safer by disabling the overloads, which are subjectively error prone.

STRINGZILLA_BUILD_SHARED, STRINGZILLA_BUILD_TEST, STRINGZILLA_BUILD_BENCHMARK, STRINGZILLA_TARGET_ARCH 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.

Quick Start: Rust 🦀

StringZilla is available as a Rust crate, with documentation available on docs.rs/stringzilla. To use the latest crate release in your project, add the following to your Cargo.toml:

[dependencies]
stringzilla = ">=3"

Or if you want to use the latest pre-release version from the repository:

[dependencies]
stringzilla = { git = "https://github.com/ashvardanian/stringzilla", branch = "main-dev" }

Once installed, all of the functionality is available through the stringzilla namespace. Many interfaces will look familiar to the users of the memchr crate.

use stringzilla::sz;

// Identical to `memchr::memmem::find` and `memchr::memmem::rfind` functions
sz::find("Hello, world!", "world") // 7
sz::rfind("Hello, world!", "world") // 7

// Generalizations of `memchr::memrchr[123]`
sz::find_char_from("Hello, world!", "world") // 2
sz::rfind_char_from("Hello, world!", "world") // 11

Unlike memchr, the throughput of stringzilla is high in both normal and reverse-order searches. It also provides no constraints on the size of the character set, while memchr allows only 1, 2, or 3 characters. In addition to global functions, stringzilla provides a StringZilla extension trait:

use stringzilla::StringZilla;

let my_string: String = String::from("Hello, world!");
let my_str = my_string.as_str();
let my_cow_str = Cow::from(&my_string);

// Use the generic function with a String
assert_eq!(my_string.sz_find("world"), Some(7));
assert_eq!(my_string.sz_rfind("world"), Some(7));
assert_eq!(my_string.sz_find_char_from("world"), Some(2));
assert_eq!(my_string.sz_rfind_char_from("world"), Some(11));
assert_eq!(my_string.sz_find_char_not_from("world"), Some(0));
assert_eq!(my_string.sz_rfind_char_not_from("world"), Some(12));

// Same works for &str and Cow<'_, str>
assert_eq!(my_str.sz_find("world"), Some(7));
assert_eq!(my_cow_str.as_ref().sz_find("world"), Some(7));

The library also exposes Levenshtein and Hamming edit-distances for byte-arrays and UTF-8 strings, as well as Needleman-Wunch alignment scores.

use stringzilla::sz;

// Handling arbitrary byte arrays:
sz::edit_distance("Hello, world!", "Hello, world?"); // 1
sz::hamming_distance("Hello, world!", "Hello, world?"); // 1
sz::alignment_score("Hello, world!", "Hello, world?", sz::unary_substitution_costs(), -1); // -1

// Handling UTF-8 strings:
sz::hamming_distance_utf8("αβγδ", "αγγδ") // 1
sz::edit_distance_utf8("façade", "facade") // 1

Quick Start: Swift 🍏

StringZilla can be added as a dependency in the Swift Package Manager. In your Package.swift file, add the following:

dependencies: [
    .package(url: "https://github.com/ashvardanian/stringzilla")
]

The package currently covers only the most basic functionality, but is planned to be extended to cover the full C++ API.

var s = "Hello, world! Welcome to StringZilla. 👋"
s[s.findFirst(substring: "world")!...] // "world! Welcome to StringZilla. 👋")    
s[s.findLast(substring: "o")!...] // "o StringZilla. 👋")
s[s.findFirst(characterFrom: "aeiou")!...] // "ello, world! Welcome to StringZilla. 👋")
s[s.findLast(characterFrom: "aeiou")!...] // "a. 👋")
s[s.findFirst(characterNotFrom: "aeiou")!...] // "Hello, world! Welcome to StringZilla. 👋"
s.editDistance(from: "Hello, world!")! // 29

Algorithms & Design Decisions 📚

StringZilla aims to optimize some of the slowest string operations. Some popular operations, however, like equality comparisons and relative order checking, almost always complete on some of the very first bytes in either string. In such operations vectorization is almost useless, unless huge and very similar strings are considered. StringZilla implements those operations as well, but won't result in substantial speedups.

Exact Substring Search

Substring search algorithms are generally divided into: comparison-based, automaton-based, and bit-parallel. Different families are effective for different alphabet sizes and needle lengths. The more operations are needed per-character - the more effective SIMD would be. The longer the needle - the more effective the skip-tables are. StringZilla uses different exact substring search algorithms for different needle lengths and backends:

  • When no SIMD is available - SWAR (SIMD Within A Register) algorithms are used on 64-bit words.
  • Boyer-Moore-Horspool (BMH) algorithm with Raita heuristic variation for longer needles.
  • SIMD algorithms are randomized to look at different parts of the needle.

On very short needles, especially 1-4 characters long, brute force with SIMD is the fastest solution. On mid-length needles, bit-parallel algorithms are effective, as the character masks fit into 32-bit or 64-bit words. Either way, if the needle is under 64-bytes long, on haystack traversal we will still fetch every CPU cache line. So the only way to improve performance is to reduce the number of comparisons. The snippet below shows how StringZilla accomplishes that for needles of length two.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L1585-L1637

Going beyond that, to long needles, Boyer-Moore (BM) and its variants are often the best choice. It has two tables: the good-suffix shift and the bad-character shift. Common choice is to use the simplified BMH algorithm, which only uses the bad-character shift table, reducing the pre-processing time. We do the same for mid-length needles up to 256 bytes long. That way the stack-allocated shift table remains small.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1774-L1825

In the C++ Standards Library, the std::string::find function uses the BMH algorithm with Raita's heuristic. Before comparing the entire string, it matches the first, last, and the middle character. Very practical, but can be slow for repetitive characters. Both SWAR and SIMD backends of StringZilla have a cheap pre-processing step, where we locate unique characters. This makes the library a lot more practical when dealing with non-English corpora.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1398-L1431

All those, still, have $O(hn)$ worst case complexity. To guarantee $O(h)$ worst case time complexity, the Apostolico-Giancarlo (AG) algorithm adds an additional skip-table. Preprocessing phase is $O(n+sigma)$ in time and space. On traversal, performs from $(h/n)$ to $(3h/2)$ comparisons. It however, isn't practical on modern CPUs. A simpler idea, the Galil-rule might be a more relevant optimizations, if many matches must be found.

Other algorithms previously considered and deprecated:

  • Apostolico-Giancarlo algorithm for longer needles. Control-flow is too complex for efficient vectorization.
  • Shift-Or-based Bitap algorithm for short needles. Slower than SWAR.
  • Horspool-style bad-character check in SIMD backends. Effective only for very long needles, and very uneven character distributions between the needle and the haystack. Faster "character-in-set" check needed to generalize.

§ Reading materials. Exact String Matching Algorithms in Java. SIMD-friendly algorithms for substring searching.

Levenshtein Edit Distance

Levenshtein distance is the best known edit-distance for strings, that checks, how many insertions, deletions, and substitutions are needed to transform one string to another. It's extensively used in approximate string-matching, spell-checking, and bioinformatics.

The computational cost of the Levenshtein distance is $O(n * m)$, where $n$ and $m$ are the lengths of the string arguments. To compute that, the naive approach requires $O(n * m)$ space to store the "Levenshtein matrix", the bottom-right corner of which will contain the Levenshtein distance. The algorithm producing the matrix has been simultaneously studied/discovered by the Soviet mathematicians Vladimir Levenshtein in 1965, Taras Vintsyuk in 1968, and American computer scientists - Robert Wagner, David Sankoff, Michael J. Fischer in the following years. Several optimizations are known:

  1. Space Optimization: The matrix can be computed in $O(min(n,m))$ space, by only storing the last two rows of the matrix.
  2. Divide and Conquer: Hirschberg's algorithm can be applied to decompose the computation into subtasks.
  3. Automata: Levenshtein automata can be effective, if one of the strings doesn't change, and is a subject to many comparisons.
  4. Shift-Or: Bit-parallel algorithms transpose the matrix into a bit-matrix, and perform bitwise operations on it.

The last approach is quite powerful and performant, and is used by the great RapidFuzz library. It's less known, than the others, derived from the Baeza-Yates-Gonnet algorithm, extended to bounded edit-distance search by Manber and Wu in 1990s, and further extended by Gene Myers in 1999 and Heikki Hyyro between 2002 and 2004.

StringZilla introduces a different approach, extensively used in Unum's internal combinatorial optimization libraries. The approach doesn't change the number of trivial operations, but performs them in a different order, removing the data dependency, that occurs when computing the insertion costs. This results in much better vectorization for intra-core parallelism and potentially multi-core evaluation of a single request.

Next design goals:

  • Generalize fast traversals to rectangular matrices.
  • Port x86 AVX-512 solution to Arm NEON.

§ Reading materials. Faster Levenshtein Distances with a SIMD-friendly Traversal Order.

Needleman-Wunsch Alignment Score for Bioinformatics

The field of bioinformatics studies various representations of biological structures. The "primary" representations are generally strings over sparse alphabets:

  • DNA sequences, where the alphabet is {A, C, G, T}, ranging from ~100 characters for short reads to 3 billion for the human genome.
  • RNA sequences, where the alphabet is {A, C, G, U}, ranging from ~50 characters for tRNA to thousands for mRNA.
  • Proteins, where the alphabet is made of 22 amino acids, ranging from 2 characters for dipeptide to 35,000 for Titin, the longest protein.

The shorter the representation, the more often researchers may want to use custom substitution matrices. Meaning that the cost of a substitution between two characters may not be the same for all pairs.

StringZilla adapts the fairly efficient two-row Wagner-Fisher algorithm as a baseline serial implementation of the Needleman-Wunsch score. It supports arbitrary alphabets up to 256 characters, and can be used with either BLOSUM, PAM, or other substitution matrices. It also uses SIMD for hardware acceleration of the substitution lookups. This however, does not yet break the data-dependency for insertion costs, where 80% of the time is wasted. With that solved, the SIMD implementation will become 5x faster than the serial one.

Random Generation

Generating random strings from different alphabets is a very common operation. StringZilla accepts an arbitrary Pseudorandom Number Generator to produce noise, and an array of characters to sample from. Sampling is optimized to avoid integer division, a costly operation on modern CPUs. For that a 768-byte long lookup table is used to perform 2 lookups, 1 multiplication, 2 shifts, and 2 accumulations.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L2490-L2533

Sorting

For lexicographic sorting of strings, StringZilla uses a "hybrid-hybrid" approach with $O(n * log(n))$ and.

  1. Radix sort for first bytes exported into a continuous buffer for locality.
  2. IntroSort on partially ordered chunks to balance efficiency and worst-case performance.
    1. IntroSort begins with a QuickSort.
    2. If the recursion depth exceeds a certain threshold, it switches to a HeapSort.

Next design goals:

  • Generalize to arrays with over 4 billion entries.
  • Algorithmic improvements may yield another 3x performance gain.
  • SIMD-acceleration for the Radix slice.

Hashing

[!WARNING] Hash functions are not cryptographically safe and are currently under active development. They may change in future minor releases.

Choosing the right hashing algorithm for your application can be crucial from both performance and security standpoint. In StringZilla a 64-bit rolling hash function is reused for both string hashes and substring hashes, Rabin-style fingerprints. Rolling hashes take the same amount of time to compute hashes with different window sizes, and are fast to update. Those are not however perfect hashes, and collisions are frequent. StringZilla attempts to use SIMD, but the performance is not yet satisfactory. On Intel Sapphire Rapids, the following numbers can be expected for N-way parallel variants.

  • 4-way AVX2 throughput with 64-bit integer multiplication (no native support): 0.28 GB/s.
  • 4-way AVX2 throughput with 32-bit integer multiplication: 0.54 GB/s.
  • 4-way AVX-512DQ throughput with 64-bit integer multiplication: 0.46 GB/s.
  • 4-way AVX-512 throughput with 32-bit integer multiplication: 0.58 GB/s.
  • 8-way AVX-512 throughput with 32-bit integer multiplication: 0.11 GB/s.

Next design goals:

  • Try gear-hash and other rolling approaches.

Why not CRC32?

Cyclic Redundancy Check 32 is one of the most commonly used hash functions in Computer Science. It has in-hardware support on both x86 and Arm, for both 8-bit, 16-bit, 32-bit, and 64-bit words. The 0x1EDC6F41 polynomial is used in iSCSI, Btrfs, ext4, and the 0x04C11DB7 in SATA, Ethernet, Zlib, PNG. In case of Arm more than one polynomial is supported. It is, however, somewhat limiting for Big Data usecases, which often have to deal with more than 4 Billion strings, making collisions unavoidable. Moreover, the existing SIMD approaches are tricky, combining general purpose computations with specialized instructions, to utilize more silicon in every cycle.

§ Reading materials. Comprehensive derivation of approaches Faster computation for 4 KB buffers on x86 Comparing different lookup tables Great open-source implementations. By Peter Cawley By Stephan Brumme

Other Modern Alternatives

MurmurHash from 2008 by Austin Appleby is one of the best known non-cryptographic hashes. It has a very short implementation and is capable of producing 32-bit and 128-bit hashes. The CityHash from 2011 by Google and the xxHash improve on that, better leveraging the super-scalar nature of modern CPUs and producing 64-bit and 128-bit hashes.

Neither of those functions are cryptographic, unlike MD5, SHA, and BLAKE algorithms. Most of cryptographic hashes are based on the Merkle-Damgård construction, and aren't resistant to the length-extension attacks. Current state of the Art, might be the BLAKE3 algorithm. It's resistant to a broad range of attacks, can process 2 bytes per CPU cycle, and comes with a very optimized official implementation for C and Rust. It has the same 128-bit security level as the BLAKE2, and achieves its performance gains by reducing the number of mixing rounds, and processing data in 1 KiB chunks, which is great for longer strings, but may result in poor performance on short ones.

All mentioned libraries have undergone extensive testing and are considered production-ready. They can definitely accelerate your application, but so may the downstream mixer. For instance, when a hash-table is constructed, the hashes are further shrunk to address table buckets. If the mixer looses entropy, the performance gains from the hash function may be lost. An example would be power-of-two modulo, which is a common mixer, but is known to be weak. One alternative would be the fastrange by Daniel Lemire. Another one is the Fibonacci hash trick using the Golden Ratio, also used in StringZilla.

Unicode, UTF-8, and Wide Characters

Most StringZilla operations are byte-level, so they work well with ASCII and UTF8 content out of the box. In some cases, like edit-distance computation, the result of byte-level evaluation and character-level evaluation may differ. So StringZilla provides following functions to work with Unicode:

  • sz_edit_distance_utf8 - computes the Levenshtein distance between two UTF-8 strings.
  • sz_hamming_distance_utf8 - computes the Hamming distance between two UTF-8 strings.

Java, JavaScript, Python 2, C#, and Objective-C, however, use wide characters (wchar) - two byte long codes, instead of the more reasonable fixed-length UTF32 or variable-length UTF8. This leads to all kinds of offset-counting issues when facing four-byte long Unicode characters. So consider transcoding with simdutf, if you are coming from such environments.

Contributing 👾

Please check out the contributing guide for more details on how to setup the development environment and contribute to this project. If you like this project, you may also enjoy USearch, UCall, UForm, and SimSIMD. 🤗

If you like strings and value efficiency, you may also enjoy the following projects:

  • simdutf - transcoding UTF8, UTF16, and UTF32 LE and BE.
  • hyperscan - regular expressions with SIMD acceleration.
  • pyahocorasick - Aho-Corasick algorithm in Python.
  • rapidfuzz - fast string matching in C++ and Python.

License 📜

Feel free to use the project under Apache 2.0 or the Three-clause BSD license at your preference.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

stringzilla-3.8.4-cp312-cp312-win_arm64.whl (64.1 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.8.4-cp312-cp312-win_amd64.whl (74.2 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.8.4-cp312-cp312-win32.whl (63.5 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.8.4-cp312-cp312-musllinux_1_2_x86_64.whl (254.4 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp312-cp312-musllinux_1_2_s390x.whl (180.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp312-cp312-musllinux_1_2_ppc64le.whl (215.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp312-cp312-musllinux_1_2_i686.whl (196.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp312-cp312-musllinux_1_2_aarch64.whl (205.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.7 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (219.6 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.3 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.6 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp312-cp312-macosx_11_0_arm64.whl (73.6 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.8.4-cp312-cp312-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.8.4-cp312-cp312-macosx_10_9_universal2.whl (112.5 kB view details)

Uploaded CPython 3.12 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.8.4-cp311-cp311-win_arm64.whl (64.2 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.8.4-cp311-cp311-win_amd64.whl (74.1 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.8.4-cp311-cp311-win32.whl (63.4 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.8.4-cp311-cp311-musllinux_1_2_x86_64.whl (254.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp311-cp311-musllinux_1_2_s390x.whl (180.5 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp311-cp311-musllinux_1_2_ppc64le.whl (216.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp311-cp311-musllinux_1_2_i686.whl (196.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp311-cp311-musllinux_1_2_aarch64.whl (206.0 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.5 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.6 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.1 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.5 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp311-cp311-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.8.4-cp311-cp311-macosx_10_9_universal2.whl (112.3 kB view details)

Uploaded CPython 3.11 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.8.4-cp310-cp310-win_arm64.whl (62.9 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.8.4-cp310-cp310-win_amd64.whl (72.4 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.8.4-cp310-cp310-win32.whl (63.4 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.8.4-cp310-cp310-musllinux_1_2_x86_64.whl (252.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp310-cp310-musllinux_1_2_s390x.whl (177.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp310-cp310-musllinux_1_2_ppc64le.whl (213.8 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp310-cp310-musllinux_1_2_i686.whl (194.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp310-cp310-musllinux_1_2_aarch64.whl (203.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.5 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.4 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (217.5 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.5 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.3 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp310-cp310-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.8.4-cp310-cp310-macosx_10_9_universal2.whl (112.3 kB view details)

Uploaded CPython 3.10 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.8.4-cp39-cp39-win_arm64.whl (64.2 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.8.4-cp39-cp39-win_amd64.whl (74.2 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.8.4-cp39-cp39-win32.whl (63.5 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.8.4-cp39-cp39-musllinux_1_2_x86_64.whl (250.9 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp39-cp39-musllinux_1_2_s390x.whl (177.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp39-cp39-musllinux_1_2_ppc64le.whl (212.4 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp39-cp39-musllinux_1_2_i686.whl (193.0 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp39-cp39-musllinux_1_2_aarch64.whl (202.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.4 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.2 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.0 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.3 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.0 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp39-cp39-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.8.4-cp39-cp39-macosx_10_9_universal2.whl (112.3 kB view details)

Uploaded CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.8.4-cp38-cp38-win_amd64.whl (72.6 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.8.4-cp38-cp38-win32.whl (63.5 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.8.4-cp38-cp38-musllinux_1_2_x86_64.whl (250.1 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp38-cp38-musllinux_1_2_s390x.whl (176.1 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp38-cp38-musllinux_1_2_ppc64le.whl (211.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp38-cp38-musllinux_1_2_i686.whl (192.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp38-cp38-musllinux_1_2_aarch64.whl (201.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.7 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.2 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.2 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp38-cp38-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.8.4-cp38-cp38-macosx_10_9_universal2.whl (112.3 kB view details)

Uploaded CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.8.4-cp37-cp37m-win_amd64.whl (72.5 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.8.4-cp37-cp37m-win32.whl (63.5 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_x86_64.whl (248.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_s390x.whl (174.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_ppc64le.whl (209.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_i686.whl (190.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_aarch64.whl (199.2 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.2 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.5 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.2 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.9 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.2 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.8.4-cp36-cp36m-win_amd64.whl (72.4 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.8.4-cp36-cp36m-win32.whl (63.4 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_x86_64.whl (247.7 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ x86-64

stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_s390x.whl (173.7 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_ppc64le.whl (209.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_i686.whl (190.2 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_aarch64.whl (198.6 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.4 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.5 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (212.8 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.0 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.6 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl (73.1 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

Details for the file stringzilla-3.8.4-cp312-cp312-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 2c033f3d74b32193a774159f5ae42c6f2cafffce422fd729e31234d6153d48b2
MD5 d0e9a00ccfac512dfccfc37665f37b19
BLAKE2b-256 246bb740cf3d1254693bbd71954f48ba330a3c3e051713e876ba0a130c4ce25d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 af1eac34543957b5afae983d302b02bb6700b2b0317ba1224b211ae7b97543d9
MD5 a0aeb198f7d1a1a3617ed31fc853b4ad
BLAKE2b-256 fb893b15a5df94399a8d2b6b7c2036d9934f7d119bd2aabf4824703f4ee88675

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp312-cp312-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 e5cfc096232758086fb63088e10266836b2e3e0d20fdb85f52ce406838425b1b
MD5 b592d5da260af62125dfe97c1d062bef
BLAKE2b-256 a665a6b301eb8e2ce4f8e5b357b4384fb2a92eeb8712f1a69e9b2a557ad41a02

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 bd167b7f6a2af68597c0f988232cff69cb94f65976a53e7dd148354d34a5fc4f
MD5 1310105baf08ec98fb1e3f1898c6408b
BLAKE2b-256 ee7dd0f696c97337985e6087bf8393670dd9af69fc1c5d42a982dfb2aa1aad08

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 b74d89c2dce3aed70aeef7a063d84bdc48202f1fae8c3b72c6e96c532463be3a
MD5 41e06a650ca6ba4120352ca9208d4e86
BLAKE2b-256 9715a0199e31e31cc7c4c8699fbde6e84ffd82db3c20377cdfd3fa833ea0f2da

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 d4b260238c66aedd2e52dcb2f9e962fa806d712d8674b60af68237f1972fc213
MD5 99ae41f469b244427c4fbef3158c2b3f
BLAKE2b-256 7b10af6d9cf5ca5282ef5bab3c46b1ccb4fa9279b56430806de966dbe8199be0

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3934a3d3327df8818e9b41c9398e542b79eb75ddaf98f773a639d6e6b23ae583
MD5 2a1983a39edaae592083a6c4020904aa
BLAKE2b-256 df5fe7797531742d4b570b5d3b0542c3f1ca7d84fb97c9c588aabd41c135f93f

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4b2dd5f58b0e22f3db2a48245687220aacd119835256c461a3e5575ebedadaf1
MD5 f3c1f606c205491f2a542b6d7a9d26a5
BLAKE2b-256 032ce68366fbb56d26e1d629351e01c288f658b5aedf9b742779b866b57ca1f3

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cb1845fe0841754a5bb5969a166d838aef0750f046cd0ab9ae08c2f3a5b5131d
MD5 ea4562d5f05080dbccac68fefe4f6135
BLAKE2b-256 bbeb056fdb5b5984ff3de00d2b50a0546403d71ef884eb2337776e8e34ff506c

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 00a0909966c298961c2ceecd68b5fa7a04617b3e393fa37d9356e31035edfdc8
MD5 2817288446a15e7686319696ebaa5943
BLAKE2b-256 a7cc6082210e6390f84dc62e42242a86025a46b6ba44c2f14706ecc2e9b37bfe

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c7df8582cb567164bd4836c267abdeebe2e852e8d0e2578b6253f1396559d939
MD5 0642ab8112a30f8205989395169c24de
BLAKE2b-256 12c5e33c384422354ed627699171ca11194ef1fdccc4a77ee9222c796595e335

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c09ee9864622469aa85b6d6563958c85e9a53952512ef44480af4e223ffc35cc
MD5 1c4f69b0d6fb24dc48673b18c8f6f62f
BLAKE2b-256 379d0a168c6604827ccc494575b2175f83b80b093df4c05904fc39632ae3d585

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 36ba12d5e1f36ce9a7439761aec054abf79ba3f9ef9e6cb94fc0c01445de9818
MD5 8ea74dccaabda5c46c74a1f741e49fc9
BLAKE2b-256 57b71a864092300bd15d44ffa4c6767f3dfe1b5c6883552d157ffe50b957cddc

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 92dfc1a64ec53370c1041176895ce24fb8ec6b066b3cfb06ab5c159e996216d0
MD5 f7c569528f6e69f0b510c24595b296d2
BLAKE2b-256 ad63286ae28901c416814533cc9355ce36dc9c4dc1c88683e4fd7e52720b1466

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 955c01345ee98bfeac2dff8d51b2b0afae35b32cf69797f288e52f7986fb997b
MD5 f0f0b37e84cc0fdc0a02bf93571af06e
BLAKE2b-256 bdf435fa59b11546de46236d97e4da085cf49820d3018a702de4abb72f4f317d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp312-cp312-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 fc68738b1f6177ff1e0618b970c4871b87f00e96c70c50ef1057a1755e01c2cd
MD5 a8ddf4da7ddb536613dc19c71186d7c7
BLAKE2b-256 59438aa7d66b150fb6913077bea0a842bbaa98d59bff8407d5cb0db55a065b2f

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 cd9e6247983d092a45f5a07e049dff5aac61190c37fbf0ed6da31fd529a845f5
MD5 c93dd7104e73a2b15c4cf317dd764ebd
BLAKE2b-256 d3b2b6f16b7dcb6e6c53cabbbc22284c40045443fd1cc3fab3c44d1f885a3a30

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 7ead113fd1b446ba1c8780a13f797df5e396f32eb205ae93f380319220f02a02
MD5 a306e1bc0cbdbd60570d7db5183921a1
BLAKE2b-256 bf43a5a7c84b2de5ab2794824cf1e73442e2eb464eaa34af28468b97b8cccfa7

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp311-cp311-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 fe9d52736e609404c690e489159556cc23533180265c7d2f3d8695fb6537dbe1
MD5 46deeda7b6b263043fd07d8378dcf36a
BLAKE2b-256 463808292b30f6989e10e6f2a3877c1933fa041a100ea765c3434f2099a3182e

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 80264ceae5413561a044dc06ac9cb4cee4c12f803d9fbba43944984a160e93e2
MD5 0b416baddcc664257b50f288c8d76bc0
BLAKE2b-256 d98c9b5b996f80b584d931a99f897db72e2ffcc9771283a8951f9e8bb2ef2891

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 17555659bc2bc7a2334b9d01064e9e8c696e19126ead74e326b91b8b24ca29a3
MD5 00201f885e9c06e3194dcdd657400bcf
BLAKE2b-256 77e97a6aa38ea4adfe310a070743fa9533eceb80879421f268608dddf405e9d1

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 a8d551fd9cf3fbb2f28f4ea47e0c48ec4abb376550104a9198d6bf49b7b6e081
MD5 6a53c5a63549cd13c4b08406625a00cd
BLAKE2b-256 e1bc46aabf3b90cf0ff9b5d4fbd2831dcb02167c2c0173486dd63a9a43bcd9eb

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3aa25cd8274bf1be42086d03b8388a359104b5e312fa741bb783ecfdbcf1deb4
MD5 962da391815d907a35b258bd9c53c80b
BLAKE2b-256 2cb17ad2db4070afe42c89b5eab3c36e415c4d2415b275e065bcdda57706da52

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5662c93ac208ce93a1a0a359979eba9641fa39ea4e3f4268c1afe9f77ae95ab4
MD5 d496fdabc4a76c31f64b411b8b4f765f
BLAKE2b-256 ceb15bc3c406281ebe0c5a27a7e7ae04285e84ac72b2a61a191fa9a341faa250

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ae518d49c24b0ec3400c7cb99b30dd22df320a47b73b13b454ae56547aa83381
MD5 0e6e06fc190ebfd63785eba3a396c501
BLAKE2b-256 2f6feb0c58946c25f7a600ba83cff0ca5c5e30bedd17daf55f48618bdc682a5d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 bd239f0583d769d3b8a50b4a4fd34e9aee034ca3e3ba15fa70149aa752cfb9fb
MD5 4379ba2592f756617b83aa70e1e6af9d
BLAKE2b-256 f9ba5029a033ccbcc534152b68859f6643168d30037e8161ea1215caa6916914

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 2903cf95ebd681d7010bfb58386f6dc0d1e178f3e15bb3f9fcdf4124d4f7f4b2
MD5 3709316a714921eb065292f72dff0f02
BLAKE2b-256 b7b7700aafb33cd81d0dc8ccf53b57989c014344fef6a946f291a9c69e9d82fd

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f5b4de47f73c82535bdb9344749fec0d865bbf735c698c76ea4970822468faf5
MD5 d34faf30cb184f35b726d9a89f0047b2
BLAKE2b-256 a304b755fb69cd5cfe2b43942c1a4f762da53489c5c888afdb17b414b15dda54

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 47e25c61fde5cca68df87bb1f2fc1d7eea5a08cdc6b2e943fe49991a42333b48
MD5 c990b9321b1e3e15e5f38be03c65e0d1
BLAKE2b-256 7cec0706ce06be63f555ac6cdf5efcc204809c25b9afd1516b8f5dc63579ae27

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7fd7aa492c6a0c340f4b3a545ea137566a60f67f76d684c7cad549feeb910df3
MD5 0bdd49447f7041b7949a17838f3cf0ee
BLAKE2b-256 ccf885c1f85df1fe16b19d32605450facb5868a48f4745fd0f2dbe8f65c39049

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 420272d93de123d6633d0bc920eecf65e8afbb82071aa7c2b73e9c0947897952
MD5 9fb05d62171a3f2f472e1969c5372f58
BLAKE2b-256 7ad27a8cf1f6896d07d8a9e6e5cda61bd21c979ebb89778ce57518a17c88dd4c

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 bd2a99cb4cd9b9bcfd91bb5311884a5560546e6bb6ab5d09e3d2b550a6d81878
MD5 4481b8fb960dd98d12c1ae7389838387
BLAKE2b-256 6e31db785eca26e96651becf91654b547e3e4a6c58f386a787609f4adc77497e

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 f4801c1847c356eb4f5087a95bf0d6ac48266827aea34202f93b9e9943b4f691
MD5 c07248d1a1a200efb2e88b5f55894ef6
BLAKE2b-256 7b5216932e16f81beadd8439eccf349c1eb50e490526469a60f77ca9e6368962

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 3b45fd5b51daeeca74c5b811e4bfce408c49718430a70d4400cb88e083fa8381
MD5 6cb902e82c1716ac3ee444358189a936
BLAKE2b-256 79883f9d33c759bb4691669bb440e5c04672691896f012144f942dfbbd9d6267

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp310-cp310-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 d2acc7c7c71394edd5d4fc32252c213cb42a10f37c7169edf6562f6491ad7ff8
MD5 b2e38a61128d07688b4951273f2936fc
BLAKE2b-256 9d122722e9397a8012ab6263acc8877c8873ff12a112b22f721c7c84d64d7fa4

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 750320f900e6755c2f29bc4a34d32fa0f5498438e92bc0d5097f9b88dd1b8fa6
MD5 47bc1280ead7af32353925af6a3cd43a
BLAKE2b-256 f6530bc5dba54a04ca6d271a3d1af1b2a9dadd4647b582a9d2c6b1ba814bf354

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 0d367565948f6c47c711560a27f95e19945989f0524af1c183eb65a7740a3096
MD5 d720a730058b171af9065ae8d85fb99e
BLAKE2b-256 1c408ac1934c52a6d125bc50270e79a299469f2ee35358b43b8003c60e07e9a9

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 5f03d5d7ae252cee460c267ece2e6aca5576545b1871d82a78c9f6be5acc2342
MD5 c57f968eef60afb40d89cc99c6852824
BLAKE2b-256 a241eaa93a6899c46e2aa228d88b10e5f207eac3d0d068ece4ccdb085adee973

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 df6cf50033108391c5bf93a54b463d1dfcfdb3185131bb03efa3dc05dd2ebaae
MD5 aa0d5de40f74117cb02fc45fd0d4fee0
BLAKE2b-256 0939691174b5b85b6e12a2c0148e20dc560b570200a139b41b90e3fa451284c0

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 09791fd3757418336c83a5293a10e75a90b1191fd56d4cce194831e4b940d504
MD5 3438f94419e1060c2b03f78855e3e540
BLAKE2b-256 f3a676d593557b20fd867c9fcfb09d7b5accc0846811d740eed23c5958e97846

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9d6855dd10c554f798415df3d277729ae83962d81569f2c34895a60807ee8e81
MD5 3cce6a92e2319a93556c5c7a91f6a3e2
BLAKE2b-256 512d995155ac2de1dafaa85a37da870620b6e14bcb7082b5807326ba2be6076a

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 4a89ba1b863be9dd068ca6a8019b69a9b03fb1c56043402cb7ed5fe3be033242
MD5 fd8859a53b3df8484fba0ea11955d8ec
BLAKE2b-256 ea789845553d216e65d2f76a71df8016ff9dae69fee7b63ca6fd9871faa86f49

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 bf544d5f5cdb2f28a8fe85f461a635263003d41ea81f7f1a4cc53cdf0f9567b3
MD5 d5d4ec37676bc0240bf57a1796422938
BLAKE2b-256 5342db4c122f71e42782564ab5a86823f5f69406bdef822a43d3252c57c97d3a

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7359a514871df41ef79e513678bcba30ba6390b28188c914ab80ca07fe84a2e2
MD5 196aa9b5647687c15d8cd58b9a42669f
BLAKE2b-256 9910f876c41c3c58b0943da462fb6ada2e2d741fcfad2d242305de15217a7fec

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 578d28a7552f8d5ba67c781a01de925c17c23dee12a95ef90da6d0a1f2595cf4
MD5 b60290eb0a4e19e6263411fba90b9476
BLAKE2b-256 ec267d0abf680589e754f9c510ffa3ce5eab577df424423b1b0f6da4abe099ae

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 27c16084f3c20997d0a4357a2215a34bf5c58e91d19c04766829334b656d9151
MD5 8237a4147865c1f92e88a3a50b4327e3
BLAKE2b-256 6370957625746bcd22bf808bd85d9e0c1a489e33deeb0aaa1656aec83ac5ae31

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e24ef6125d2c61dbfed7ac3ff156cfe5126335eef053167f48c3c18f315226aa
MD5 c753e23b8557243df17488a614da5746
BLAKE2b-256 d298e2170281e5096997bc0f8ca143cf5527877dfa200bb2de95ba717a763444

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 f3bd666063a1417822c7b67e2b5167d94c2363a5b3652c49a9edf4b4a1612c22
MD5 9e1d09a8779cdb0fe2ba871859e8781e
BLAKE2b-256 7a5df8d0230edcfadfd855e0c687cdea614c04e9a4a43fd288a4c2a70423cd77

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 265fbea2c28f6c4f0246978f19faf7053e0f60d786f64bfd2854b2db78c3f429
MD5 2205fd70c43da08d880206fbbf43aafa
BLAKE2b-256 127bbf3e00571b00a86554b31cc549c01efbea6b85960ccfc9e7b38e3513cf97

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 fd48113734e40c071e18f0dfa73508f4c3ad59f83c9f753c2e07119271ca2623
MD5 c8e0e8788f5207d8a9df31b4282720c4
BLAKE2b-256 fb423d125aacde0b44158416992e5ca2bbc5364cc0eec1d1e4adee3ac4d320ef

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp39-cp39-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 3a91eda1c16a31d97a2b94f0bf10446f5e71050a3fcd557f3978f8771708c9fb
MD5 b04b6b3c79efb736a9d7002c54c78bbf
BLAKE2b-256 d52ebcf2e84dedd0ea54cd72b49f5b6fac0e06fd0fad1483c588ed280ea9c02e

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 62031223bc03254284fe8b8b8dfcdce6f53b4c2f03151a2dcc6ee93f1b13da90
MD5 0ef872b638036dad0626944e367cf95f
BLAKE2b-256 159291c119467ca5115eeb2d51ed55b723ec88cd589e8b2fcf74b1134fc1c619

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 fbea73089546a3c5f618f76e90a1d23b1d2acb079a195db3be496c2a312bd26d
MD5 4f3ee74ba62eb3eacfd106bcaccea110
BLAKE2b-256 f33d465ae1571fcda10c4c230a5269ec549e6cf625848cf3976e52550e2a0cf2

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 5ddb135b132d36084382753d51de0a485422c7564e19714fe6ef27773c500322
MD5 10345babd147c9285bcf841064022187
BLAKE2b-256 bdda193689651ff10af821f9b93368007dbff8530d6c74b10473d0eb18648bfb

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 afed8d4698cd556f52ca1432bc71d8931f7d37e2c5abbffcc854ace6607512df
MD5 cbe9e39a7f4844442360b2042d7a8cc1
BLAKE2b-256 d8bfa23ffb4ef307b291bd3347ec67b4828b50388929d62aa658234f797bef0a

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 69a1b607259c8b30567bccb073735b2e317389466ddd65467c5028f8dcdd1b2d
MD5 bac6b8fca48fd00186bf10c9a21f0348
BLAKE2b-256 51faaa47de559a3ddab8c4d921326ecc0ab4e8272df942000884fe1627470b88

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4f38a61b20788c69698d4a23a2977a77edd81d9e6f428af324f2b1674ea59ba5
MD5 e6e41060d6accdf38f2e132ee2360cad
BLAKE2b-256 65d21c8727da0c933ebdbacbf22c82160e783c673f1941f53ebd754598917b76

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e137bb5f62e34473f7da805b033e435a4a3c8eb82f60621fff3c793e7a61298a
MD5 025cecba217922587f3e4e5c6360e433
BLAKE2b-256 fc0c6f0e006056152a94eed837f6047024c7da10a2e9d316305a937d06507ebd

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 fe9f04c6b8ccb628c4602510032d774e0184dcccc5953c1cdec4e06d8ab7e9d7
MD5 1681eaa14b0ded7801e8d86a6a36851d
BLAKE2b-256 41706ec81436654719529c2fd44cb51d8bab6cf4571825a4f519e1c36a6b00c9

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0dc474ca794385c91bb143e7d40091ae3763e022043045e45440609ad18f6602
MD5 57a18a7a619d0cf33411b9d4a626b576
BLAKE2b-256 ffcc8e361f789be42dd348955fdef3dc8f90653795ed4af68dfdd0154a538917

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e114d5310c2f592bcd7fc0f4538ab252da15fad5686831cdef4ad9bbe34b634d
MD5 fdb540b556b2ccd89b99d9572c29bd79
BLAKE2b-256 f3c571e3e59f02e7bf9f85bba39363df51a74219ee24bf4f2d9a6a14663bf691

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3ae603283924861690549b22fa95d4847d6dab9a7f46ecfe027acb50de25895f
MD5 4a783cbb4017b90b556e4acbe34beb93
BLAKE2b-256 fe042b1e3e5945b8d3a0792fbf9a8cba64eee6ee813648a9fd7f365b8edfa71d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 da6c69c3857cc69cbb85e9749c4285270cee90fc46a2140182166aee723fe705
MD5 93f32ab39ab9249be78e3e58d3305565
BLAKE2b-256 cbe41d463ba0798e7f8ead2118c9f7b7328fd322e3bc5eb7a16c0892fd57508e

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 8f2aa9014cd0f3580ceaa265c38029d87997c7be030dbff8f34de5afc21e2885
MD5 d76c8ae3bf7003040fd502e24362b4f1
BLAKE2b-256 5bf68af6e48987ed3a1657e7c947ed46ad62f2ce98bf0a868a08f5431ce11650

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a0c072faac344f118ae95c6876ead2c5c6fcaa2fd1054e1b173007fc6da35930
MD5 eda181f2c087e74c6ad62d3d84b17aea
BLAKE2b-256 ece817d300366eb2556c5704424415ac513225e0d663be2dfde1736669c68979

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp38-cp38-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 8adb3cf998c10e9718b2f11dcc7e251685038c406166add1f72d51fc9c8a8e4c
MD5 674b31c50dd98143887292e3021c9e38
BLAKE2b-256 3afb56d1795b204499fa923e686ab96bf69cbdf05b8a8b6373713fbc2c6d8db4

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 04917a08e980d51679388f8bb98544471ae4e2ecc54bdc7f0877a6c79637b92c
MD5 a8fe24809abdc9672ae7238a6c251521
BLAKE2b-256 4235cd53a5eb6b23126e6d99ab013191806705e2ffb9844d78edb6c5e5359152

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d3ec288d8a8b4567459270edc3f94118cb77b725a7e689936e9fb639e4f07d0b
MD5 99912cc5cf763efa55c8e4fc70bf0d27
BLAKE2b-256 f7a59e6721a6cf6f95e3e60d859199536715bb3501e5f1fbf4169f7c903718c4

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 c875d36d96ceb6f3202e1f27df844c7b081af6ae7b0a38099e5b30c32aded82c
MD5 5284267049b284b20fca96200bf972a2
BLAKE2b-256 1ef4ac856601d929f0a2cc84bd94d54f8cf7431ae578480fca373ff7c4e096a3

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 6cee3815395aee8dcfe90a9902473709db3be0d6aa3c7cbc221ec6b512960af4
MD5 5ad659be10d246ea2494234c20ebbcfe
BLAKE2b-256 2d577f681b09cf72b6397af1160b0de1bc6f24c277ffa28a4964e6da2e7db883

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 abf8e0361074bdf686ece702dc8ee4b96e77ec16cdac525fc371915be1393858
MD5 89e49c0e94b1d6699f5c2aad8947c57a
BLAKE2b-256 5ea95bfd5dfbe765341f60e2586b5fd531c16c301c5f3cdb7c94b9b2ab1d4409

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 522b7e0e5e687849d3c17db478166297e4ad58e4442235cc589c28344e9f759a
MD5 f4047e65e2eef145ffd02314382b1908
BLAKE2b-256 131bb7f47636711e0d3db08cc84f63c952e0a1b0cb3b5c96b84750e7192e8d09

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 628b9a3c51ef0f636b4154b010d6e7499f23f1313d5b1e5957a87496a5fe252e
MD5 ea25a1bd4d073cdff5217d5370921b32
BLAKE2b-256 f2f75d5faad29c49bebe72cbc1f6a89fd8157a701f82ecbf939259710ee647e6

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 5c10bf85abffc012c825adb388cc07ea83d6d8f240f10034ea8b382e9e99f15b
MD5 fd11f5ad82e6fbea1d35e9d2dc21edbd
BLAKE2b-256 5e13a9e422fbe1acca1ac20e9168056e533fe7b63c0745fef3188aa23cbb1005

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fac443cd5256a0b11ea5433e0ec1fc3baaf8c6ddef3c295f408eb236df79350b
MD5 99a325342e23878e8f558f4f77cb51dd
BLAKE2b-256 2f29b3617ebdfa2b9158fb3f0c2c08d68b3765dc178f2d243a37b8da67330fb7

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 2f7d79b78d45edde8ad288e8520cb5ec28e751e4346278dbb4bb37dba1f019cf
MD5 fdd5b29b5e221d6e5918655a0d61a659
BLAKE2b-256 be9446fb38a87ce81a320f144aaf6bb0785ccee108320a868ed2414100ed366d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 05a2c27cdab7c06dd881a08ec0f27855ff2b2a68ec45ad972b1cd97ba007d389
MD5 474c0f716623bd67d0ec884df49811c0
BLAKE2b-256 33b9a8a723bae73571764a172bba71b809f2af0b98c251dd05bae17c52585fb4

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8181c964aa05490a3d3a68902c739d511e2714cff51678b720277e676de8d782
MD5 dbd491f87299e7568152f8a3819b0607
BLAKE2b-256 dbc11fd47a3fb3c4b3816517a750007e635f247d3525eebcd9fb9ac5ac91bf9d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp38-cp38-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 be4d203f985464b1df57aff3037ff804b66937ce85d746b6e9c46ad813a06522
MD5 a1f43134da33c9ba56ab4e127d0ee24c
BLAKE2b-256 2328d3535307061e97de9ea4ffdee5c456e1b09a7f357a142a900cbc0734f456

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 eb603eeb097b6974959989cbf85b4f563b66bb0572e330e25c2c1610d904bef4
MD5 34bad3a73ab040be26d46d7909e49f27
BLAKE2b-256 04a14cbd1b754a65503200abd6786ff6a125b20076a2f5895af40bd010ca2ae8

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 c18aee0f951d6a448e9bca0036c3f84757f59c1c5254318df65fd8f2ca59d47f
MD5 3d59a8620bf19bb1671465810279fd4b
BLAKE2b-256 e49856f4e3a2f8c226d817f8c25c3ecf9f4af007b6abf2499bbe58b2acbc411c

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8af15f6c03296fbce97680a962da9b69f95c144b8ca1694cdb5edfad70088b2d
MD5 2f57b421f026051accfc091ccf0a1e2c
BLAKE2b-256 07c45a47e6c1fd95f511ed9aab3644862b94d25d298757b23942ab8dd89e062b

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 28060d6944817a040015541c21843e7488f14d9320a81a683c62c7e5797c7c68
MD5 6acd12b299fe04cc842cc0196de5719e
BLAKE2b-256 5b1be546393c228085380c55e518f9ed4a2405fc31b8573769d1b305d6622c55

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 ea67852d8e10ebb45c0c8b3018c657fb47c9f7898cf6ea9b4e6e2377ae3343c4
MD5 e0d950a7109dae4f11b4e28af820665e
BLAKE2b-256 99b1f4c031225e0ac06e1c653687467bb346cfd1f1c51dbd8a1554213aea6f85

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a81ece28db65ed2f6f886471fa23623267ce19df74062dc3f2ce9044ee2d851d
MD5 12cbab9458031a2f289c6fae89d3e8ce
BLAKE2b-256 c15d9f8560a8f84f8f2b8f61011b6505c9c2de27eb8bb9f4e724b6aa2a1b703b

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 007352f429707b6f737cccca40876aa81fb82358be3c1f401c7d99dcf2fc07f4
MD5 b738a7d647175935397ecdd786ff8395
BLAKE2b-256 322cab6a0c935bf32cf38814ffc02d4ba906f18f23e8e992c34a9b41d1731096

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 49cd0d9247d215eb71afe130761a80fc4c226a02b43701f06e1fe9782acca0e4
MD5 65a1c5c68a63d69362161c87dd6365ce
BLAKE2b-256 178cb421bf68adb58c909542d01e0a39c8b6c60f08f1fa24e0d296da1a1f4a53

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 415ad83a66f86afd36f26fade42543cc68532b2527f7f3ffbdf3d31964dba9a7
MD5 de651e70f9c0d79e734fcc41ac3ce4ac
BLAKE2b-256 b1e22426ee1fd342ebff848f5573b1738da3cb0bfe73b7a23590f175688a7361

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 8b01444a0a2e616b37a98ec636b89bf1e77d6d8e59f1582cd9b735fe1d178239
MD5 9f5063e2e330a2f784acd76b038b617f
BLAKE2b-256 17037ce96058a500fb9d96d9d6d64bb91f8182e056ba2c668f82607ac552f3a8

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 eaeba05b216d12a8c482cfd444d8932a7af9fe257100360e9ada2414ee41b338
MD5 60121b8cebef009a32106ed8c2008825
BLAKE2b-256 0fcdcc50b00d8d4ec1e3c5031dca4f38409f6d96e4b69c2262e6c4ba902554c0

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f43bcc9c18e637bb2aeeca5196af97360db65526b50f1fdfb3639b7a3d73161f
MD5 3498f8effda731ec17da37575db5016d
BLAKE2b-256 8ae59dbcee75569eb3a64a25d689434ee5d698bdfea66d1af626be0fb3e1fcd9

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 bb6070c412935a8f7a958a40081db5ff453619a4490cd65923af1e16d41418f5
MD5 54206fb047cc2e5d168373a6bf984e02
BLAKE2b-256 27bc6628728e9dea2eba52319d93fa27ad63b27ab6176c835b4e717901f0e080

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 7ea0b75026949736685bbdce8cc9e37c614b7f920b3cf8fc0471cd3b05eb8132
MD5 ad3c5108718d77d4cede20f80dc5fdd1
BLAKE2b-256 810d450e4ed798d8d290de97572eca9e96b98b86f0d813d0caa96a1cc21957fd

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-win32.whl.

File metadata

  • Download URL: stringzilla-3.8.4-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 0579608548ec67f1af92da44d0d337c2765912da12a6087c8eb44268ca0484c4
MD5 b0be1e83b4a88fcfc0d16ea3ae91691c
BLAKE2b-256 013ad1303ada0bf5c5d04ba32d507d3fdbdfdf240dff847721e2ced796d9850c

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a715d24d60dae78f353715014f292bdd2c334cdba49efeadc0bc3c0819bd9959
MD5 14d7168c017e09bfb567b19a7daaf10e
BLAKE2b-256 719f4ec4abdc21064a60412110aad77c161673da0abf08aedacab3ce79dcde85

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 02964b44e6c249eded8be88260f8778b995e055160ad56222d465980ff717ac4
MD5 3ce478dd7c646bfce1efda42442a8c21
BLAKE2b-256 35235af9b6fddb76de23ad4d6a6ce3948015170c2b603ae66b331432134cdafd

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 0651c45222683c17383ba856d5a2f413fd87e18b5d673dab6a2ac2441b634466
MD5 329fade4fdd147421de02ea87edc04a8
BLAKE2b-256 b24148a2b3240b7eddf2cbd5794125b9eedf9e12981d7d2c97576f1d79921995

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 80b939bc5d8531d464ff09567d1e2b1454c70ad929c6ed4a98673d0a77317f18
MD5 d06e139373d30c906a4267a838ebbea3
BLAKE2b-256 51a49c47d1f08b86be062dbd4e615ea2e645dce7c9cbabede865c91637ab4170

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 05a953c7c040bd4a4182cf18c9e0738e3cc3e84aaac7725a148b3f08894b44de
MD5 c85d62ebc52e34ec9961d73f1b972980
BLAKE2b-256 388a48ed645c160cb3d4f68737e8aeb92a17f2deb1c75cfab4ef2c1e859a55f2

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1f2de3f313fd329e7bef8300176f43419a9488912c391ff8fcb4a60ba9d06b38
MD5 49bfd45b2c45ebe1f9ba7e35329edbc8
BLAKE2b-256 189a9ea0f2c61f83ed31507c6c09983f64878751cd9d91ec08c64d4d13e15c9a

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 aeccc9d86e13e89f896781b08d37e0b58cc87affa8ae3808678f14a56cbf3a46
MD5 e92b7281975293e7ea063cafa1590ca5
BLAKE2b-256 69b4820ce2372de6d92f46d9ca51a250476d8a99ce28af616065e435701f4158

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 f40385051cd80517156b99a27a26ed98d58682b293bc5f7941d4ff1076cc79a0
MD5 ef03a3e4daff75dfaa73b2b25a68b8c7
BLAKE2b-256 80eb95b0142ab9dae341c49231902faace24c65f3f175dba8a6b7b28636c3ed4

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 79413c9db45fec927ab74d9327729343fd29af334fca303ca21084fdf9029f04
MD5 1c4b61f68e8d0c401b8280aa731819f1
BLAKE2b-256 2d9f4f8ace18a2616d276bc3c43a45774d1b0a763b883a917b8b336db24cc3c5

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 0655a4b3111cb092b5cf95535e8c8aadce892b1930539a5235be7170ef3086fd
MD5 67bd15af440f05dc17a28f71fc8d3ad3
BLAKE2b-256 df28a6555c58494c767195e947156469684fdea38406cca6c2315668ad24a75c

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 35cf176a99c1bc6093a1f9ac2db38e21a7b6fb9076bdd48932f75ae12f5de3d5
MD5 1395d2a6fe42a0daa9987a98d718900a
BLAKE2b-256 f45450dd23d55a2cf853173472bb7f4c5549253161dba654f37b55ff70b5d775

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page