Skip to main content

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

Project description

StringZilla 🦖

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

StringZilla Cover

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 and is practically a shortcut for text.split('\n').

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")

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. 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.6.1-cp312-cp312-win_arm64.whl (61.7 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.6.1-cp312-cp312-win_amd64.whl (67.5 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.6.1-cp312-cp312-win32.whl (62.5 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.6.1-cp312-cp312-musllinux_1_2_x86_64.whl (249.2 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.6.1-cp312-cp312-musllinux_1_2_s390x.whl (175.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp312-cp312-musllinux_1_2_ppc64le.whl (209.8 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp312-cp312-musllinux_1_2_i686.whl (191.0 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp312-cp312-musllinux_1_2_aarch64.whl (185.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.5 kB view details)

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

stringzilla-3.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (186.0 kB view details)

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

stringzilla-3.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.6 kB view details)

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

stringzilla-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (188.8 kB view details)

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

stringzilla-3.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (192.3 kB view details)

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

stringzilla-3.6.1-cp312-cp312-macosx_11_0_arm64.whl (70.2 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl (73.0 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.6.1-cp312-cp312-macosx_10_9_universal2.whl (110.9 kB view details)

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

stringzilla-3.6.1-cp311-cp311-win_arm64.whl (61.7 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.6.1-cp311-cp311-win_amd64.whl (67.4 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.6.1-cp311-cp311-win32.whl (62.4 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.6.1-cp311-cp311-musllinux_1_2_x86_64.whl (248.5 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.6.1-cp311-cp311-musllinux_1_2_s390x.whl (174.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp311-cp311-musllinux_1_2_ppc64le.whl (209.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp311-cp311-musllinux_1_2_i686.whl (190.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp311-cp311-musllinux_1_2_aarch64.whl (185.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.3 kB view details)

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

stringzilla-3.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.6 kB view details)

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

stringzilla-3.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.5 kB view details)

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

stringzilla-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (188.8 kB view details)

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

stringzilla-3.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.8 kB view details)

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

stringzilla-3.6.1-cp311-cp311-macosx_11_0_arm64.whl (70.1 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl (72.9 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.6.1-cp311-cp311-macosx_10_9_universal2.whl (110.7 kB view details)

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

stringzilla-3.6.1-cp310-cp310-win_arm64.whl (60.6 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.6.1-cp310-cp310-win_amd64.whl (65.7 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.6.1-cp310-cp310-win32.whl (62.4 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.6.1-cp310-cp310-musllinux_1_2_x86_64.whl (246.8 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.6.1-cp310-cp310-musllinux_1_2_s390x.whl (172.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp310-cp310-musllinux_1_2_ppc64le.whl (207.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp310-cp310-musllinux_1_2_i686.whl (189.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp310-cp310-musllinux_1_2_aarch64.whl (184.0 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (251.7 kB view details)

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

stringzilla-3.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (183.9 kB view details)

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

stringzilla-3.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (211.6 kB view details)

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

stringzilla-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (187.3 kB view details)

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

stringzilla-3.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.2 kB view details)

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

stringzilla-3.6.1-cp310-cp310-macosx_11_0_arm64.whl (70.1 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl (72.9 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.6.1-cp310-cp310-macosx_10_9_universal2.whl (110.7 kB view details)

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

stringzilla-3.6.1-cp39-cp39-win_arm64.whl (61.8 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.6.1-cp39-cp39-win_amd64.whl (67.6 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.6.1-cp39-cp39-win32.whl (62.4 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.6.1-cp39-cp39-musllinux_1_2_x86_64.whl (245.6 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.6.1-cp39-cp39-musllinux_1_2_s390x.whl (172.0 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp39-cp39-musllinux_1_2_ppc64le.whl (206.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp39-cp39-musllinux_1_2_i686.whl (188.0 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp39-cp39-musllinux_1_2_aarch64.whl (182.9 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (250.4 kB view details)

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

stringzilla-3.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (182.9 kB view details)

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

stringzilla-3.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (210.1 kB view details)

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

stringzilla-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (186.1 kB view details)

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

stringzilla-3.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (188.9 kB view details)

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

stringzilla-3.6.1-cp39-cp39-macosx_11_0_arm64.whl (70.0 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl (72.8 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.6.1-cp39-cp39-macosx_10_9_universal2.whl (110.6 kB view details)

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

stringzilla-3.6.1-cp38-cp38-win_amd64.whl (65.8 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.6.1-cp38-cp38-win32.whl (62.4 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.6.1-cp38-cp38-musllinux_1_2_x86_64.whl (244.9 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.6.1-cp38-cp38-musllinux_1_2_s390x.whl (170.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp38-cp38-musllinux_1_2_ppc64le.whl (205.6 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp38-cp38-musllinux_1_2_i686.whl (187.4 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp38-cp38-musllinux_1_2_aarch64.whl (182.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (249.6 kB view details)

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

stringzilla-3.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (182.1 kB view details)

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

stringzilla-3.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (209.2 kB view details)

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

stringzilla-3.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (185.1 kB view details)

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

stringzilla-3.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (188.0 kB view details)

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

stringzilla-3.6.1-cp38-cp38-macosx_11_0_arm64.whl (70.0 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.6.1-cp38-cp38-macosx_10_9_x86_64.whl (72.8 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.6.1-cp38-cp38-macosx_10_9_universal2.whl (110.6 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-win_amd64.whl (65.8 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.6.1-cp37-cp37m-win32.whl (62.4 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_x86_64.whl (242.4 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_s390x.whl (168.2 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_ppc64le.whl (202.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_i686.whl (184.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_aarch64.whl (178.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (247.0 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (179.2 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (206.4 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (182.0 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (185.0 kB view details)

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

stringzilla-3.6.1-cp37-cp37m-macosx_10_9_x86_64.whl (72.8 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.6.1-cp36-cp36m-win_amd64.whl (65.8 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.6.1-cp36-cp36m-win32.whl (62.4 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_x86_64.whl (242.7 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_s390x.whl (168.5 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_ppc64le.whl (203.2 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_i686.whl (185.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_aarch64.whl (178.9 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (246.9 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (179.3 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (207.0 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (182.0 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (185.4 kB view details)

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

stringzilla-3.6.1-cp36-cp36m-macosx_10_9_x86_64.whl (72.6 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 0b73077ab039f370f24330b61e039f7639a31242638c9bc9043b430038cf2528
MD5 07aa87a14e83c2b73b5e8cf8183249ef
BLAKE2b-256 eb4b61aac165c5c9e7214ea7bc8fc1df887bcab617591004728d7639866dc7d0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 eff7962a30fd4c3181081dc29a520da09e04641d37c4d191d09335266729b6ff
MD5 1b13bfad91df429ddd33db7a0093b4f0
BLAKE2b-256 59f811a9505d105fb9c4a7ed18d1d30072083d3086559d3eea136322ab756d1f

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 728fd79fb71d0f08dc7eb7f94a67d7389cb03ac096635035944940dc16aa3f04
MD5 9b9080df2791b26c3279ee3ff241b437
BLAKE2b-256 d8fa14f7c49512b498af5e0ef34c28960284d42cb162d2d6c546fcde7bed0e5a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b64d732edb033327f5ccc06e2c41060eac9e5ee6bf9580acd8a21eff629a936d
MD5 7108746006ff6a9db3302ab4ef1b9874
BLAKE2b-256 c8403476f56575b5bb85dc0c3324e67485b53b140264ccde332c4a77559da5e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 91136bb3a618c166f1d2a3623f00f009e22500c5437d0298b36e9085d4ac6635
MD5 8946c7a43c2db702bf493c9ddaef4d3f
BLAKE2b-256 9347ae5e12fa30c65698681aca9edd77fa24f6d24ec46bf306d1fd3de1296eeb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 362c018e11b616b7a0a34c76d49e2fb90a63320da90afec4e8d1649224cb4066
MD5 56f6851d30fc1d096c9e25fb7cac87cf
BLAKE2b-256 15c16a37c3ed4a95c8cb91fd01fb675b650150a20427fb4a76cbf57a6d169193

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 de3bd06b4888190056dcbdf9d7d7e1072f9e065cc88ed01c9a5d3b3dd7e16b06
MD5 a61338ec75f9ce4587ed6ff3e16c5c78
BLAKE2b-256 0ad03415c9e887b726f7a9935b25fb7d72b5e90e6098b9d8c0aba568b5d42a3c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a1e83fd43561a0d86de44e0deafa14a126dba40c88ae8e47108d647a873c6d10
MD5 b3b19f12b20550e096e1df934d0055d5
BLAKE2b-256 9daa37d5f8fa7ddbf72b616e086daa7bbdfc98ae965963b96b0c8105e28d0052

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 032e52b0cf912cd55f778f7c998ee3f23b8f16702596b411f856b60245ca36de
MD5 01905dc261c280f7bc765baecab9b38b
BLAKE2b-256 fe325d7118e570c5b3207760eaefdc0373fc12bfe344f89a1ff5e2580612a642

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 0b136d696c693b4d893d9a519ac6d84281a9a6b5eda24189a0ed71e48573d863
MD5 7b03be77679c3f600295c11e8685a4aa
BLAKE2b-256 901db4c63853affa18ac7d3ffe38d912be74cb152089b2bf0a86ca601c8a48e8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 12a040404f1ca1aa7af9e07501a9148125ae0183c4acebf6e549b326c6b53dd3
MD5 df0ba721f5f70dcf307100775d5b76f7
BLAKE2b-256 4d37aa0fdb5b05be3b80c8f0b86eb95b974a2b05bbadadfc14dd3ef74c542325

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 28d50eee3af109d7171e34b51f9cf1f177a5505eb3f7f7aaf62665eb99397772
MD5 9f390db0cb3c990db92e957b27b726d6
BLAKE2b-256 a475961c896a465d0c94b4205168d631cbf30b363e2204de6674872dbbd21dc5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 80dd7962021cb5788f9bbf3adc9bf0d2d3dcd115c4493d6482dec93a9ec7e082
MD5 3a1a28461ede305acf2120984e28b574
BLAKE2b-256 3db17f55ce3fb82d2306f819e4b6a871e0ceb854ca917bee1fd4df355aaed4f8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d9e99a18d34ea2529dc3a15a51671657bdccefefd21fb039845352c2e014f6e6
MD5 f0b76679f4a47212f2158ffacfe186a2
BLAKE2b-256 2aa6fae485343d8494fc5a0767a85a5b047014c307cdd6d44aef73ad1dd7f76d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f6e3289bcc0064d9aea4042d9b680bc499ee78c30e04c07cb1eeafa7aabb8ec4
MD5 82e73c051a061a06f5f85d7ffb89edea
BLAKE2b-256 cb71a652b56c652fedfd195f8fa0c48bc026d0932a7de8b3908a23c229befbf2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 6d7473b93ff90e4e69d0b47f788f84737127aa526a8265fcdc4462295d519ee9
MD5 eac74289f28b24c5fbd0825ca2185341
BLAKE2b-256 a876c59c77f48b2136f9856efe1f8aeefd82ae0b0aac33ff554282e447680cf1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 64c0e1066cc24004948252cc86e9d509b2f8409212e44895f7cc9dce65ffc8e2
MD5 9b22bafbf46fbda7bca5a392a0bb3091
BLAKE2b-256 deb54bf799938f846f65fbdf78f04e6bdaa340a0f7f7431ab34900f12a96c85e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a65bf406146d8d0f2a4bb861de8959e97ee0cc2f85797b8e73c5d2a2bf1568d6
MD5 9473f09cdd2bbad544367d099a66f68a
BLAKE2b-256 a49212f0ec904ec50a3139e02c7459536ae0b5461efe7af8f092da348357e478

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 a9986c9a6a79303cf0ab0d30a0c395fbaf7c72536299334da7197d8cde450396
MD5 f4936a254c9414d8ea17db717729d0ec
BLAKE2b-256 eb44501b84a95156cd990d416d092bfbf0d0cde6946c35d783f60f2408d9862c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6dac178c4fc08d88277a2fbdd58eb68278540bf028dd382bd7c886e50a56f944
MD5 1d1fd771a5334b460dbb46963a478484
BLAKE2b-256 2532fcf5c4764c8412b8e299a4581dc8e97ee113fc3162ab4eeed9f1eb429837

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 03dea111c965a32e07b64e74b4bf78d891617a489e1ac22aa1d5bf37da81b68f
MD5 fd264c8128ec31f6a7f10b9ddf359900
BLAKE2b-256 d73807f37ebcad42d7bb05e420f83ef0636277d7c1e99ea6d8cd6a83656ee073

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 a0102b7405c01187208f16a3a7224ab91d9e127ebbd16756ded0203efecb03f8
MD5 7faf86cc3068ea2d813216bf433b1882
BLAKE2b-256 2433598558e1ff4b9dc92972cdc350abaec23d0b81fb5d1c44df0de6a1efcb8e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 61215c446fef42018475d9f1b938106af77c939352347c12dcb5828bea06c8c6
MD5 bffe3c30984b16750d5d56cba066ecc5
BLAKE2b-256 f1b6fae42bcd520dba0546e15a5097a0403ac399ed9e38d9754287f76b8f46c3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b1a3bf634b783c02c7473c8e64a22eb3c561d219b9ed8446cc8153f329d123c1
MD5 5c72852c90ea51f27d26fe710e4259e4
BLAKE2b-256 cdd6d74b1ff65d19d6f9cacbf86450140c2196135108eb0ed40719f492410f43

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 63e85cba4c7c68308d1a06c0923a2ed57ca5f67209711f604209e5b7b5abceba
MD5 9ca1d709e6b7828df5e22122b6233577
BLAKE2b-256 2ab81546cb9e83afc2e068e510b202ba80196924dcd73328ee306ca028e26600

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 362b38998df34a490cd174f3ddc60ef9eaaa0978b4005f0e76a787db3155563a
MD5 b34087aa4ad5605ba7fc4c33ae86135f
BLAKE2b-256 82d0597b91ec2c96393bd6e0424c131ed30ccd19aa558a39ae13155ade5996a2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 dfafa63210e60d9ff6f74bbacb8134461724bc09128076d4e413ade5641cf500
MD5 3079b3ef6b539c156e79c81e58f3cf8b
BLAKE2b-256 fd2a08df681cc8610ad2301d774840a958535619dbd5da79fd5bb3f573f610f1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 82d56dbf6f0698c90fd0c1b32a4470e28bea8cb26ed125191ddea337d1044952
MD5 d7c6d01d1fee3ed6e4285571bf0eca07
BLAKE2b-256 9df97bb4c7f3f1aad918260f7f15ba69d989798ce02fb6f875454e0b658a1f6a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c468c85c59a39549d055c65a11e8edd992767919850a6680caeb249d72163d1b
MD5 de0f8f51e08aea5d2f8d114d034280cc
BLAKE2b-256 b88014b1405e6dbaca55626616a1bf39c2c66691d5d747369f48f5e7c103e1a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 98f156f4b79f1f04c6e583eb42cec3b7c1f4cacd38a867094b3a9ee7fd1c0ede
MD5 1edfdea1cba20c38de21fb9213996e96
BLAKE2b-256 e02e047e80e57a38e52cc35b5ed6316bec14d69d104dd549cd1fb540aa34dd94

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 1a086c28b1772b68ea888e60b006d07d0ced415ce63ceb540874726f56fadc84
MD5 ae77792065794900c6d14f3f7b3eabbc
BLAKE2b-256 9366651474b8940893b73eee7cf459758fb11a33953228b3e701c60267dde2a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 28136c1977f5c198a1389bddeccbb8c76b272c0a428ed2d5db131b8dd1b28123
MD5 f8bc2b5d2ffd49e8e0d336998c0666e8
BLAKE2b-256 8999733fbfce2c6340e0812c6206dd685578a9db447ba18bca1e5f4f5d4a0259

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 e550019b1278280b946fb601c74b3add3aff6c1eb75f1b17a0392a1cd21176e3
MD5 3bc55ae4f22c2f774d6e3a033ad4434b
BLAKE2b-256 d20219975b7bdd275380e8c688c93184112887a6acaf2f2209b62a22efbdac37

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 9cc6ed3c3f653cc561f6ca57b6550e14ce055c358d264d2f4e470eb147b0aa67
MD5 269dc14d23c86a83c575378fd049a703
BLAKE2b-256 7501c33903dbe52a306458d47d967a49d6cc29bedc5cc4ee117e2f2356c823dd

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 3ebbbd95ee86a189da04d25349d470055abd5381c577c5a19141a1e38faafdf1
MD5 21a0a9894cd98cf40719a8cf0c31b950
BLAKE2b-256 bbec72234a9adbca8af1f4f0b9106a4945a2c7ac1f85f70f7c7601585c10a25d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e341f88531d0ec1de13c2ab77c6fb13ca0af05429797dea259658ef436a95c9e
MD5 45ea905c4c6506098a079e74fd9dfca7
BLAKE2b-256 d0341bd520001aadb4f28cb65488a53b6789c967b5f17e9b8a5632916587faf7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 555591a7a1f03db939b1cc4f917451db38caa75c600d4400da1692ca3159a27b
MD5 ebd59d6590cf39acdc6312dd9801dd13
BLAKE2b-256 02739bad7facb006d32374cfe0134064f45d469be1d5dde88c60518ce0e3c7f9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 f21cfe209997bbb861dea67450713201a81361a7b17013d95247c0d6dfedd732
MD5 916aa9bbe18d9536c0fa8ccc2fb821a8
BLAKE2b-256 e0ed81aae493432f71a14c5a0eb555482658300357c4c1f0957b1088d96ce047

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 8fda1f7183e4792c076a51d2d76605a4a5c7dda3db455ff0fcb16cfd47f48402
MD5 588c210083ff3d6260dcbc345013aef5
BLAKE2b-256 d459593aabec6e22be023ee59b31d1e3634d2bdf5b0bdf420609537ed07bc53b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4587739e0ced9b17b5d0805877ecfa72849feda34c6d6f8fd47d2f719a679a0c
MD5 a83765228c90b7e5fb627d14e67840b9
BLAKE2b-256 842dbe65fc8abe7b25d9bc4d0cae138549380129ae6ee5c3f8b9bced9e521efc

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bb95db1ee3e52865e9485fc56f13131274a1826191ad8d4abb9516fcace8697e
MD5 4eeda7d97931a1477772367d4653c8a9
BLAKE2b-256 7df14d9785ae83552654c3a1772576604e881db363eb33ecdbb834d8df071607

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 847c67d1ad50fc9ea4f3c40b05d86460e0c8753a6018a5c1ef96567fc87c726e
MD5 d3e70fbada47d360c576a470ebba6cda
BLAKE2b-256 3e942450ac6724697d59e36a9b608f6f6cde05a466637cc4350d5665fb3321f5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9b905f548611c6e6106a416c95264f9e4811b55bab5b003a95ec783b1a08e857
MD5 fb80bf759f4769a654462d72ad417a5f
BLAKE2b-256 b57f627d824317e475fe95d5466180056c7d16473068c1aff794bbe965dc06d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4398e54d6edda82d7ced223810cccf2632d5b5fe6655dd340c2618ff20189dd5
MD5 ce689f5c0900746b9af75510842dd719
BLAKE2b-256 195b40ad44ce460adc711d0642a89f8805e67f572015ff39a66344144326bab4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 051ac5cd7d9f6cb35368f94f45c3b28318dedbe219a07ab753cc7be1515b0f5b
MD5 7b2f5f647b6b3c35cbdf285bbc496da9
BLAKE2b-256 fba45e9bdfc50a2143e89410cc9140f0ab78bc27a6c9ca27f0a07eb379530a36

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a8140a576d4ba41e46afa0b0067ba994af61b676018836260142798df383dab5
MD5 acb4bbe6bb61713004fc3b71bc69b9eb
BLAKE2b-256 4ef1d8e0303c38d0d6013b2ee3bba645a6dc4f9b99b1ca1f2df897d94a1e6b4c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 23505a7c9a5d8c85e391a6f66366a2d5cb558ffcbf22dca45e1fbec9852011df
MD5 049712ecfd5fc474a8ab851ca464aa4f
BLAKE2b-256 0155407975b881edd96e12f78cdb1f67aaa682b001ead6ba54e66230ef40229c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 92225453597ccf659ef3d9c38fb9787ce328ac3dc48d2ca782e378a2658c39fe
MD5 a203bf4884ecfc3534a73e636c24186f
BLAKE2b-256 b7c97d434c895007b5c97a2e762e2305b53285696507492ea47014748af25cee

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 1d4c77144473ab775e62add84d6b710aec3634fa45ba08af530559268976bf92
MD5 5e588b72b1c40e2256fde184f4f7bd3c
BLAKE2b-256 129e42da2478d10de64c0c8856020c85904a4f47441eee4f8e39f0c3d87bee1b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 164fbacbdecd4bf855fd90e2ce133214766a69d60e5ac916a61da03841ddcc2c
MD5 cf585485b51a083d0dc51f49ff55bdb7
BLAKE2b-256 d23c87c317854a577b5a16ef22dd086924845a0dc356c552583fd0f5855576c6

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 095f2d667057cece2492a4951c1da0abebcb2ea58a5682c43f97d92d48a28bd4
MD5 b369baed233f98a8b5e4fe210a6154da
BLAKE2b-256 e95a7d9551a5462eca08bdb5cb79ccb1004a42d692998e560bda244c911aab52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 521ccd413d5b868399c076f9389f6ff2ae86c6c2a9c7df6f06487eb84091e8a7
MD5 5bcdf5e7ac060eeb8333493f6df56a71
BLAKE2b-256 5e40836ee1273e8ef8e408a0bed5c771e82eb772aca43cb08ee8d07307b078d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 1f8b0e79805db6b667227cba583f02af69df01b44b775dda0818d9ad8ce23580
MD5 f46f625f28d291f7e8ae87ad6c52c9d7
BLAKE2b-256 5c33836e5b82e0f4b98fd076272296b27f36a0deff972f88c145baa98cef266d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 f66741d91945c3d2276b63f58991eee01669e69f0e1a2803e19dafe975e7640a
MD5 fadbad78721e4779c1dc02d282fefd17
BLAKE2b-256 61b7a1d3799a2eaf61092624aa19b8479e5579f72c3806bc7ceca0e10985dbb3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ba8f12cae4e470287c003112f2e12a85c8e882ab4c4b06a23a7eb61b2f98bcb2
MD5 99504fc31e5b48d9693e0c221f80abca
BLAKE2b-256 36ec38117f8a3ca2095d2e0dd28fa08f2a11c8074aba219d4d0ddde1fa4f72bc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 7cdbe7ef912b715a39b5ea690236bb4153c3624fb8d2d6c18d5924d08795e088
MD5 1de653b574b1973cb38fe9906d338a9a
BLAKE2b-256 d1d2ecc21ccb6d12f3fd26a08bd05b1603dfe693c69a7e8711ef99bb67375fcb

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c1c2ebee7eea8b6e0439c6518d5106bc1cd0cfba52f2df0e7cd08d7d93c50ad8
MD5 2e60e6eb1ebc7e8782008c40168e6d6c
BLAKE2b-256 4b8c16c191b3d12e325d60d752c8c09c8b677cdc543fb43cbdb327f614f2d95f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 750dd3c9dfcd3a09af02eb0d6cce91d6a8be202954f27a2af67e1cddab2f928e
MD5 dd3ddb5cda9452a798d9466100e8a0fa
BLAKE2b-256 c0335c633b4447bb9c93a903915258109c1ced9bd53a11a68a991fc8cbf8ac02

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 d7ac4f9ab356275b1bad1ae4a375da9cd8a214e376531af09fb10a21af4f9f2b
MD5 1bbc01ab8f21400c2ba6a419df27d5ee
BLAKE2b-256 f452eba54de17372bbe97543c8d6b97a5307e934b251637a5662fbe1bd089553

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 140b20b78b57ee659bbf0c93d5e8dfe1d9a8ef466636009c4ae73420a1e3fee6
MD5 6bb42378cc69f2371511806cda8ea06c
BLAKE2b-256 e70b58bc7f8c19664e52cf248bffc480824a59e1a488bfa0cdf5435a74faecb5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c0dc96dd7872b62290bd0df0e909666ba08972a139c313b211a29f43a167d0ff
MD5 84c52c14ff580c05f165c1c6003bb945
BLAKE2b-256 216b68e119c4996fde04b871139330ecd9a9ebe1b7fd7e57a4242ba4e7e79e9b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a97f4f887faca27895eea2dd3727522cafb55944ef64232aeda2ebb609c60ee3
MD5 e7251fb73ecfb5f6dec5193919973283
BLAKE2b-256 8bc4662583935c336015477454cc4216d55151a0bc9f0dbb5ac44b7156173837

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 51d4bce2cebd9ba314717336fdc1f3c0e04b62474116131b7703af725709044e
MD5 63df087d636fd89903bfd2307f9cb31d
BLAKE2b-256 a504395d38a67c18107306c940a2de7004b152985e2f26ecba4d761b0adb7e24

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 62331281f786d30cd69fe660537fc0944977efdc9658dbc5e181167ab7081217
MD5 41fbb313b81ed222946005f61024c2f0
BLAKE2b-256 10db65da7d199bd73a8846dc2e73f38441897c334ebf9fa7630332f257a0ba91

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a4746a2e94b71689cc668eecd97f8afa339c6fbc6ebd2845898fc86c5521e980
MD5 7c47775a9a0cd9529dd920ce9cc427ab
BLAKE2b-256 a51038072fdb2b75017a59bd556119f08bf49f3b2657b5ed2ac403ba88b347ca

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 139feb4b0e2e98e2a09da4f98a003ac5b50fc4924392c346797950fc027036a4
MD5 697fba3ccaa7f2e3774f8d1f2f7f5f38
BLAKE2b-256 bea3711a53890c9b0b3e957dad0c89080d7d8eccae1891b0cdf0a6f0c6fcc2f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 28baab042bc10e7b2d2493c30e42ddd5321e7e36f8722640595f9e37626025f5
MD5 a455b1d2602add00103a9c5e15cd56c3
BLAKE2b-256 47d3e0a0961676cd21bdbc484d5960cef1895d2dab47786e9758d36fb2f6e4fc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 0c44f083dd89474dbbe5d42a21e1bc0dc0bfd69c433a43fce1579a7a308ea5f5
MD5 4ec1286aa5f416d5f714f0e88641e81c
BLAKE2b-256 2a194bac02d65a51e588976d7903f8aaa706208e5059450d08ba4e3d81c2f587

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 cafb3e10bd485f66a3bd6f78623cd8e52a9396926ad03d396816d74a8e140d24
MD5 7c86f093c06f1b20fc56c4450760cec9
BLAKE2b-256 fb477549f47d7ace6e1f754cb2a883a58a6c1f987e7b507953e69ff1e4a29ef5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 823d024ded01f1a4518047db86d2e023fb8c4174c72bec21de3b018bd17dd586
MD5 5eca55939bd1c52781dcb0e3ebddeeee
BLAKE2b-256 bfa87ee46ad13023eac6b542300e4b3b9cdf1e553ebebc822dff345b04e82445

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 06c253700cb0044487ce103cd639a7992805824eac7036c08a59d0cf4c1531d1
MD5 9e06b11e8f5cad03a54e7f923d2858cb
BLAKE2b-256 8e070d09c453e1b718bbac56ed68d1a0b73d7eea39ee3e38463ae1d168fc15d5

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9ff5a3158463abe28222eb9c038ea47edba72065817b223c4c90b5d93cd25e9f
MD5 e7e51acebae5ff8de0fd051fecd3f54d
BLAKE2b-256 3e4d1386b10f74872ab9f12b5b086c13913bc706005e779dfec43dc93b5632e4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 66fdc1e2753e33d04737265219382680fa6c8718593c15bb56700514f16cdacc
MD5 1942533777ad677b2fc2ed644396a8ed
BLAKE2b-256 dee962d7b435b4a42a81b19de4b94ee24fb155ba23c1b1d7aae87a7fe6e513ee

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 d2dcebe456667e3e4e82e61faf5b2f78bb9d6f4041dbba9c94878e2ddabbcef6
MD5 0346c915983e155349673d916623bb54
BLAKE2b-256 6c180254a6abb3c3cc98d95c67d55fb4bff121182526f9f4b37b8847da3fda9e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9e738d8722242e2eb43da3972ae55bc61021c3797c23fc2918354c18fa950cc2
MD5 c0263d9e7984f9a684885ef5afc76889
BLAKE2b-256 7ef2229b504a8ccebeb150c61c129e9b1e8b27eb5f6797d2f1e69f814addb66a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 6433d9af4b8d649c3a222c2e58c9f3cf6b4799695a51873be5e90af9c76b3279
MD5 9b2a9152be5e7a4ea987c1b43fce91da
BLAKE2b-256 331ec576ea655ef8cccc991da93ff42fbcf26c7a479ffd63f24f581ce019ed17

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3ebbafaa5824abbddcda6ff9def766d7c1813de4714e806587e5b0693cad0bf9
MD5 dbb4cae5d85a153d1c3aeb37e6e4332c
BLAKE2b-256 19bc37da54d55de1d286b6f07940272f691007a6aa7130c50f51d9e3de04d4d4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 cf1552dce83966b213cce195fec97c2accde0c6c8ea4106aa2d6f2a1e0a96b1a
MD5 fa069ce23aac168161689704c69ed6bb
BLAKE2b-256 81199db826c6524e06e7239e2f275e22c46c15c71cc81dabd74abd7340f92719

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 954b7fa57673cd31a5cec4f665a5f1e2fd02d2080a455bd7a451631526bb4a46
MD5 b5f3e55ee4cb1e06515caf0abdf3c9e5
BLAKE2b-256 0052acbbf4e12dbf87f33756d6ff7967cadb7efd4ef5c8f6a613488e39c42114

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 6f500ad175193d15cb2755b060fb398459c5842fadd1d082e96925113775dc8e
MD5 d38e77a60ed946d6b82521b72ba10a9e
BLAKE2b-256 1868d3c058962c9e2f05d5518b05d3939ce66fcbf559f26fd797975dd43a3ad3

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 8ed376584d406813dcaa6bb137bb57d9a959c2b37e75bd0ce36ce848c49daa0e
MD5 76e2bb80e3249e2cf24f893ed0cb00a9
BLAKE2b-256 31fe1db453b9d470c9676d8c838194dbc3065958b2734f6e59261c25a3d42c85

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 faa45ba8980a18a9e0560b32b2839e63784b00c218aaa2d579fc1f29198c0309
MD5 665f5e4615c05371ef6db9720eca22ae
BLAKE2b-256 9c684e549e2c3fd60d0821ca7072d4a392123ab3538cdb46d0eba31a09d555c2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d729d6a91eb18550eec51d8ea3eb0b0dfaf2da84cad835ff98eae392752e4ecf
MD5 6faf83bcdd8df53de996058593966b29
BLAKE2b-256 d2ff7829a3360ebe9be4fb5dd6535cca3822b39eb00f20feb832ab7e4e46b00d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 edc391a8afccb91f9681f618270909e11a08f17923d5a1ca961f6530996864c1
MD5 4429d948202512cb6613cb30b6b07e10
BLAKE2b-256 43d3ad04f36c5c476d2090cabf8effd8593007fa261d839944349bfd720eea2d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 87f9c14d84c1c60a2238087d34059f3f0cc5e18a36e753f85a5df5b62060ded1
MD5 3c8d0572abb44de4ff53907764b99bfd
BLAKE2b-256 7cf5d9191b422b8eab553e9c22d858818bd96f23bb6b6e12008175e80cc07bb2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5779b49fa7bbacc047586268d8c858d46d5b401f769a2ecfeb6237e12ca2809f
MD5 966c9f6c03f2a0792ed2a4eaf1c8a642
BLAKE2b-256 2d39c51bcaa8138ae2abb39a0991e889bbd3b0c332db7e067256d9e94e4c77e6

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5a1c9476aca2d573f31dfae346deb922c020c38f1bbaea494984757b8ec191a1
MD5 db03715ad032fbdf449f6a1a34cf8b18
BLAKE2b-256 84da8e347bfe152415a16304b1abba7c72cad9c20e1b4b1083d5094e175a2981

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 564db91bd53f62db7705f6c0273bd2297090dfb0c09f5edf3e3b7a6c963cd50c
MD5 a436744c899c3535d1792db50e688260
BLAKE2b-256 78f8e5ecdd8b131eea9c194850331e72cb1def2ad48967cde81f4b6aba3d1aab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c4baa84b224bfa9f853e83e9120b3a8c2d282ff7b52ebb87b9f4e1e922573fc5
MD5 c35c024cb6433f1d16a548f03a14a996
BLAKE2b-256 0075de0097d23e945de97b7717150503cb4ff5e580011ec9fa5b9c7517554abc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6ab94d2257364089a290edb1513774acf28938023698e02de3e1a0fbc47eb99a
MD5 c673874c86c5f7d3818d8a4b726e4623
BLAKE2b-256 2467795f945e9564d94eafa1c7a81a1d16b0bb8d5782cc7c896894a7d38aeae6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 6edf9dabe427ab921a4df3d73ad72a4d31771faa162c9419f3d263ec71e50f45
MD5 d39c4f08807044a96d7a90cb2c394f7e
BLAKE2b-256 34d6bc88ad93d0806315f2d9860477d319a182ad041c52537a8c52e500f546e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 277162fe63286dbdc1bc6cb7162541fa4ad557381c8e25cf43b242b62abae0e9
MD5 eeedb22388cf824d7bdfd642656be016
BLAKE2b-256 7cb0a1a40330aaaba015cd85f96f11a630f0c7ae876766d0e64229e84a0abd00

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 789822f9cd59036fa0172af06f49f34b5c3208591ff5e36d5f3639187370da9e
MD5 41983f09388a2c9098d4b5fd999b928f
BLAKE2b-256 2390ffc29e92820b785e06d1c1ba97404b88f3d21910714bf7d0815d0c64889e

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 882267541e5cd6fa426b664a6c7e59bca409fddc46df6a5b8c29d114270f7177
MD5 a338337f28248cd1dc8854b4e3eac792
BLAKE2b-256 8536c805c2e8b01d215cc86c14556e8ee242a20176253602fa49225b981f504d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0e22c4e2a9dc4f987a28b7ad0df588843d2eaceeac63d03da92ec4280b29c9f8
MD5 041c40201a994fea9ca03616609f7569
BLAKE2b-256 d8a6f8a95095ec6fa22f05ab023268971f6210685b0fdc9a43cd1f5bd1996378

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 9d8a21652926d9487cb7f71755150fa6198e2eeb0903390590743ed671780f43
MD5 b0217e41b3662a27d83103c4c7857d53
BLAKE2b-256 19cd832a241c9c5576a52246f9a839a162e0b116eb7febd2e82d7ce6cbe163e5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 0659a3a6efcbafafff4195417d04235a1fdc37ead63e932b8889c705b080bb05
MD5 63ca6b11e7b53db903259505fefb1ed0
BLAKE2b-256 30f2387e1bfa1dcd2c0d425c0086372c45d1b9a47ce737b9b44b0e101361ca2c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3eaa25bb84be0ce9c389076aec1493971e05f267bfdf20bb02f857cc5ed7f61c
MD5 4bbb539f4490f278d11fd59120729239
BLAKE2b-256 0f7ba561c7c71cf9ed0757a456442cda47cb9becfcb7a87986317e9179de5c5d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a262e68869c211a9e8d6ccc6d9a195cb883cc7b7850091f029ad533938859d68
MD5 e70bfa1c11e0ee17746dc35f1cc06b81
BLAKE2b-256 8d35a85b89db26a5969808d4423720f50f20a4ae99b57dbddbb947e938b5a1e6

See more details on using hashes here.

File details

Details for the file stringzilla-3.6.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.6.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e1f01668c01bd177b011421a581491ba8c4ee792e0f96f9498b4f43864996270
MD5 506b05809d655a9d29a6a9862853de68
BLAKE2b-256 552814d93b05b64f5e8b53a2c4643847044b80436f8375c01fdebab3792555b3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 127a4f1d5f7a18873260cc9d810b7b5efe4cf6182331088383ed5e2d94e5d519
MD5 f9252d4a844eb16adda4580d6cd24195
BLAKE2b-256 64f7564536729849f3a34a19d747dce4662ab0645060f7f8fd1b77026836894e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9e3cc99c0f19420b70a3700a8a9e0fd2ac04f8ec6548e814a5642e54cee3b85c
MD5 523aff5d6c3754f69dc1e899704accfd
BLAKE2b-256 c5e6f63df9e4331d5d1607b804063eeaa00d2b1f263f4e216f80d397337f0017

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8633f4ccfef601d7845ec4e107a18e61675a0a787c49fbe1096106818edc3136
MD5 68973c5bcfef575e700a2814fbc16029
BLAKE2b-256 783bc0b4b2d64a928fcac52a9f65c4a5e37017aa6f77b843983e9ee471720bee

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 af73bdcfba80485aeedfd26d63537b12e39daeb866e57d3eb60fc5b891b46761
MD5 682cb91a1f7f98def286d4a0263e19e8
BLAKE2b-256 7153d262630870afaf08107c3b36321e9a8be44b3d15050b93d16c94327b8109

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.6.1-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 fe3014f5b7d6b5c1f9e44aaffbd707ef7c049fc2346aec397f0ae4b487c66e0b
MD5 c525575eb36aee1efefc7743e3ee60a5
BLAKE2b-256 da17d649bb213248cd13b7734c8137c9e3fd5a05fb3d19abb3968c94f326a1c1

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