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 🐍

  1. Install via pip: pip install stringzilla
  2. Import the classes you need: from stringzilla import Str, Strs, File

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. Some of the 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 is available as a Swift package. It 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.1-cp312-cp312-win_arm64.whl (62.5 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.8.1-cp312-cp312-win_amd64.whl (68.8 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.8.1-cp312-cp312-win32.whl (63.2 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.8.1-cp312-cp312-musllinux_1_2_x86_64.whl (254.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.8.1-cp312-cp312-musllinux_1_2_s390x.whl (180.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp312-cp312-musllinux_1_2_ppc64le.whl (215.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp312-cp312-musllinux_1_2_i686.whl (196.0 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp312-cp312-musllinux_1_2_aarch64.whl (190.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.8 kB view details)

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

stringzilla-3.8.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.4 kB view details)

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

stringzilla-3.8.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (219.3 kB view details)

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

stringzilla-3.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (193.5 kB view details)

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

stringzilla-3.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.3 kB view details)

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

stringzilla-3.8.1-cp312-cp312-macosx_11_0_arm64.whl (71.3 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.8.1-cp312-cp312-macosx_10_9_x86_64.whl (74.1 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.8.1-cp312-cp312-macosx_10_9_universal2.whl (112.9 kB view details)

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

stringzilla-3.8.1-cp311-cp311-win_arm64.whl (62.5 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.8.1-cp311-cp311-win_amd64.whl (68.7 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.8.1-cp311-cp311-win32.whl (63.1 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.8.1-cp311-cp311-musllinux_1_2_x86_64.whl (253.9 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.8.1-cp311-cp311-musllinux_1_2_s390x.whl (180.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp311-cp311-musllinux_1_2_ppc64le.whl (215.9 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp311-cp311-musllinux_1_2_i686.whl (196.0 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp311-cp311-musllinux_1_2_aarch64.whl (190.9 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.2 kB view details)

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

stringzilla-3.8.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.3 kB view details)

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

stringzilla-3.8.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (219.8 kB view details)

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

stringzilla-3.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (193.9 kB view details)

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

stringzilla-3.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.2 kB view details)

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

stringzilla-3.8.1-cp311-cp311-macosx_11_0_arm64.whl (71.2 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.8.1-cp311-cp311-macosx_10_9_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.8.1-cp311-cp311-macosx_10_9_universal2.whl (112.7 kB view details)

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

stringzilla-3.8.1-cp310-cp310-win_arm64.whl (61.4 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.8.1-cp310-cp310-win_amd64.whl (66.9 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.8.1-cp310-cp310-win32.whl (63.1 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.8.1-cp310-cp310-musllinux_1_2_x86_64.whl (251.7 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.8.1-cp310-cp310-musllinux_1_2_s390x.whl (177.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp310-cp310-musllinux_1_2_ppc64le.whl (213.5 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp310-cp310-musllinux_1_2_i686.whl (193.8 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp310-cp310-musllinux_1_2_aarch64.whl (188.7 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.2 kB view details)

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

stringzilla-3.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.1 kB view details)

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

stringzilla-3.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (217.2 kB view details)

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

stringzilla-3.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (191.8 kB view details)

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

stringzilla-3.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.0 kB view details)

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

stringzilla-3.8.1-cp310-cp310-macosx_11_0_arm64.whl (71.2 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.8.1-cp310-cp310-macosx_10_9_universal2.whl (112.7 kB view details)

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

stringzilla-3.8.1-cp39-cp39-win_arm64.whl (62.6 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.8.1-cp39-cp39-win_amd64.whl (68.8 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.8.1-cp39-cp39-win32.whl (63.2 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.8.1-cp39-cp39-musllinux_1_2_x86_64.whl (250.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.8.1-cp39-cp39-musllinux_1_2_s390x.whl (176.8 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp39-cp39-musllinux_1_2_ppc64le.whl (212.0 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp39-cp39-musllinux_1_2_i686.whl (192.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp39-cp39-musllinux_1_2_aarch64.whl (187.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.0 kB view details)

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

stringzilla-3.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.8 kB view details)

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

stringzilla-3.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.7 kB view details)

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

stringzilla-3.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (190.7 kB view details)

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

stringzilla-3.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.7 kB view details)

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

stringzilla-3.8.1-cp39-cp39-macosx_11_0_arm64.whl (71.2 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.8.1-cp39-cp39-macosx_10_9_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.8.1-cp39-cp39-macosx_10_9_universal2.whl (112.6 kB view details)

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

stringzilla-3.8.1-cp38-cp38-win_amd64.whl (67.0 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.8.1-cp38-cp38-win32.whl (63.2 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.8.1-cp38-cp38-musllinux_1_2_x86_64.whl (249.7 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.8.1-cp38-cp38-musllinux_1_2_s390x.whl (175.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp38-cp38-musllinux_1_2_ppc64le.whl (211.2 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp38-cp38-musllinux_1_2_i686.whl (191.9 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp38-cp38-musllinux_1_2_aarch64.whl (186.7 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.3 kB view details)

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

stringzilla-3.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (186.9 kB view details)

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

stringzilla-3.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (214.7 kB view details)

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

stringzilla-3.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (189.8 kB view details)

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

stringzilla-3.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (192.8 kB view details)

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

stringzilla-3.8.1-cp38-cp38-macosx_11_0_arm64.whl (71.2 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.8.1-cp38-cp38-macosx_10_9_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.8.1-cp38-cp38-macosx_10_9_universal2.whl (112.6 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-win_amd64.whl (67.1 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.8.1-cp37-cp37m-win32.whl (63.2 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_x86_64.whl (248.0 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_s390x.whl (174.3 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_ppc64le.whl (209.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_i686.whl (190.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_aarch64.whl (184.5 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.8 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.1 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (212.9 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (187.5 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.9 kB view details)

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

stringzilla-3.8.1-cp37-cp37m-macosx_10_9_x86_64.whl (73.9 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.8.1-cp36-cp36m-win_amd64.whl (67.0 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.8.1-cp36-cp36m-win32.whl (63.1 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_x86_64.whl (247.3 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_s390x.whl (173.4 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_ppc64le.whl (208.8 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_i686.whl (189.9 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_aarch64.whl (184.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.0 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.2 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (212.5 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (186.8 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.3 kB view details)

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

stringzilla-3.8.1-cp36-cp36m-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 0df27bb1b43a9afcfe7dfab7eb6516c62a73b4f8b01b2a898d6d3eced25e344d
MD5 45c51d98d0f1cd0b3ce9ad2bd9dba04b
BLAKE2b-256 c9fe40f134c05a8de559d63ef2b2534374cdff740e10c769df0190bc40604e56

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a0477672e6942b4831ec6de8b2eb2b5b1de5139e70cd67cb2c72413e94f0b331
MD5 13f1a1c2a4061ec9bebf6e509861296e
BLAKE2b-256 9364ce03e596d1f54ed1cf9bed46fae9279730fe02823fb6492ecb20717f8f3f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp312-cp312-win32.whl
  • Upload date:
  • Size: 63.2 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.1-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 25932089365d5178931fac140950377bc70e6f66127ec1de8961a000d8cb73d0
MD5 3a6434d31ed6fc497d16617656f749b3
BLAKE2b-256 984730c267a7d60ed00e4e6f49290a55385f19eea55fda899a53b1f2f1351e53

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1a63ae713c82e53926157e0c9a35c18cb6b41157eb394b4f0bcd5be1df18667c
MD5 75c2258f72ed6b21191efbd188a0e26e
BLAKE2b-256 3efec5a5d248b466946b29f01af64ef97042bef8de0a3f7851c08d1dbdc29d9e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 2d843988b94ebd1baa081e8e953888d35529dd8676b5df9b9c4029ea14cae6ea
MD5 bbd23593c9d415f5641f09cdc344de27
BLAKE2b-256 04242a22c9cbb2fa6f9f779fe8ce7d9278e117bc61df0c03e3128fb668fd56ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 9a84534f37af5298450304b5873002db271a43ad755c98827310762831dbf835
MD5 32a4e45ec0a015151b474dbf8fb60ec5
BLAKE2b-256 e33cb9cdf55ba21fc68c214455da206066a80f963994ff89376afe26f4e273c4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a66365b8dcb643a98a0e88e5af6185822d235bbf43212221fa21cafddae57bb7
MD5 1b197531295faaa8c3290da1ba6d0e4f
BLAKE2b-256 1887b84f4bb529d5008c87e7233debc575d6ecdb110ffcde2c452517ef2634c3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f4d94e415a2850a8aa2f3088f5c42a180462ae7a59c6a38f1196d05629a516b1
MD5 a9833058419cdc72dae63d72e03ee80e
BLAKE2b-256 fc5a80826b1d132ae177bd62f90301fbe95414303ac1b62e7fc7ce2e0c0af434

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7ed1d5d39c5f671bbb07595d09a7469d5096284794c69765b8c96a2d5ff3a8c1
MD5 d8a90987621ac33e187eae700aabd414
BLAKE2b-256 caff009634d4fefc6f60682c63d787fcf12aa16807cfdda79ca016b71d558531

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 f12453aa34491ca4ab79499f31a6fd14cc378001f482b6d45bbd09a06bd81272
MD5 c9cce00fcd66797e6ff0793dbd85a2c2
BLAKE2b-256 f516b8adc294c49d2a867d6957afc83a829c677a0cecb5b0fe642b30e8eb0736

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 5663136c0e5e0fabdb7570593454f8ce66ccc638ee320022b1347f58cf25bf4a
MD5 3c8a3056adea6fd1cdeec10e629dac57
BLAKE2b-256 9f0e95d853b3a46cd431ac2978be2af5a0498a7e5cef71a7caa7236dab84529c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 80ecaa1e23f0a142a81b791cb28d60560626c727d35f232acbe23b2d258bdb0d
MD5 5748e9743a6943f49ffde8e337306e76
BLAKE2b-256 6144121688a7e6a317cdb9c4576cba6a78e68434ab759fcd36a9eb67bbc6410e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 92e6dad85d2e6932d859a81626955838e003e8784a955f307783362450ff5766
MD5 b3cd64bdc826e1434158ae70fd1a8e67
BLAKE2b-256 480b4b7882bf5f4c8e866ec24d25c2cb34cfd4f21e5aabdb7b7a066767c2b4ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 90d8dca309469138c5ed15645447227990540e43057c675fe746735456cf9b2b
MD5 e3ba9f7e056e21d64a971cf7ab3427c3
BLAKE2b-256 80c571e5fa68811233f10ea775f86cc86814190b761fee4612bf115a1d2b795b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 9d7113b49c27d075f32b7987d4941302608cecc4a3d6e73ce08a66a73249ca66
MD5 2d8090228e50cb531343e4b3e43a228d
BLAKE2b-256 63c84db3526e1fa9a6aea620a11d352f1a88126fa4ed9f5379943411ba907b14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 e0eb074df7e50a888fd746c38d66a02569b25e628ec6cc0c140218787b603053
MD5 2906c03a84b101b126743c1d6c092c42
BLAKE2b-256 b273057dded4f8100454d10e69a77e1c127789a6285cc45c0b94bc3267dedc70

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 ed655eb155b3d8f63da719420cc21cd1ec28e8d0ce81ab68f86f2ad2383d189c
MD5 e71a66bbe637b5da363351191c8b6b0d
BLAKE2b-256 a3dd33cbcae468803d47d44d61d18f48236f1c0e8e4f35b962ada003f5033c3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 650d9d416abb7e34b990f60c5c88874d36039954eb16f8e68af66a01bf15b404
MD5 970b87f80cc00a89dc3ae7d1ec531fc6
BLAKE2b-256 e1f9fc6ac271c06c3855be9665534362ce6d25ec6d3801dce5544bdae0f7b7d9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp311-cp311-win32.whl
  • Upload date:
  • Size: 63.1 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.1-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 66af6bc2322ea70f1dfaeb9714dbee68fce42d7fc43c6ebc82fbe6caaaa03dfa
MD5 dbc709fa5bf21791bd40c49a6f0cabfc
BLAKE2b-256 f49bf99e3b0fb52ad29ce435da29fbc1a6398325bbcb4cd7d304dbcaf657a480

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0228b8bd00d078f52079f5a91bd18ccab7381ad287862ed1cb351250bc9e98f9
MD5 8fd39c125263c24b7ec201fabfd2ef90
BLAKE2b-256 74a4f96421f7910a2a71ff5d298dd46e49d18526d7f551816b78f8a2ffc58a35

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 558fe1adb65967d5d14d9092100449db6affc08fa29ccc4d8ff483b2176f4c7a
MD5 b23a996bc8de49ed33e649f155f74cb3
BLAKE2b-256 12d925507df5489ffffdba435b6d28db9d7749bc678b8835c6957251c6109b8e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 cfe27e5f2d41e2c68faba9e0270f891d6d16dcc8e3380ae7e7f079c4dadc99ef
MD5 725c2f46de52addd550e98be0ba02993
BLAKE2b-256 618c3d1a62413e7a2e86602c74299f68411dab8cdc7ce54aa99a559c1e2a03a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 5007a15b375e6357065248e513eac77ae5fa33ad0733f9547469334032515972
MD5 b44063e1a5a66aa197db17542e6adf00
BLAKE2b-256 91dcffcf713f82aeda3c297682931d4d209c4e6080dd650be6146e5c261f3756

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ba720e2a0b6e45a27128e3225a3d2b0fa93606b7612478ab3fd344bd624f1414
MD5 49c9c6f0a6cd202e4674274f95ea9bd1
BLAKE2b-256 2b803d66a75ab6e02a2556f6068a10d508b70c22cc97b93a8168c2b552eafbf7

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 421c3556b7267abb43522ef2b79ce7e36bca51ab020e81ec2da5cf0175ed5f1e
MD5 c3ee812031eb464fffe404bc14748a36
BLAKE2b-256 c31ce1aa121e5e0f083ff59a9afc5db8f6e21ff51a8a99bd7ab0c7681da24ff5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 be078bcc1171baf335d8a9f4496fe37f780045460e4d71895f088df483a09d6d
MD5 020daddbe33971a83749090c1c996f06
BLAKE2b-256 fbdb759b255d0b88a96a1bf2d9d6a8ab361eec1f94cf03b96f449fd979e8a804

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 5b2771d512769c4cacddbfedacf9a219a5576029eb5bde91826da70be361a6a2
MD5 8d3fe6be5df65ee08faa5d0d47c4a4f8
BLAKE2b-256 948d60810f44fdce60a251fbcfd998b185cb675252b75df0da56b167183d97c1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9344c359ae85baf5e0213ae040f9b7a11b4e663be97578f38a5fba6908abc6fd
MD5 a01a4cad1b93885700645cb8045a05a4
BLAKE2b-256 38a11ea7d1f2f6470c54460b695093166fcf3db9017723d6c1d745f73dbd3219

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e51e67b632488abfd56cb633c6ab2d4936b242f95d4719ed66edebe432c7aaa0
MD5 181450e8be431ce3f396d85c186f3091
BLAKE2b-256 c469cccddda80eb61946f4514830317ebb81ad89472bc8c228d9bc3e0dc8d9ed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 554043643f45d614a71a5cb300fc4e3547a34af3667f2fb78749d5fcbe4345dd
MD5 4c8d45125693c49280be877f5340525d
BLAKE2b-256 8fa5e3734e17b4c06090b21b1b700d7f7cfa3a4886314ce8ea8ab5c74abb8c87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a733116b020ae8c2371de3ebbdc808ddef1dd7d076665da641fae7b1d7d6df97
MD5 ecd8f32cb0c6a7eb5cc027f82fee0e4f
BLAKE2b-256 6dd7c05aeede44064f2b87186380f7e0edb301fdfd6152b1adc838798e029172

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 f94a6f8126bc2240230a2f318431a1d89d5e63068e400041bb2859187e4b84a2
MD5 c597c29446eafba8577564b1c6b9d6d3
BLAKE2b-256 69c4c98660831b619420c6c100da6b30f7df4c87fd1913472a0fb6ae209f6e48

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 a63636643a8a837c53a25bbf3db1876d9ec58258aa384b8626d8fde6d862457f
MD5 cfb1fba8995ecef6a9afcce033347170
BLAKE2b-256 d21fbceb88ce859c7ad6591eaf11f7ef74a957f4b02dc8ca4fd1f61a09c1912b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 c16cc484d35006b05773b7d7c5c0b3a432dd96058c0148cf02b2b4581da459db
MD5 ed6b994df56444c0795b779c90bb5980
BLAKE2b-256 6107422c52eb412f9588049fe260a69840d7ffb23806c21f578df9633ba03859

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp310-cp310-win32.whl
  • Upload date:
  • Size: 63.1 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.1-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 4e34b412d6edccc7345a9380d3ee9dc2266701ea4070126baf3b517d3cd95007
MD5 c4a0ea9f2f82beda0878c0c16ccaafd6
BLAKE2b-256 89ee2f03f9bf87ebb9b8e2e39a74db31f0d7e34bd6b42216974593cdaa4b03f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 908479e9e7a09c839f80e2730e5c1dd94e0fe07a5e51bd380b377244a2fde5d3
MD5 e66fe85973fdc5bd42736a562c11822b
BLAKE2b-256 5760d8815e43cf0a8860b7467df84f5c59710abe10691a5628cbbb48252e632a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 8a54d5f75a212dcc4eab234d0287a738c142dd3a52d26d8e3a240ddcd29a07bf
MD5 1e9bb3cd6425f698c42487e10be1edfe
BLAKE2b-256 0fe681f75c22c9ad9de9c453807c003a7e7e1c3ee0365a82cde4158a71caf528

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 14de748863517b17e8d16a28f0e58fb8a9560edc6bf2a2fe8b9c1abcc0ab7194
MD5 c2bc9982c676787eebd09470e48216d5
BLAKE2b-256 57a38b2dfbcc187f82a2f5b6b55f13dc166b2cd81d41cdd3b6eaecbb77e25463

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 7ee4012fab46e02e8f305f69f427f859d9ed704b0850e584c8d8d72ff61bcbb2
MD5 22b8677b46e9d83dcfab8c9799403f16
BLAKE2b-256 5c76aec2e091bb37c5c922edf422b62776f3facd1469295ed8d6d45e705ee15b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ec1aa18f6e37c97f1ce32947b92c8b9c46385a3313e823e9496c5d33a7ef1d37
MD5 a27154e53f907d080c382460b053d4ca
BLAKE2b-256 90dbf36311658a0c0b68f23c60d6b57da2dcfe6ffa1ad62866668b6f7a6c22bb

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8d2f02e075bdfd1962f1d3d851e5fc2cb5cd680e2152290ed3d85b7640290259
MD5 1d95390889b0ea9f7f3e84d7687d75c9
BLAKE2b-256 23cdc61221bc253613ea1c0e35f10fd90d0931b695e933b9196ce2b9e0bdaed1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 8126060e112a28c3581fbd2524a12795509faf78161cde0ae02da10283d89238
MD5 a16f1e1fb650a38519e9389be4a7a381
BLAKE2b-256 dc32c8460e35a48b15d251689ab54f6b9b41597afd91626aa322075be4a4bf32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 3245664a8adb6ade4541cd8a581b84fe3f77ec972358b6062d94d54c4ed95d96
MD5 e5a066a6c9b712df8c79fbdfdc017d55
BLAKE2b-256 e57f34d7c9c0ef11cf1db6e7a070e907e8bac680b7edfbede0bffbda6ac214b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a518be792f401e32dcc3679fe8da9c64a5edaffefc46c576adc152074d102c74
MD5 a2a632b43c93f8b60accbe5be0d88d9a
BLAKE2b-256 4ecc06a81bdc9192b9a69e977085d3ac923736befe024224dcec5dab889eba2d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c7d67cfedbadc20ce37d7120b80fc6f2e738b4a97d9dee8b54daf6c350c81adc
MD5 fa7f3e0f7eb727c79a4c258eb566220d
BLAKE2b-256 3c4a0cdbe6b32057dd1def8794f6cc55f7e8ad1616811b8a76ad3372e4b402bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f7dfe73ce49b1f93e58bbe0df151a0932d7efc0b50032fda498ba86b7262d6c7
MD5 dc8ad5e70c2500314265b9777d5250de
BLAKE2b-256 ffc4f49150551c2a1acce2e9ac11edc4a996d1a23e2750ee08acd2cb299d8a0b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 41b523f8dfdc3c8c18ebcae1bb08918023734d7420bae919d16a47be9a98bbcf
MD5 80e6b40cf77c5f79514a2636cc84633c
BLAKE2b-256 f81b727556e9a54bb6ed7b781f2a5f31e90566d9c57e1479906466b75c31690b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 0065a060f837dd7c274811ad9c47d59321606d1de2af41e4b4550d262c47fda9
MD5 8efe26e2d8720cd48af34da39200c787
BLAKE2b-256 05a31f9825f37a8425ea30b1411017a10b822618c36c1a37aacacf231ceb73a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 218452207724e95932d89df92f9d7d1a97d453a688a20e988842791664e062ec
MD5 d1f1165197e5690eb1a5c0dec195152f
BLAKE2b-256 ddb968e76c32ca717667cc75dfb0a78e2429533feafdc4cfb522cd18aa66d4e9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 0149e19e19b10780705bc8efdc901b8f0306f3e06d4ae35f56fe3c0dcf1503a6
MD5 e80f323a146b2bf0be860c4c903b101f
BLAKE2b-256 2782b47b4645ceebc3646f51ad61a554750a92b3623d36e540a1464be3121ae0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp39-cp39-win32.whl
  • Upload date:
  • Size: 63.2 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.1-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 5a072ee6732cb4ef6b5a3a78b8a5bf66c172349f1289820f3896ce4043d84c59
MD5 58a5238d70e78edbac905d2c6b629022
BLAKE2b-256 4a0c58bb2337cf5bec2ea174402605b02d45395694d308612642522fdddb19ba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 13b4b4a01ff9d5e7dfacd94e8a9263ada94fc15132ab8e3b917dcff54cf07e39
MD5 6d6c3fb4fceed90f7e60a0ed50d7b07a
BLAKE2b-256 c6e0d7f08fbdc668dfe8bf3ad03823df8de2c2528f2263caf9528d15e0e36b97

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 acf757a53c18d965a28d220f693a846e5ead41e1efc5cb2b6e3d26d9ce5f1e41
MD5 bbdcd3e54910b95a0ea71b7779f48c1f
BLAKE2b-256 a659864fae2ae3b9cc4872157a3afe5910a29a156bd02000e1f30505abc69a57

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 24e1abeab2ad460bb9bf5c2f9c40e4376aea72d73394518577ed5a16e8866a1e
MD5 f719ec46908497cd4193610b1a8b2d0d
BLAKE2b-256 d012d88131289db639522f48d663f6e0f97519a2c6ad11f78b008acaab3ec3d3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 c561085184f07a29168f44cca9bdf51c798065191af8dff3e579bcd5ce04909c
MD5 0b8a8bd8d6bfe79a5bce9f57c3b21be7
BLAKE2b-256 65f61081a709cee36b993e328de5f6e01db4c4c85c162fa4a2444d8d700d05a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3e7429ffd941fdf60d18f4811e3dd29c6212b5586e01ef50602f22a3529d6a7d
MD5 048ca742ca0b869d499f940e2e1bfb40
BLAKE2b-256 3cc7f860d83df4d275dff0bdc83d185f9a328dfeb0fc940621dd05f6a2b83f47

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 36eb985433427f8ee604dcc9e3b8a59bde252c2cac586c62ade44ee0b2a0f85d
MD5 b52b90d15a77b0104ae7756ab2bcc8dd
BLAKE2b-256 b473412ec48b7525c6b4280c0e8b3765ddb53a8d950cac666bfbc664958be260

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 43213ce9f7aca67d4387b7c3f3bb78be255b3215e0015cc296e38983e0ba605a
MD5 e499206b5090bcee4464cded165062d2
BLAKE2b-256 906882bc37af6214aa2c6330a9473724f81b301d14a2c6288f93642a4548f2b7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6c9ef79fe6e44926e450afd89d2be1c22e19440208d771a0970dc12d59bd3cd0
MD5 48e4067ad396c47e73c88d7495ff21a3
BLAKE2b-256 d2a41f414c554075f79a84550c3f6c48e69e82226f8ceab2eb6c32e39d776f60

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fe257a9d9602d8da4589f0a64ea7ccc241701e3e9b6f7de2e5895c942f7cc201
MD5 d02d8a7a9bc3a9810c6e7a42453765d1
BLAKE2b-256 797a2323719947829ffff12ce3f78147257fa0eac52e97fdd54f67fdd1328e20

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9b22764d77582a553e15918a2b70354231e59cf5011ae3e4a729fb6de642baa0
MD5 aec5f53c894adf798aa684bf22c9c534
BLAKE2b-256 11aeb41d2cea03a6bb8ba282f6245a3873a00178ce409a7e9b52a37e0e05b62d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 44674795dee5f5b8766be45ca7620df81b1bcd90938e464f0c0af7c559b29919
MD5 c8944bca50dc8cf2a0ce560bea5564aa
BLAKE2b-256 d8b60c7274ab77f0b89acacb647130d1b45f21c726e1394dd05b152a1dc942fc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 34c89d3dfac1b3898faea77b7ec277bd4484dee5435e54b638dd3b0ade093e61
MD5 be5ee5b92367cb49bf7a6c8f8224d445
BLAKE2b-256 2fa5b572569e57797258f11aaae88836b88fd5c7bd1b4f3863ce433da69cea2a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 609fa3a46ccda55766cecad845fc879ea67bc3751489212686302ac25aa706fd
MD5 9cffa52930e6aa88a6d4481b2f03bda1
BLAKE2b-256 52a60d98b026a8d1152531c5dcd663f1f4daa6eade67d123cfba4008a0e096d7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 49fe827e1c023f135de5b970dad5deb19c825311d4600b63bee7767007aa37ed
MD5 50900fc012e13f5cf963f3c93ac3a484
BLAKE2b-256 5dca1fef6d5b3246d1b0a0739ebfbb21024b2577d4fbecc2b061cb6703d701f0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp38-cp38-win32.whl
  • Upload date:
  • Size: 63.2 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.1-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 35edb462e18781adb6bc2272a0f98908e943526bd241fbd7abb10b15283df2d5
MD5 332acf790da323b54f69473c9a2c49e6
BLAKE2b-256 308b13661cb0d521e401f18b42adbd541d306ae62dc6f7957dd67fa4a6f0e30d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 527cd00a2a0ffcb4886f441719f1c9702d7c72822a2b082753de0af020ee5ecc
MD5 006464017b9efdec053487a4c78f9ac6
BLAKE2b-256 3804504a93e4bac5ccc6aeb093d283e06cc6cc75c55cfe98b8dbbe4d80d849f6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 8a080ad255de8d79b9b5805c479e60698049dab127de8006df8de2106d79ad1a
MD5 4c914230457b57255bc2575d1b766904
BLAKE2b-256 3ba333d24351f3e2c7711a2e26a03dca114d9f68b7c6722c1b86893fd8638656

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 7c041fcc18f0d3120bd966c9b66105e61807b5d278919177f1b4e8134b739352
MD5 42441c716e2e4d869249c3c30ae806c7
BLAKE2b-256 58328499957e1bba52a5f8f7baf7a7ca117bd86502de99b0ebc9bec11d39ec6e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3bb133ba9cab964f5ac1a221806e5cf4d68a5080e6475039636423674df5645c
MD5 456f02a0a3901a7c9e90d6cc9b20bd0e
BLAKE2b-256 2d291fed125d8d8d3c6ee1505d03730c0a537ac9cf7149de19df0e2792e4ebd3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3cba2aa4bb9ddae37ea1889fd0d478c8c2d329c943cc61a3769bdabdeb69ef3e
MD5 bf03fe9014fd095463b3e78a04ace29e
BLAKE2b-256 1a4c1d9debbedf3eb376135ae024a0829f6183dcee62a3fbfd69169ddaa05c7d

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 78a3b1eeb320c0dd34f24fb8326e47e636fad057a92e4b6df27b822ecbd1a117
MD5 98cc78ebc168c04c48a06379acb1a6fd
BLAKE2b-256 8b0f88e522479e50afe584008d9c4e6cfd00f15836478cc094dd2cf2a1fd0373

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 6aee3e187b427ac6b932727be25755d23538907fcc7dbd3b946236e8004e2ae8
MD5 f8142a8af9c9c2156f39d542ebedc0f1
BLAKE2b-256 88d3726e7b8cd59a0b927c5f39034815189e3e0159b7618e2b83f1ced5964b75

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c91c48c7654d12f791533b2b9e2a40c9ac4d4661c8397f7395f872fad39599ee
MD5 887c077207fd1ad50f0ac5c5161a89e0
BLAKE2b-256 7c65313ecb7ff6745e16d7c348919f31e2ac122ff06be270e3cf0f5567d24b7c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bd0c4033422a7ee445ffebd8217254f0edc2f6b933d37f6ea3d11ef6e1a8d0a2
MD5 0ce06e0cceaa4b82669e9cf46c0019fe
BLAKE2b-256 acfe9751419ceb253518f10efba68837156f462f6f931d6f9113ea340fe7b938

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 5c81f8107b33b37854f2c7d80e2e335e98b520f076ef9c95c1059b35b2ee4317
MD5 744319579a5efcfd2dfafd2f7b9394a8
BLAKE2b-256 fc35dcbcf9659ecefd3bc39bee343942287738fe2a4f7b20e346c0a44ef4cc66

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 eac7a42173d743c4141d48cb66676229e6fdd9da311912438318defc5e39f18f
MD5 b95301e3a4d56ce38238c17689e6c977
BLAKE2b-256 1911bdb28c36814c174829bee64e70a4780d9899afd9a771e829d654ebf3643c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 c6bba55bf713a478a32ba280066d568d78cd2dcb167f760530ad4f996290342f
MD5 7b6c8e3c5821491ac5c279db8f4d583a
BLAKE2b-256 a761cb117cfc15677d7ca6252dd0fa6ebdd068b83b426a8e0eb5ce038b8380a7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 bf21535eece1184297dca2bdc4dfe514e4e53ec34b455b1159181dfed6f57009
MD5 f83238705070ae5a303083dc1588ced3
BLAKE2b-256 375075f467650b5c3ce6bc1c863bbae393294f9a10425aa3aca244e4e7838cf8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 f9136a390ff860e66dbc8cee393836bc87a77fab0e5759b2907e1c8e82f74752
MD5 38ff2b07b57515a67c3a178a22bba31d
BLAKE2b-256 2017513608eee14fcad6d30303617a89586c44c18afe210c5cb048adbc8c8e15

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 63.2 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.1-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 4010cc4c3d78e18c465f04a2ed990ca3192fe5f2ef5102e7e7a1d6fff34eaade
MD5 bf0645e0445a3ccd88ed68c00f97ee8d
BLAKE2b-256 b509b04cd908526d8407c0dcb1fb00ecec0bba499e054fd44127e2cd135279c5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 77c487a56355645d0f53672266caa3041ae6b996620bc99a76471079ff950ca6
MD5 548f1ae7add895b4a438c00ed1d93bc2
BLAKE2b-256 67820e525dd84c63cc1f6547a89f339bd4ac1108c89b571e12d4018c71be5b8d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 79ae4f8872fd1d082617d61852c5e9c64aa33f8d786e5c3f3dfcfafe4a2cb99f
MD5 042ff8786d29f7e360ab0391a23a34ff
BLAKE2b-256 9a7f79230612009009ac787c694ff87b471ee62aab6e78b1d261016d06d714be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 befe7045fedffffb179690c3e32ae3f81fc41e681962f9dacace4fe5fd32bea4
MD5 4a81185847355bc175b7ebcc9e70dffd
BLAKE2b-256 b5f94c408730e785d1e11a18272b40d790a0cf73add65f4d26748d58f202c2ae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 4698e49c7e1e2cd7c1fe4b55662016c03d0324fd488ec61a795f8a35d8ddf82f
MD5 ea2812318352c896125def367dcd7684
BLAKE2b-256 4eee816c6f5443e147032aadf7556a75bb22aeca464097d55aa88c072c67ee93

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 cb79a006753030f1e90905a2ea3bc8034a02ec8271f1d187ef658da9aa73727f
MD5 8a2a93ef21038aeb42b546ff86ea51cd
BLAKE2b-256 9207d0d548d0d6f7b6eccd3fc02755bf81967f2855fd6f9c2b1415a25dbadaff

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 38df1e3c5f2ec4919f7bd1274c35928be35a1c7df1f22be480f42a73fa179f33
MD5 a544beca47e7391499018e24d45a489c
BLAKE2b-256 d644f3895715b34d07a324152e6a89126ae7fb62134804170e44cfe0e838b9e3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 c5986f70e565db3d333d9ed8fffa381689b7b546fb4f46eefd8f768754937d0b
MD5 08c28d69e5c296e45f49eab7cefbbecf
BLAKE2b-256 eba82fcafffec1d1b11bce9e6d797b47f6869c692022057467cf558c5e1b0567

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 f4a5c59bf6da0fea92f9d7c53600450e706ad4f9d8b531d70ae5f942818389d9
MD5 8ab7b3bf24b8ad8da3d4bb1b41fd0499
BLAKE2b-256 d81c5bbab2932091e93770507fecda8fd990e2119573f322e5deefda0c84956b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a8bd829ccb5db629a4b97030ad4b14005664f757571df7441b23f8c93208b670
MD5 b03e2c3612b278bb223416421879dc68
BLAKE2b-256 420d383052da0d95721cf669d5325559b7da0c8fb6e66db08eaeb1ce1d752370

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 bf4ef1fd74b03a258e83b4eba8b50916272bdfa18fa257a250c2c2dff6d38716
MD5 6dbd23391ad9e0b3521577778fbb1170
BLAKE2b-256 e910a29d1432006f1de866948a55798f14812077e96408eaa42f6333519e4e74

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a2c0e9b5821d0c6cc652d25f566dd9f6d1bffbf7ee1db4cdc0f299f46d025b4c
MD5 1052d97a4490f771e7a1115a6fb38ea5
BLAKE2b-256 20f244dd79e6e38c97c6b0185abb001b709bdb9afacf154d5475a49932526ab0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 afc1387a705b494ef0f932efd921cbf1e58490ac4e016b52ea5d05a31a17eb52
MD5 6c3f51fed72375aaa696d2137e6dde82
BLAKE2b-256 c4b8e979057fba2ea2ef18ba648e957789b04d973970066d48881d6dd7e2cff8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.1-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 63.1 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.1-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 6306898a233fbefac4ba5872195c964d5cff8eecd9a42d24625fbb6f0a746322
MD5 d3e47ae17275de27246d93046026fb90
BLAKE2b-256 21239516d85ace4f97e4c232abcccd18fcb7c84863e0eadd7d36a41828685e2c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b95eeeb859bf6f3239f9ca3341a8aec2f8d58a46a7c5dc83306ed97ec6d1db70
MD5 646d83518b65bc4bcf3e7efbf7674e7e
BLAKE2b-256 534f9b5c2479c7b705c2598e4826063777602a62af5e0f952e53e6ceb612c923

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d3cb858f9a53d3e384b288cf4f2c293ac6c67b5db7e02d915bfda0c9203d44e1
MD5 eec873d40e621766317edb347b1a1de1
BLAKE2b-256 3746f2191a245f3415ccf7708956b5334e3c6058a481730656daba3b29dcd005

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 f486a4cee30e8de1bfeda759058bd07eee1a0b1f38d59dfe9c7fa7febfee039f
MD5 7869cb553e29be45d77352cb41fc8046
BLAKE2b-256 c9e5c4e5eebcb1192c35070752de3c40457fd0ee3571b024a105735bf6a51b18

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ff47e2251d191d38e0c4975cde0daa037bc1068c112db19c5e5731e181e0cec4
MD5 3ae5299be91ed43dd18b5563bacdd9c1
BLAKE2b-256 860b62f2e9a4b3230982b78f0b40b6da990b58b1d5c869e859a44e8e2ebf7f7b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ef83783a61ce7836468f1be84e219be78dcf116e92076910f3a26f28a00327ba
MD5 c759ae93ec0370a8060d4b9a47223614
BLAKE2b-256 df1a1557cf4e5a3b835d5caa389e8f96ab5b3ff786a2d1d6c9acd20d125f3be0

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.1-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.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 96242af89da582755c5c76580c81038caca8945f0bdf170f1ea9d84bf5e0a22c
MD5 d2458e07d8c9c0c15ac1c9ede97164bb
BLAKE2b-256 2885021dc60b3f72b27262e248280713ed699c4dbe0cb8ce6b8d289e9d90a9e6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 35162756fdd16e3ff692ea1359f3e0eb68cbbcd7c4b3effa4612e327bd9183db
MD5 2a8eb38b40cb5db66c58c83fef69332b
BLAKE2b-256 e9cc8f953270f9f5c3e33de762d995feda5dda8e25c8abaf5557e4dee442d658

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9ba589e108824426ee3ec0d9ff7e3f246a0360eef1e1ce5c25f4ea7460cda1d0
MD5 28f5d1139f0c81f6b3dd7bcd9db3b73b
BLAKE2b-256 147d958d5270203aae718f2b1e34aea36bf83b311bcc75b84bee97fb7e87df9a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2db9047b630e6f2056937317edded6b86a857fb1198cc610dae075d584e52add
MD5 7fa02bd6b7f57c5e0bfa502e79f7d10b
BLAKE2b-256 f0e717b138612682f20d0e334a4becb3e757b75aadcf85b37f62a5559e92353e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 b451262745792e14a86d2ba5146e894e3289b8f014da095962640bc30984e73c
MD5 a2589c2aeff6ee13babc522d3a3f62ee
BLAKE2b-256 bfdaee61fa864de943044406e11740fb4a72ae231683930e5ce1e16ff6701a62

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.1-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 bd9558ecc64bf8f28fe39aeacb66daf61ca95bdcd1df4c7f396f09fd3d83696c
MD5 5d53c2125de59b03d799daabb9e481eb
BLAKE2b-256 95e9214cdd5163f840c8e1d6e380dd4c6d08e674f890aa59f472b729762b1734

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