summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.txt308
-rw-r--r--GNUmakefile22
-rw-r--r--Makefile20
-rw-r--r--README.html117
-rw-r--r--README.txt10
-rw-r--r--test.cc270
-rw-r--r--test/src/main.c106
-rw-r--r--test/src/test/bool.i9
-rw-r--r--test/src/test/cmp.i11
-rw-r--r--test/src/test/fndbyte.i33
-rw-r--r--test/src/test/fndchr.i12
-rw-r--r--test/src/test/foreach.i23
-rw-r--r--test/src/test/memcat.i43
-rw-r--r--test/src/test/memcmp.i26
-rw-r--r--test/src/test/memcp.i18
-rw-r--r--test/src/test/memeq.i24
-rw-r--r--test/src/test/memfill.i23
-rw-r--r--test/src/test/memgen.i29
-rw-r--r--test/src/test/nullptr.i7
-rw-r--r--test/src/test/strcat.i19
-rw-r--r--test/src/test/strcp.i42
-rw-r--r--test/src/test/streq.i17
-rw-r--r--test/src/test/strfill.i18
-rw-r--r--test/src/test/strlen.i13
-rw-r--r--test/src/test/utf8dec.i43
-rw-r--r--test/src/test/utf8enc.i42
-rw-r--r--test/src/test/win1252dec.i76
-rw-r--r--test/src/test/win1252enc.i76
-rw-r--r--zap/GNUmakefile71
-rw-r--r--zap/Makefile64
-rw-r--r--zap/include-private/zap/priv.h (renamed from zap/include-priv/zap/priv.h)12
-rw-r--r--zap/include/zap/base.h25
-rw-r--r--zap/include/zap/bs.h43
-rw-r--r--zap/include/zap/math.h94
-rw-r--r--zap/include/zap/mem.h61
-rw-r--r--zap/src/abs.c96
-rw-r--r--zap/src/fastimpl.c12
-rw-r--r--zap/src/fma.c171
-rw-r--r--zap/src/fndbyte.c80
-rw-r--r--zap/src/fndchr.c73
-rw-r--r--zap/src/mem/fndbyte.S59
-rw-r--r--zap/src/mem/fndchr.S57
-rw-r--r--zap/src/mem/foreach.S71
-rw-r--r--zap/src/mem/memcat.c (renamed from zap/src/strdup.c)11
-rw-r--r--zap/src/mem/memcmp.c (renamed from zap/src/memcmp.c)8
-rw-r--r--zap/src/mem/memcp.S107
-rw-r--r--zap/src/mem/memeq.S82
-rw-r--r--zap/src/mem/memfill.S45
-rw-r--r--zap/src/mem/memgen.c25
-rw-r--r--zap/src/mem/strcat.c (renamed from zap/src/foreach.c)11
-rw-r--r--zap/src/mem/strcmp.c (renamed from zap/src/strcmp.c)6
-rw-r--r--zap/src/mem/strcp.S53
-rw-r--r--zap/src/mem/streq.S57
-rw-r--r--zap/src/mem/strfill.S48
-rw-r--r--zap/src/mem/strlen.S46
-rw-r--r--zap/src/mem/utf8dec.c51
-rw-r--r--zap/src/mem/utf8declen.c35
-rw-r--r--zap/src/mem/utf8enc.S152
-rw-r--r--zap/src/mem/utf8enclen.S80
-rw-r--r--zap/src/mem/win1252dec.c111
-rw-r--r--zap/src/mem/win1252enc.c113
-rw-r--r--zap/src/memcpy.c143
-rw-r--r--zap/src/memdup.c24
-rw-r--r--zap/src/memeq.c112
-rw-r--r--zap/src/memfill.c60
-rw-r--r--zap/src/strcpy.c71
-rw-r--r--zap/src/streq.c83
-rw-r--r--zap/src/strfill.c13
-rw-r--r--zap/src/strlen.c58
70 files changed, 2261 insertions, 1792 deletions
diff --git a/.gitignore b/.gitignore
index ca10573..92965f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
*.a
*.o
-/test
+/test/test
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 6c1910f..83ace3c 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,141 +1,167 @@
-| F
-
-- Remove type specifier from version macro;
-- Add mathematical functions abs and fma;
-- Update documentation;
-- Remove nothrw attribute from foreach;
-- Remove UB from foreach test;
-- Fix parameter mismatch in foreach test;
-- Use unsigned char instead of uint_least8_t;
-- Remove unnecessary casts;
-- Add new headers: 'zap/math.h' (for mathematical functions), 'zap/mem.h' (for memory sequence functions);
-- Restructure makefile;
-- Fix not using INT_LEAST8_MAX and INT_LEAST8_MIN instead of INT8_MAX and INT8_MIN;
-- Remove '/build' from gitignore;
-
-| E
-
-- Fix incorrect version number;
-
-| D
-
-- Add function foreach: Run function on each element;
-- Use directive globl instead of global in assembly;
-- Use SIZE_MAX instead of negative one;
-- Remove asflags from makefile;
-- Don't require GNU Make;
-- Change the type of fndbyte: (size_t (void const *,size_t,uint_least8_t)) => (size_t (void const *,size_t,unsigned char));
-- Change the type of memfill: (void (void *,size_t,uint_least8_t)) => (void (void *,size_t,unsigned char));
-- Update readme (add documentation for some functions);
-- Update susinfo symbol names;
-
-| C
-
-- Fix install target;
-- Remove type literals;
-
-| B
-
-- memdup: Use sus_unlikely instead of __builtin_expect;
-- Rename project to zap (from rgo);
-- Remove global license file (useless with MPL);
-- Migrate test to C++ (for reasons which will be revealed later);
-- Restructure headers;
-- Add include guards to the private header;
-- Add attribute useret to functions;
-- Require GNU Make;
-- Compile position independent code;
-- Update readme;
-
-| A
-
-- Installation script: Create installation directories if they don't already exist;
-- Don't use susinfo types;
-- Remove declarations for getbinver;
-- Add memcmp, strcmp;
-- Update makefile;
-- Reimplement fastimpl as a global variable;
-- Change type of fastimpl (uint_least8_t => _Bool);
-- Change the return types of memeq and streq (uint_least8_t => _Bool);
-- Enable compilation warnings;
-- Add type literals (like those from susinfo);
-- Use *int_leastN_t instead of *intN_t;
-- Remove restrict-qualifications;
-- Remove C++ version of memdup;
-
-| 9
-
-- Fix readme not reflecting that we now support all platforms;
-- Rename the 'Building' section in the readme to 'Building & Installing';
-
-| 8
-
-- Use susinfo;
-- Implement algorithms in C (with inline assembly on supported platforms);
-- Add comments;
-- Fix strcpy counting the null-terminator;
-- Fix strcpy taking a pointer-to-const as the output;
-- Implement strcpy, streq in IA-32;
-- Optimise streq: Only use the lower eight bytes for the return value;
-- Optimise strlen: Use fewer registers;
-- Fix memfill taking a pointer-to-const as the output;
-- Fix strfill taking a pointer-to-const as the output;
-- Update readme;
-- Add private header;
-- Remove assembly-specific version macro;
-
-| 7
-
-- Relicense under MPL2;
-- Instead of throwing an error, define a macro when the header is included on an unsupported platform;
-
-| 6
-
-- Remove stupid debug return from memcpy;
-
-| 5
-
-- Fix compile flags not indicating new relative header location;
-
-| 4
-
-- Add install target to makefile;
-- Merge makefiles;
-
-| 3
-
-- Enable compiler optimisations;
-- Optimise memfill;
-- Optimise memcpy: Use movdqu instead of movups (AMD64, i386 SSE2), add 256-bit copy (AMD64 AVX, i386 AVX);
-- Update makefile;
-- Implement fndbyte, fndchr, strlen in IA-32;
-- Fix bug in test;
-- Update readme;
-- Add new planned architectures: Motorola 68000, Power ISA, RISC-V, Sparc;
-
-| 2
-
-- Fix target purge in makefile not being labeled phony;
-- Add machien architecture check in header;
-- Implement memcpy, memeq, memfill in IA-32;
-- Fix some incorrect comments;
-- Use a different register order for temporaries and optimise register usage;
-- Fix bug in memeq: Should jump if zero, not if equal;
-- Update readme;
-
-| 1
-
-- Fix indentation in license notices;
-- Fix incorrect declaration for rgo_strcpy, rgo_streq;
-- Implement fndbyte,memeq,strcpy,streq;
-- Add new tests;
-- Fix bug in memcpy: Should jump if zero, not if equal;
-- Remove declaration for rgo_memcmp;
-- Add macro rgo_ver, defined to the current version number;
-- Add assembly declaration for rgo_fndchr, rgo_fndbyte;
-- Fix some incorrect comments;
-- Use movups instead of movdqu in memcpy;
-
-| 0
-
-- Initial.
+# 10.0
+
+* Update readme;
+* Fix typo in makefile;
+* Include headers inside header guard;
+* Remove unneeded includes;
+* Rename private include directory: 'include-priv' => 'include-private';
+* Remove assembly support from (public) headers;
+* Remove fastimpl (assembly algorithms are still used);
+* Add copyright/license notices to makefiles;
+* Seperate sources according to header;
+* Require GNU Make;
+* Move (most) C-implementations into a seperate project: zapx;
+* Restructure assembly;
+* Implement strfill in assembly;
+* Use new versioning system (api.ver);
+* Remove documentation;
+* Add features from latest standard;
+* Temporarily remove i386 implementations;
+* Update readme format;
+* Update changelog format;
+* Remove impl;
+* Remove stdver;
+* Readd ver;
+* Use git tagging;
+
+# F
+
+* Remove type specifier from version macro;
+* Add mathematical functions abs and fma;
+* Update documentation;
+* Remove nothrw attribute from foreach;
+* Remove UB from foreach test;
+* Fix parameter mismatch in foreach test;
+* Use unsigned char instead of uint_least8_t;
+* Remove unnecessary casts;
+* Add new headers: 'zap/math.h' (for mathematical functions), 'zap/mem.h' (for memory sequence functions);
+* Restructure makefile;
+* Fix not using INT_LEAST8_MAX and INT_LEAST8_MIN instead of INT8_MAX and INT8_MIN;
+* Remove '/build' from gitignore;
+
+# E
+
+* Fix incorrect version number;
+
+# D
+
+* Add function foreach: Run function on each element;
+* Use directive globl instead of global in assembly;
+* Use SIZE_MAX instead of negative one;
+* Remove asflags from makefile;
+* Don't require GNU Make;
+* Change the type of fndbyte: (size_t (void const *,size_t,uint_least8_t)) => (size_t (void const *,size_t,unsigned char));
+* Change the type of memfill: (void (void *,size_t,uint_least8_t)) => (void (void *,size_t,unsigned char));
+* Update readme (add documentation for some functions);
+* Update susinfo symbol names;
+
+# C
+
+* Fix install target;
+* Remove type literals;
+
+# B
+
+* memdup: Use sus_unlikely instead of __builtin_expect;
+* Rename project to zap (from rgo);
+* Remove global license file (useless with MPL);
+* Migrate test to C++ (for reasons which will be revealed later);
+* Restructure headers;
+* Add include guards to the private header;
+* Add attribute useret to functions;
+* Require GNU Make;
+* Compile position independent code;
+* Update readme;
+
+# A
+
+* Installation script: Create installation directories if they don't already exist;
+* Don't use susinfo types;
+* Remove declarations for getbinver;
+* Add memcmp, strcmp;
+* Update makefile;
+* Reimplement fastimpl as a global variable;
+* Change type of fastimpl (uint_least8_t => _Bool);
+* Change the return types of memeq and streq (uint_least8_t => _Bool);
+* Enable compilation warnings;
+* Add type literals (like those from susinfo);
+* Use *int_leastN_t instead of *intN_t;
+* Remove restrict-qualifications;
+* Remove C++ version of memdup;
+
+# 9
+
+* Fix readme not reflecting that we now support all platforms;
+* Rename the 'Building' section in the readme to 'Building & Installing';
+
+# 8
+
+* Use susinfo;
+* Implement algorithms in C (with inline assembly on supported platforms);
+* Add comments;
+* Fix strcpy counting the null-terminator;
+* Fix strcpy taking a pointer-to-const as the output;
+* Implement strcpy, streq in IA-32;
+* Optimise streq: Only use the lower eight bytes for the return value;
+* Optimise strlen: Use fewer registers;
+* Fix memfill taking a pointer-to-const as the output;
+* Fix strfill taking a pointer-to-const as the output;
+* Update readme;
+* Add private header;
+* Remove assembly-specific version macro;
+
+# 7
+
+* Relicense under MPL2;
+* Instead of throwing an error, define a macro when the header is included on an unsupported platform;
+
+# 6
+
+* Remove stupid debug return from memcpy;
+
+# 5
+
+* Fix compile flags not indicating new relative header location;
+
+# 4
+
+* Add install target to makefile;
+* Merge makefiles;
+
+# 3
+
+* Enable compiler optimisations;
+* Optimise memfill;
+* Optimise memcpy: Use movdqu instead of movups (AMD64, i386 SSE2), add 256-bit copy (AMD64 AVX, i386 AVX);
+* Update makefile;
+* Implement fndbyte, fndchr, strlen in IA-32;
+* Fix bug in test;
+* Update readme;
+* Add new planned architectures: Motorola 68000, Power ISA, RISC-V, Sparc;
+
+# 2
+
+* Fix target purge in makefile not being labeled phony;
+* Add machien architecture check in header;
+* Implement memcpy, memeq, memfill in IA-32;
+* Fix some incorrect comments;
+* Use a different register order for temporaries and optimise register usage;
+* Fix bug in memeq: Should jump if zero, not if equal;
+* Update readme;
+
+# 1
+
+* Fix indentation in license notices;
+* Fix incorrect declaration for rgo_strcpy, rgo_streq;
+* Implement fndbyte,memeq,strcpy,streq;
+* Add new tests;
+* Fix bug in memcpy: Should jump if zero, not if equal;
+* Remove declaration for rgo_memcmp;
+* Add macro rgo_ver, defined to the current version number;
+* Add assembly declaration for rgo_fndchr, rgo_fndbyte;
+* Fix some incorrect comments;
+* Use movups instead of movdqu in memcpy;
+
+# 0
+
+* Initial.
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 0000000..36105b5
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,22 @@
+# Copyright 2022 Gabriel Jensen.
+# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+# If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+LIBZAP = zap/libzap.a
+
+.PHONY: clean install purge
+
+$(LIBZAP):
+ $(MAKE) -Czap
+
+install: $(LIBZAP)
+ mkdir -pm755 "$(HDRDIR)/zap"
+ mkdir -pm755 "$(LIBDIR)"
+ install -m644 "zap/include/zap/"*".h" "$(HDRDIR)/zap"
+ install -m755 "$(LIBZAP)" "$(LIBDIR)"
+
+clean:
+ $(MAKE) -Czap clean
+
+purge:
+ $(MAKE) -Czap purge
diff --git a/Makefile b/Makefile
deleted file mode 100644
index f4d59b1..0000000
--- a/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-LIBZAP = zap/libzap.a
-
-.PHONY: clean install purge zap
-
-zap:
- $(MAKE) -Czap
-
-install: zap
- mkdir -pm755 $(HDRDIR)/zap
- mkdir -pm755 $(LIBDIR)
- install -Dm644 zap/include/zap/base.h $(HDRDIR)/zap
- install -Dm644 zap/include/zap/math.h $(HDRDIR)/zap
- install -Dm644 zap/include/zap/mem.h $(HDRDIR)/zap
- install -Dm755 $(LIBZAP) $(LIBDIR)
-
-clean:
- $(MAKE) -Czap clean
-
-purge:
- $(MAKE) -Czap purge
diff --git a/README.html b/README.html
deleted file mode 100644
index 1a08610..0000000
--- a/README.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE html>
-<html>
- <h1>zap</h1>
- <p>A library for algorithmics.</p>
- <p><i>Note: This library is still in it's early stages and is NOT anywhere near being fully optimised.</i></p>
- <br />
- <h2>Building and installation</h2>
- <p>The provided makefile has been tested to work with both GNU Make and BSD Make.</p>
- <p>The default target builds the static library file (located at <i>zap/libzap.a</i>). The target <i>clean</i> removes object files, whilst <i>purge</i> removes object files and the static library file.</p>
- <p>Currently, zap doesn't support being compiled as a shared library out of the box, but the makefile could be modified to allow this.</p>
- <p>The <i>install</i> target installs the headers to <i>$(HDRDIR)</i> and the library file to <i>$(LIBDIR)</i>.</p>
- <p>Instructions for building the test program may be found on the first line of <i>test.c</i>.</p>
- <h2>Documentation</h2>
- <h3>abs</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/math.h&gt<br />signed char zap_abs_c(signed char val);<br />int zap_abs_i(int val);<br />long zap_abs_l(long val);<br />long long zap_abs_ll(long long val);<br />short zap_abs_s(short val);</code>
- <h4>Description</h4>
- <p>Returns the absolute value of <i>val</i>.</p>
- <br />
- <h3>fma</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/math.h&gt<br />signed char zap_fma_c(signed char a,signed char b,signed char c);<br/>int zap_fma_i(int a,int b,int c);<br/>long zap_fma_l(long a,long b,long c);<br/>long long zap_fma_ll(long long a,long long b,long long c);<br/>short zap_fma_s(short a,short b,short c);<br/>unsigned char zap_fma_uc(unsigned char a,unsigned char b,unsigned char c);<br/>unsigned int zap_fma_ui(unsigned int a,unsigned int b,unsigned int c);<br/>unsigned long zap_fma_ul( unsigned long a,unsigned long b,unsigned long c);<br/>unsigned long long zap_fma_ull(unsigned long long a,unsigned long long b,unsigned long long c);<br/>unsigned short zap_fma_us( unsigned short a,unsigned short b,unsigned short c);</code>
- <h4>Description</h4>
- <p>Returns the the fused multiply-add of <i>a</i>, <i>b</i>, and <i>c</i>.</p>
- <br />
- <h3>fndbyte</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />size_t zap_fndbtyte(void const * ptr,size_t num,unsigned char byte);</code>
- <h4>Description</h4>
- <p>Searches for the byte-value <i>byte</i> in the array pointed to by <i>ptr</i> within the bounds of <i>num</i>.</p>
- <p>If <i>ptr</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes in the array, the behaviour is undefined.</p>
- <p>If the byte-value is found within the domain, the position of it's first occurrence (starting at zero) is returned. Otherwise, <i>SIZE_MAX</i> is returned.</p>
- <br />
- <h3>fndchr</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />size_t zap_fndchr(char const * str,char chr);</code>
- <h4>Description</h4>
- <p>Searches for the character <i>chr</i> in the string <i>str</i>.</p>
- <p>If the character is found in the string, the position of it's first occurrence (starting at zero) is returned. Otherwise, <i>SIZE_MAX</i> is returned.</p>
- <p>If <i>str</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
- <br />
- <h3>foreach</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />void zap_foreach(void * ptr,size_t sz,size_t num,void (* fn)(void *),void * * rem);</code>
- <h4>Description</h4>
- <p>Iterates through the array pointed to by <i>ptr</i>, invoking the function <i>fn</i> with a pointer to the current element. Each pointer value after the first is equal to the previous plus <i>sz</i>.</p>
- <p>If the pointed-to object of <i>rem</i> is not a null pointer, the iterations are started from that address. If <i>fn</i> throws an exception, the current position is written to the pointed-to object of <i>rem</i> (unless <i>rem</i> is a null pointer) and <i>foreach</i> returns the control-flow to the caller via this exception.</p>
- <p>If the expression <code>(sz * num)</code> is not a valid object size, the behaviour is undefined.</p>
- <p>If <i>fn</i> is not a valid pointer to a function with C language linkage, the behaviour is undefined.</p>
- <p>If <i>rem</i> is not a null pointer and the pointed-to object is not initialised to <i>NULL</i> before the call to <i>foreach</i>, the behaviour is undefined.</p>
- <br />
- <h3>memcmp</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />int_least8_t zap_memcmp(void const * lptr,size_t num,void const * rptr);</code>
- <h4>Description</h4>
- <p>Compares <i>num</i>-bytes of the arrays pointed to by <i>lptr</i> and <i>rptr</i>.</p>
- <p>The returned value is determined by the first byte found to be different in the two arrays. If the byte has a larger value in <i>lptr</i>, a negative (less than zero) value is returned. If it's the other way, a positive (greater than zero) value is returned. Otherwise (the arrays where represented the same), zero is returned.</p>
- <p>If <i>lptr</i> or <i>rptr</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
- <br />
- <h3>memcpy</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />void zap_memcpy(void const * in,size_t num,void * out);</code>
- <h4>Description</h4>
- <p>Copies <i>num</i>-bytes from the buffer pointed to by <i>in</i> into the same relative position in the buffer pointer to by <i>out</i>.</p>
- <p>If <i>in</i> or <i>out</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
- <br />
- <h3>memdup</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />void * zap_memdup(void const * ptr,size_t num);</code>
- <h4>Description</h4>
- <p>Copies <i>num</i>-bytes from the array pointed to by <i>ptr</i> into a newly-allocated array. The new array is allocated by <i>malloc</i>.</p>
- <p>The returned value is a pointer to the new array.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes in the array, the behaviour is undefined.</p>
- <br />
- <h3>memeq</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />bool zap_memeq(void const * lptr,size_t num,void * rptr);</code>
- <h4>Description</h4>
- <p>Checks <i>num</i>-bytes of the buffers pointed to by <i>lptr</i> and <i>rptr</i> for equality.</p>
- <p>If any two bytes are found to be different in the two buffers, false is returned. Otherwise, true is returned.</p>
- <p>If <i>lptr</i> or <i>rptr</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
- <br />
- <h3>memfill</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />void zap_memfill(void const * ptr,size_t num,unsigned char byte);</code>
- <h4>Description</h4>
- <p>Fills <i>num</i>-bytes of the buffer pointed to by <i>ptr</i> with the representation of <i>byte</i>.</p>
- <p>If <i>ptr</i> is not a valid pointer to an array, the behaviour is undefined.</p>
- <p>If <i>num</i> is larger (but not smaller) than the number of bytes of in the array, the behaviour is undefined.</p>
- <br />
- <h3>streq</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />bool zap_streq(char const * lstr,char const * rstr);</code>
- <h4>Description</h4>
- <p>Checks the equality of the strings <i>lstr</i> and <i>rstr</i>.</p>
- <p>If one of the strings has a length different from the other, or if any character in the two strings is different from the other (at the same offset), true is returned. Otherwise, false is returned.</p>
- <p>If <i>lstr</i> or <i>rstr</i> (or both) are not valid pointers to null-terminated strings, the behaviour is undefined.</p>
- <br />
- <h3>strfill</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />void zap_strfill(char * str,char chr);</code>
- <h4>Description</h4>
- <p>Writes the character <i>chr</i> to every valid position in the string <i>str</i>, excluding that of the null-terminator.</p>
- <p>If <i>str</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
- <br />
- <h3>strlen</h3>
- <h4>Synopsis</h4>
- <code>#include &ltzap/mem.h&gt<br />size_t zap_strlen(char const * str);</code>
- <h4>Description</h4>
- <p>Counts the number of characters in the string <i>str</i>.</p>
- <p>Returns the number of characters (excluding the null-terminator) in the string.</p>
- <p>If <i>str</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
-</html> \ No newline at end of file
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..80614de
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,10 @@
+ZAP
+
+This repository contains the standard paper (stdzap), the official, "optimised" implementation (zap), and the official reference implementation (zapx).
+
+# Building and installation
+
+zap uses GNU Make for building:
+The default target builds the static library file (located at 'zap/libzapq.a'). The target 'clean' removes object files, whilst 'purge' removes all artefacts.
+Currently, zap doesn't support being compiled as a shared library out of the box, but the makefile could be modified to allow this.
+The 'install' target installs the headers to '$(HDRDIR)' and the library file to '$(LIBDIR)'. Both values need to be set when invoking the makefile (like via `make HDRDIR=/usr/include LIBDIR=/usr/lib`), or by modifying the makefiles directly.
diff --git a/test.cc b/test.cc
deleted file mode 100644
index 521d556..0000000
--- a/test.cc
+++ /dev/null
@@ -1,270 +0,0 @@
-/* c++ -Izap/include -Lzap -otest test.cc -lzap */
-
-#include <cassert>
-#include <cinttypes>
-#include <cstddef>
-#include <cstdint>
-#include <cstdio>
-#include <stdexcept>
-#include <zap/math.h>
-#include <zap/mem.h>
-
-extern "C" auto zap_test_foreachfn(void * const _ptr) -> void { /* This function is passed to foreach, which requires C-linkage function pointers. I tried to overload the function to also accept C++-linkage function pointers, but that only made GCC moan. */
- auto const ptr {static_cast<int *>(_ptr)};
- auto val {*ptr};
- if (val == 0x45) {throw ::std::domain_error {"Damn!"};}
- val %= 0x2;
- *ptr = val;
-}
-
-int main(void) {
- ::std::fprintf(stderr,"zap test\n");
- ::std::fprintf(stderr,"arch: %s\n",sus_archstr);
- ::std::fprintf(stderr,"fast: %s\n",::zap_fastimpl ? "yes" : "no");
- ::std::fprintf(stderr,"\n");
- {
- {
- auto val {::zap_abs_c(-0x5D)};
- ::std::fprintf(stderr,"val: %hhi\n",val);
- assert(val == 0x5D);
- }
- {
- auto val {::zap_abs_i(-0xEF4)};
- ::std::fprintf(stderr,"val: %i\n",val);
- assert(val == 0xEF4);
- }
- {
- auto val {::zap_abs_l(-0x6666E67B)};
- ::std::fprintf(stderr,"val: %li\n",val);
- assert(val == 0x6666E67B);
- }
- {
- auto val {::zap_abs_ll(-0x7C91A4B244F0DC99)};
- ::std::fprintf(stderr,"val: %lli\n",val);
- assert(val == 0x7C91A4B244F0DC99);
- }
- {
- auto val {::zap_abs_s(-0xDC9)};
- ::std::fprintf(stderr,"val: %i\n",val);
- assert(val == 0xDC9);
- }
- }
- ::std::fprintf(stderr,"\n");
- {
- { /* Largest number for each signed parameter: (floor(cbrt(2^(x-1)-1))) */
- auto val {::zap_fma_c(0x5,0x2,0x2)};
- ::std::fprintf(stderr,"val: %hhi\n",val);
- assert(val == 0x9);
- }
- {
- auto val {::zap_fma_i(0x29,0x4AD,0x453)};
- ::std::fprintf(stderr,"val: %i\n",val);
- assert(val == 0x143840);
- }
- {
- auto val {::zap_fma_l(0x1BAA11,0x361DA,0x17462F)};
- ::std::fprintf(stderr,"val: %li\n",val);
- assert(val == 0x4EB8123D17);
- }
- {
- auto val {::zap_fma_ll(0x45,0x60,0x1A4)};
- ::std::fprintf(stderr,"val: %lli\n",val);
- assert(val == 0x9DC5);
- }
- {
- auto val {::zap_fma_s(0x7,0xE,0x1D)};
- ::std::fprintf(stderr,"val: %i\n",val);
- assert(val == 0x19D);
- }
- { /* Largest number for each unsigned parameter: (floor(cbrt(2^x-1))) */
- auto val {::zap_fma_uc(0x6u,0x6u,0x3u)};
- ::std::fprintf(stderr,"val: %hhu\n",val);
- assert(val == 0x18u);
- }
- {
- auto val {::zap_fma_ui(0x14u,0x17u,0x3u)};
- ::std::fprintf(stderr,"val: %u\n",val);
- assert(val == 0x59);
- }
- {
- auto val {::zap_fma_ul(0x5AAu,0x412u,0x16Du)};
- ::std::fprintf(stderr,"val: %lu\n",val);
- assert(val == 0x5D354u);
- }
- {
- auto val {::zap_fma_ull(0x10EFC7u,0x19FB63u,0x1133259u)};
- ::std::fprintf(stderr,"val: %llu\n",val);
- assert(val == 0x1BEE278BAB32u);
- }
- {
- auto val {::zap_fma_us(0x23u,0x19u,0x1Cu)};
- ::std::fprintf(stderr,"val: %u\n",val);
- assert(val == 0x2DF);
- }
- }
- ::std::fprintf(stderr,"\n");
- {
- constexpr ::std::size_t arrsz {0x8u};
- ::std::uint_least64_t arr0[arrsz] {0x0u};
- ::zap_memfill(arr0,arrsz * sizeof (::std::uint_least64_t),0x0u);
- ::std::fprintf(stderr,"arr0[0]: %" PRIXLEAST64 "\n",arr0[0x0u]);
- ::std::fprintf(stderr,"arr0[1]: %" PRIXLEAST64 "\n",arr0[0x1u]);
- ::std::fprintf(stderr,"arr0[2]: %" PRIXLEAST64 "\n",arr0[0x2u]);
- ::std::fprintf(stderr,"arr0[3]: %" PRIXLEAST64 "\n",arr0[0x3u]);
- ::std::fprintf(stderr,"arr0[4]: %" PRIXLEAST64 "\n",arr0[0x4u]);
- ::std::fprintf(stderr,"arr0[5]: %" PRIXLEAST64 "\n",arr0[0x5u]);
- ::std::fprintf(stderr,"arr0[6]: %" PRIXLEAST64 "\n",arr0[0x6u]);
- assert(arr0[0x0u] == 0x0u);
- assert(arr0[0x1u] == 0x0u);
- assert(arr0[0x2u] == 0x0u);
- assert(arr0[0x3u] == 0x0u);
- assert(arr0[0x4u] == 0x0u);
- assert(arr0[0x5u] == 0x0u);
- assert(arr0[0x6u] == 0x0u);
- ::zap_memfill(arr0,arrsz * sizeof (::std::uint_least64_t),0x7Fu);
- ::std::fprintf(stderr,"arr0[0]: %" PRIXLEAST64 "\n",arr0[0x0u]);
- ::std::fprintf(stderr,"arr0[1]: %" PRIXLEAST64 "\n",arr0[0x1u]);
- ::std::fprintf(stderr,"arr0[2]: %" PRIXLEAST64 "\n",arr0[0x2u]);
- ::std::fprintf(stderr,"arr0[3]: %" PRIXLEAST64 "\n",arr0[0x3u]);
- ::std::fprintf(stderr,"arr0[4]: %" PRIXLEAST64 "\n",arr0[0x4u]);
- ::std::fprintf(stderr,"arr0[5]: %" PRIXLEAST64 "\n",arr0[0x5u]);
- ::std::fprintf(stderr,"arr0[6]: %" PRIXLEAST64 "\n",arr0[0x6u]);
- assert(arr0[0x0u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x1u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x2u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x3u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x4u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x5u] == 0x7F7F7F7F7F7F7F7Fu);
- assert(arr0[0x6u] == 0x7F7F7F7F7F7F7F7Fu);
- ::std::uint_least64_t arr1[arrsz] {0x0u};
- ::zap_memcpy(arr0,arrsz * sizeof (::std::uint_least64_t),arr1);
- ::std::fprintf(stderr,"arr1[0]: %" PRIXLEAST64 "\n",arr1[0x0u]);
- ::std::fprintf(stderr,"arr1[1]: %" PRIXLEAST64 "\n",arr1[0x1u]);
- ::std::fprintf(stderr,"arr1[2]: %" PRIXLEAST64 "\n",arr1[0x2u]);
- ::std::fprintf(stderr,"arr1[3]: %" PRIXLEAST64 "\n",arr1[0x3u]);
- ::std::fprintf(stderr,"arr1[4]: %" PRIXLEAST64 "\n",arr1[0x4u]);
- ::std::fprintf(stderr,"arr1[5]: %" PRIXLEAST64 "\n",arr1[0x5u]);
- ::std::fprintf(stderr,"arr1[6]: %" PRIXLEAST64 "\n",arr1[0x6u]);
- assert(arr1[0x0u] == arr0[0x0u]);
- assert(arr1[0x1u] == arr0[0x1u]);
- assert(arr1[0x2u] == arr0[0x2u]);
- assert(arr1[0x3u] == arr0[0x3u]);
- assert(arr1[0x4u] == arr0[0x4u]);
- assert(arr1[0x5u] == arr0[0x5u]);
- assert(arr1[0x6u] == arr0[0x6u]);
- auto const eq {::zap_memeq(arr1,arrsz,arr0)};
- ::std::fprintf(stderr,"eq: %u\n",eq);
- assert(eq);
- }
- ::std::fprintf(stderr,"\n");
- {
- auto const str {"Hello there! General Kenobi?"};
- ::std::fprintf(stderr,"str: \"%s\"\n",str);
- auto const strsz {::zap_strlen(str)};
- ::std::fprintf(stderr,"strsz: %zX\n",strsz);
- assert(strsz == 0x1Cu);
- }
- ::std::fprintf(stderr,"\n");
- {
- auto str {"Oh my science!"};
- ::std::fprintf(stderr,"str: \"%s\"\n",str);
- auto len {::zap_strlen(str)};
- ::std::fprintf(stderr,"len: %zX\n",len);
- ::std::size_t pos0 = ::zap_fndchr(str,' ');
- ::std::size_t pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
- ::std::fprintf(stderr,"pos0: %zX\n",pos0);
- ::std::fprintf(stderr,"pos1: %zX\n",pos1);
- assert(pos0 == 0x2u);
- assert(pos1 == pos0);
- str += pos0 + 0x1u;
- len = ::zap_strlen(str);
- pos0 = ::zap_fndchr(str,' ');
- pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
- ::std::fprintf(stderr,"pos0: %zX\n",pos0);
- ::std::fprintf(stderr,"pos1: %zX\n",pos1);
- assert(pos0 == 0x2u);
- assert(pos1 == pos0);
- str += pos0 + 0x1u;
- len = ::zap_strlen(str);
- pos0 = ::zap_fndchr(str,' ');
- pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
- ::std::fprintf(stderr,"pos0: %zX\n",pos0);
- ::std::fprintf(stderr,"pos1: %zX\n",pos1);
- assert(pos0 == SIZE_MAX);
- assert(pos1 == pos0);
- }
- ::std::fprintf(stderr,"\n");
- {
- char const str0[] = "What's up, my guy?";
- ::std::fprintf(stderr,"str0: \"%s\"\n",str0);
- char const str1[] = "What's up, my guy?";
- ::std::fprintf(stderr,"str1: \"%s\"\n",str1);
- char const str2[] = "I don't know you!";
- ::std::fprintf(stderr,"str2: \"%s\"\n",str2);
- bool const cmp0 = ::zap_streq(str0,str1);
- bool const cmp1 = ::zap_streq(str0,str2);
- bool const cmp2 = ::zap_streq(str1,str2);
- ::std::fprintf(stderr,"cmp0: %u\n",cmp0);
- ::std::fprintf(stderr,"cmp1: %u\n",cmp1);
- ::std::fprintf(stderr,"cmp2: %u\n",cmp2);
- assert(cmp0);
- assert(!cmp1);
- assert(!cmp2);
- }
- ::std::fprintf(stderr,"\n");
- {
- char const str0[] = "What in the world are you doing?";
- ::std::fprintf(stderr,"str0: \"%s\"\n",str0);
- char str1[sizeof (str0)];
- assert(::zap_strcpy(str0,str1) == 0x20u);
- ::std::fprintf(stderr,"str1: \"%s\"\n",str1);
- assert(::zap_streq(str0,str1));
- }
- ::std::fprintf(stderr,"\n");
- {
- char const str0[] {"Oej Moej Goejd"};
- char const str1[] {"Er jeg egentlig okay med AWP?"};
- ::std::fprintf(stderr,"str0: \"%s\"\n",str0);
- ::std::fprintf(stderr,"str1: \"%s\"\n",str1);
- auto const cmp0 {::zap_strcmp(str0,str1)};
- auto const cmp1 {::zap_strcmp(str0,str0)};
- auto const cmp2 {::zap_strcmp(str1,str0)};
- auto const leastsz {sizeof (str0) < sizeof (str1) ? sizeof (str0) : sizeof (str1)};
- auto const cmp3 {::zap_memcmp(str0,leastsz,str1)};
- auto const cmp4 {::zap_memcmp(str0,leastsz,str0)};
- auto const cmp5 {::zap_memcmp(str1,leastsz,str0)};
- ::std::fprintf(stderr,"cmp0: %i\n",cmp0);
- ::std::fprintf(stderr,"cmp1: %i\n",cmp1);
- ::std::fprintf(stderr,"cmp2: %i\n",cmp2);
- ::std::fprintf(stderr,"cmp3: %i\n",cmp3);
- ::std::fprintf(stderr,"cmp4: %i\n",cmp4);
- ::std::fprintf(stderr,"cmp5: %i\n",cmp5);
- assert(cmp0 > 0x0);
- assert(cmp1 == 0x0);
- assert(cmp2 < 0x0);
- assert(cmp3 > 0x0);
- assert(cmp4 == 0x0);
- assert(cmp5 < 0x0);
- }
- ::std::fprintf(stderr,"\n");
- {
- int arr[] {
- 0x0,
- 0x1,
- 0x2,
- 0x3,
- };
- void * rem {nullptr};
- ::zap_foreach(arr,sizeof (int),sizeof (arr) / sizeof (int),::zap_test_foreachfn);
- ::std::fprintf(stderr,"arr[0]: %i\n",arr[0x0u]);
- ::std::fprintf(stderr,"arr[1]: %i\n",arr[0x1u]);
- ::std::fprintf(stderr,"arr[2]: %i\n",arr[0x2u]);
- ::std::fprintf(stderr,"arr[3]: %i\n",arr[0x3u]);
- assert(arr[0x0u] == 0x0);
- assert(arr[0x1u] == 0x1);
- assert(arr[0x2u] == 0x0);
- assert(arr[0x3u] == 0x1);
- }
- ::std::fprintf(stderr,"\n");
- ::std::fprintf(stderr,"All tests have passed!\n");
-}
diff --git a/test/src/main.c b/test/src/main.c
new file mode 100644
index 0000000..79bf0ce
--- /dev/null
+++ b/test/src/main.c
@@ -0,0 +1,106 @@
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <zap/mem.h>
+
+#define zaptest_log(_expr,_typ,_fmtspec) (fprintf(stderr,"(" #_expr "): " _fmtspec "\n\n",(_typ)(_expr)));
+
+#define zaptest_chk(_lexpr,_rexpr,_typ,_fmtspec) { \
+ fprintf(stderr,"(" #_lexpr "): " _fmtspec "\n",(_typ)(_lexpr)); \
+ fprintf(stderr,"(" #_rexpr "): " _fmtspec "\n\n",(_typ)(_rexpr)); \
+ if ((_typ)(_lexpr) != (_typ)(_rexpr)) { \
+ fprintf(stderr,"Mismatch!\n"); \
+ return true; \
+ } \
+}
+
+typedef bool (* zaptest_testtyp)(void);
+
+#include "test/bool.i"
+#include "test/cmp.i"
+#include "test/fndbyte.i"
+#include "test/fndchr.i"
+#include "test/foreach.i"
+#include "test/memcat.i"
+#include "test/memcmp.i"
+#include "test/memcp.i"
+#include "test/memeq.i"
+#include "test/memfill.i"
+#include "test/memgen.i"
+#include "test/nullptr.i"
+#include "test/strcat.i"
+#include "test/strcp.i"
+#include "test/streq.i"
+#include "test/strfill.i"
+#include "test/strlen.i"
+#include "test/utf8dec.i"
+#include "test/utf8enc.i"
+#include "test/win1252dec.i"
+#include "test/win1252enc.i"
+
+static zaptest_testtyp zaptest_tests[] = {
+ zaptest_test_bool,
+ zaptest_test_cmp,
+ zaptest_test_fndbyte,
+ zaptest_test_fndchr,
+ zaptest_test_foreach,
+ zaptest_test_memcat,
+ zaptest_test_memcmp,
+ zaptest_test_memcp,
+ zaptest_test_memeq,
+ zaptest_test_memfill,
+ zaptest_test_memgen,
+ zaptest_test_nullptr,
+ zaptest_test_strcat,
+ zaptest_test_strcp,
+ zaptest_test_streq,
+ zaptest_test_strfill,
+ zaptest_test_strlen,
+ zaptest_test_utf8dec,
+ zaptest_test_utf8enc,
+ zaptest_test_win1252dec,
+ zaptest_test_win1252enc,
+};
+
+static char const * zaptest_testnms[] = {
+ "bool",
+ "cmp",
+ "fndbyte",
+ "fndchr",
+ "foreach",
+ "memcat",
+ "memcmp",
+ "memcp",
+ "memeq",
+ "memfill",
+ "memgen",
+ "nullptr",
+ "strcat",
+ "strcp",
+ "streq",
+ "strfill",
+ "strlen",
+ "utf8dec",
+ "utf8enc",
+ "win1252dec",
+ "win1252enc",
+};
+
+static void zaptest_dotest(zap_sz const _n) {
+ fprintf(stderr,":: \x1B[94mTesting\x1B[0m %s...\n\n",zaptest_testnms[_n]);
+ if (zaptest_tests[_n]()) {
+ fprintf(stderr,":: \x1B[91mError\x1B[0m in %s! Aborting...\n\n",zaptest_testnms[_n]);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr,":: \x1B[92mSuccess\x1B[0m with %s!\n\n",zaptest_testnms[_n]);
+}
+
+int main(void) {
+ fprintf(stderr,"Zap Test\n\n");
+ fprintf(stderr,"Version: %lX\n",zap_ver);
+ fprintf(stderr,"\n");
+ zaptest_log(zap_nopos,zap_sz,"%zX")
+ zaptest_log((void *)zap_nullptr,uintptr_t,"%" PRIXPTR)
+ for (zap_sz n = 0x0u;n < sizeof (zaptest_tests) / sizeof (zaptest_tests[0x0u]);++n) {zaptest_dotest(n);}
+}
diff --git a/test/src/test/bool.i b/test/src/test/bool.i
new file mode 100644
index 0000000..adacf85
--- /dev/null
+++ b/test/src/test/bool.i
@@ -0,0 +1,9 @@
+#include <inttypes.h>
+#include <stdbool.h>
+
+static bool zaptest_test_bool(void) {
+ zaptest_log(zap_true,uintmax_t,"%" PRIXMAX)
+ zaptest_chk(zap_false,0x0u,unsigned char,"%hhX")
+ zaptest_chk(zap_true > zap_false,0x1u,unsigned char,"%hhX")
+ return false;
+}
diff --git a/test/src/test/cmp.i b/test/src/test/cmp.i
new file mode 100644
index 0000000..fbb7d5c
--- /dev/null
+++ b/test/src/test/cmp.i
@@ -0,0 +1,11 @@
+#include <inttypes.h>
+#include <stdbool.h>
+
+static bool zaptest_test_cmp(void) {
+ zaptest_log(zap_lt,intmax_t,"%" PRIiMAX)
+ zaptest_log(zap_gt,intmax_t,"%" PRIiMAX)
+ zaptest_chk(zap_eq,0x0u,signed char,"%hhi")
+ zaptest_chk(zap_lt < zap_eq,0x1u,unsigned char,"%hhX")
+ zaptest_chk(zap_gt > zap_eq,0x1u,unsigned char,"%hhX")
+ return false;
+}
diff --git a/test/src/test/fndbyte.i b/test/src/test/fndbyte.i
new file mode 100644
index 0000000..56231ac
--- /dev/null
+++ b/test/src/test/fndbyte.i
@@ -0,0 +1,33 @@
+#include <stdbool.h>
+
+static bool zaptest_test_fndbyte(void) {
+ unsigned char const arr[] = {
+ 0x1u,
+ 0x3u,
+ 0x7u,
+ 0xFu,
+ 0x1Fu,
+ 0x3Fu,
+ 0x7Fu,
+ 0xFFu,
+ };
+ zap_sz pos = zap_fndbyte(arr,sizeof (arr),0x1u);
+ zaptest_chk(pos,0x0u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0x3u);
+ zaptest_chk(pos,0x1u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0x7u);
+ zaptest_chk(pos,0x2u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0xFu);
+ zaptest_chk(pos,0x3u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0x1Fu);
+ zaptest_chk(pos,0x4u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0x3Fu);
+ zaptest_chk(pos,0x5u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0x7Fu);
+ zaptest_chk(pos,0x6u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0xFFu);
+ zaptest_chk(pos,0x7u,zap_sz,"%zX");
+ pos = zap_fndbyte(arr,sizeof (arr),0xFEu);
+ zaptest_chk(pos,zap_nopos,zap_sz,"%zX");
+ return false;
+}
diff --git a/test/src/test/fndchr.i b/test/src/test/fndchr.i
new file mode 100644
index 0000000..8fb670a
--- /dev/null
+++ b/test/src/test/fndchr.i
@@ -0,0 +1,12 @@
+#include <stdbool.h>
+
+static bool zaptest_test_fndchr(void) {
+ char const str[] = "What the drake doing?";
+ zap_sz pos = zap_fndchr(str,'?');
+ zaptest_chk(pos,0x14u,zap_sz,"%zX");
+ pos = zap_fndchr(str,'t');
+ zaptest_chk(pos,0x3u,zap_sz,"%zX");
+ pos = zap_fndchr(str,'!');
+ zaptest_chk(pos,zap_nopos,zap_sz,"%zX");
+ return false;
+}
diff --git a/test/src/test/foreach.i b/test/src/test/foreach.i
new file mode 100644
index 0000000..e7b933d
--- /dev/null
+++ b/test/src/test/foreach.i
@@ -0,0 +1,23 @@
+#include <stdbool.h>
+
+static void foreachfn(void * const _ptr) {
+ unsigned int * ptr = _ptr;
+ unsigned int val = *ptr;
+ val %= 0x2;
+ *ptr = val;
+}
+
+static bool zaptest_test_foreach(void) {
+ unsigned int arr[] = {
+ 0x0u,
+ 0x1u,
+ 0x2u,
+ 0x3u,
+ };
+ zap_foreach(arr,sizeof (arr[0x0u]),sizeof (arr) / sizeof (arr[0x0u]),foreachfn);
+ zaptest_chk(arr[0x0u],0x0u,unsigned int,"%X");
+ zaptest_chk(arr[0x1u],0x1u,unsigned int,"%X");
+ zaptest_chk(arr[0x2u],0x0u,unsigned int,"%X");
+ zaptest_chk(arr[0x3u],0x1u,unsigned int,"%X");
+ return false;
+}
diff --git a/test/src/test/memcat.i b/test/src/test/memcat.i
new file mode 100644
index 0000000..f16faef
--- /dev/null
+++ b/test/src/test/memcat.i
@@ -0,0 +1,43 @@
+#include <stdbool.h>
+
+static bool zaptest_test_memcat(void) {
+ unsigned short const arr0[] = {
+ 0x1u,
+ 0x3u,
+ 0x7u,
+ 0xFu,
+ 0x1Fu,
+ 0x3Fu,
+ 0x7Fu,
+ 0xFFu,
+ };
+ unsigned short const arr1[] = {
+ 0x1FFu,
+ 0x3FFu,
+ 0x7FFu,
+ 0xFFFu,
+ 0x1FFFu,
+ 0x3FFFu,
+ 0x7FFFu,
+ 0xFFFFu,
+ };
+ unsigned short buf[(sizeof (arr0) + sizeof (arr1)) / sizeof (arr0[0x0u])];
+ zap_memcat(arr0,sizeof (arr0),arr1,sizeof (arr1),buf);
+ zaptest_chk(buf[0x0u],0x1u, unsigned int,"%X");
+ zaptest_chk(buf[0x1u],0x3u, unsigned int,"%X");
+ zaptest_chk(buf[0x2u],0x7u, unsigned int,"%X");
+ zaptest_chk(buf[0x3u],0xFu, unsigned int,"%X");
+ zaptest_chk(buf[0x4u],0x1F, unsigned int,"%X");
+ zaptest_chk(buf[0x5u],0x3Fu, unsigned int,"%X");
+ zaptest_chk(buf[0x6u],0x7Fu, unsigned int,"%X");
+ zaptest_chk(buf[0x7u],0xFFu, unsigned int,"%X");
+ zaptest_chk(buf[0x8u],0x1FFu, unsigned int,"%X");
+ zaptest_chk(buf[0x9u],0x3FFu, unsigned int,"%X");
+ zaptest_chk(buf[0xAu],0x7FFu, unsigned int,"%X");
+ zaptest_chk(buf[0xBu],0xFFFu, unsigned int,"%X");
+ zaptest_chk(buf[0xCu],0x1FFFu,unsigned int,"%X");
+ zaptest_chk(buf[0xDu],0x3FFFu,unsigned int,"%X");
+ zaptest_chk(buf[0xEu],0x7FFFu,unsigned int,"%X");
+ zaptest_chk(buf[0xFu],0xFFFFu,unsigned int,"%X");
+ return false;
+}
diff --git a/test/src/test/memcmp.i b/test/src/test/memcmp.i
new file mode 100644
index 0000000..d54a062
--- /dev/null
+++ b/test/src/test/memcmp.i
@@ -0,0 +1,26 @@
+#include <stdbool.h>
+
+static bool zaptest_test_memcmp(void) {
+ unsigned char const arr0[] = {
+ 0x7Fu,
+ 0x3Fu,
+ 0xFFu,
+ };
+ unsigned char const arr1[] = {
+ 0x7Fu,
+ 0x3Fu,
+ 0x1Fu,
+ };
+ unsigned char const arr2[] = {
+ 0x7Fu,
+ 0x3Fu,
+ 0xFFu,
+ };
+ zap_cmp cmp = zap_memcmp(arr0,sizeof (arr0),arr1);
+ zaptest_chk(cmp,zap_gt,signed char,"%hhi")
+ cmp = zap_memcmp(arr1,sizeof (arr1),arr0);
+ zaptest_chk(cmp,zap_lt,signed char,"%hhi")
+ cmp = zap_memcmp(arr0,sizeof (arr0),arr2);
+ zaptest_chk(cmp,zap_eq,signed char,"%hhi")
+ return false;
+}
diff --git a/test/src/test/memcp.i b/test/src/test/memcp.i
new file mode 100644
index 0000000..4cfc17c
--- /dev/null
+++ b/test/src/test/memcp.i
@@ -0,0 +1,18 @@
+#include <inttypes.h>
+#include <stdbool.h>
+
+static bool zaptest_test_memcp(void) {
+ unsigned int arr[] = {
+ 0xA5D0u,
+ 0x98FFu,
+ 0xA29Au,
+ 0x910Cu,
+ };
+ unsigned int buf[sizeof (arr) / sizeof (arr[0x0u])];
+ zap_memcp(arr,sizeof (arr),buf);
+ zaptest_chk(buf[0x0u],0xA5D0u,unsigned int,"%X");
+ zaptest_chk(buf[0x1u],0x98FFu,unsigned int,"%X");
+ zaptest_chk(buf[0x2u],0xA29Au,unsigned int,"%X");
+ zaptest_chk(buf[0x3u],0x910Cu,unsigned int,"%X");
+ return false;
+}
diff --git a/test/src/test/memeq.i b/test/src/test/memeq.i
new file mode 100644
index 0000000..d9de72f
--- /dev/null
+++ b/test/src/test/memeq.i
@@ -0,0 +1,24 @@
+#include <stdbool.h>
+
+static bool zaptest_test_memeq(void) {
+ unsigned char const arr0[] = {
+ 0xFFu,
+ 0x7Fu,
+ 0x3Fu,
+ };
+ unsigned char const arr1[] = {
+ 0xFFu,
+ 0x7Fu,
+ 0xFFu,
+ };
+ unsigned char const arr2[] = {
+ 0xFFu,
+ 0x7Fu,
+ 0x3Fu,
+ };
+ zap_cmp eq = zap_memeq(arr0,sizeof (arr0),arr1);
+ zaptest_chk(eq,zap_false,unsigned char,"%hhX")
+ eq = zap_memeq(arr0,sizeof (arr0),arr2);
+ zaptest_chk(eq,zap_true,unsigned char,"%hhX")
+ return false;
+}
diff --git a/test/src/test/memfill.i b/test/src/test/memfill.i
new file mode 100644
index 0000000..9cb4d6e
--- /dev/null
+++ b/test/src/test/memfill.i
@@ -0,0 +1,23 @@
+#include <stdbool.h>
+
+static bool zaptest_test_memfill(void) {
+ unsigned long arr[0x4u];
+ zap_memfill(arr,sizeof (arr),0x7Fu);
+ arr[0x0u] &= 0xFFFFFFFFFFFFFFFFu;
+ arr[0x1u] &= 0xFFFFFFFFFFFFFFFFu;
+ arr[0x2u] &= 0xFFFFFFFFFFFFFFFFu;
+ arr[0x3u] &= 0xFFFFFFFFFFFFFFFFu;
+ zaptest_chk(arr[0x0u],0x7F7F7F7F7F7F7F7Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x1u],0x7F7F7F7F7F7F7F7Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x2u],0x7F7F7F7F7F7F7F7Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x3u],0x7F7F7F7F7F7F7F7Fu,unsigned long,"%lX");
+ zap_memfill(arr + 0x1u,sizeof (arr) - sizeof (arr[0x0u]),0x3Fu);
+ arr[0x1u] &= 0xFFFFFFFFFFFFFFFFu;
+ arr[0x2u] &= 0xFFFFFFFFFFFFFFFFu;
+ arr[0x3u] &= 0xFFFFFFFFFFFFFFFFu;
+ zaptest_chk(arr[0x0u],0x7F7F7F7F7F7F7F7Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x1u],0x3F3F3F3F3F3F3F3Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x2u],0x3F3F3F3F3F3F3F3Fu,unsigned long,"%lX");
+ zaptest_chk(arr[0x3u],0x3F3F3F3F3F3F3F3Fu,unsigned long,"%lX");
+ return false;
+}
diff --git a/test/src/test/memgen.i b/test/src/test/memgen.i
new file mode 100644
index 0000000..dcc7c69
--- /dev/null
+++ b/test/src/test/memgen.i
@@ -0,0 +1,29 @@
+#include <stdbool.h>
+#include <stddef.h>
+
+static unsigned long zaptest_fib(zap_sz const _num) {
+ if (_num <= 0x1u) {
+ if (_num == 0x0u) {return 0x0u;}
+ return 0x1u;
+ }
+ return zaptest_fib(_num - 0x1u) + zaptest_fib(_num - 0x2u);
+}
+
+static void zatest_memgenfn(zap_sz const _num,void * const _ptr) {
+ unsigned long * ptr = _ptr;
+ *ptr = zaptest_fib(_num);
+}
+
+static bool zaptest_test_memgen(void) {
+ unsigned long arr[0x8u];
+ zap_memgen(arr,sizeof (arr[0x0u]),sizeof (arr) / sizeof (arr[0x0u]),zatest_memgenfn);
+ zaptest_chk(arr[0x0u],0x0u,unsigned long,"%lX");
+ zaptest_chk(arr[0x1u],0x1u,unsigned long,"%lX");
+ zaptest_chk(arr[0x2u],0x1u,unsigned long,"%lX");
+ zaptest_chk(arr[0x3u],0x2u,unsigned long,"%lX");
+ zaptest_chk(arr[0x4u],0x3u,unsigned long,"%lX");
+ zaptest_chk(arr[0x5u],0x5u,unsigned long,"%lX");
+ zaptest_chk(arr[0x6u],0x8u,unsigned long,"%lX");
+ zaptest_chk(arr[0x7u],0xDu,unsigned long,"%lX");
+ return false;
+}
diff --git a/test/src/test/nullptr.i b/test/src/test/nullptr.i
new file mode 100644
index 0000000..00b49bd
--- /dev/null
+++ b/test/src/test/nullptr.i
@@ -0,0 +1,7 @@
+#include <stdbool.h>
+#include <stddef.h>
+
+static bool zaptest_test_nullptr(void) {
+ zaptest_chk((void *)zap_nullptr,(void *)NULL,void *,"%p")
+ return false;
+}
diff --git a/test/src/test/strcat.i b/test/src/test/strcat.i
new file mode 100644
index 0000000..e037b88
--- /dev/null
+++ b/test/src/test/strcat.i
@@ -0,0 +1,19 @@
+#include <stdbool.h>
+
+static bool zaptest_test_strcat(void) {
+ char const str0[] = "u r ";
+ char const str1[] = "mr gay";
+ char buf[sizeof (str0) + sizeof (str1)];
+ zap_strcat(str0,str1,buf);
+ zaptest_chk(buf[0x0u],'u',char,"'%c'");
+ zaptest_chk(buf[0x1u],' ',char,"'%c'");
+ zaptest_chk(buf[0x2u],'r',char,"'%c'");
+ zaptest_chk(buf[0x3u],' ',char,"'%c'");
+ zaptest_chk(buf[0x4u],'m',char,"'%c'");
+ zaptest_chk(buf[0x5u],'r',char,"'%c'");
+ zaptest_chk(buf[0x6u],' ',char,"'%c'");
+ zaptest_chk(buf[0x7u],'g',char,"'%c'");
+ zaptest_chk(buf[0x8u],'a',char,"'%c'");
+ zaptest_chk(buf[0x9u],'y',char,"'%c'");
+ return false;
+}
diff --git a/test/src/test/strcp.i b/test/src/test/strcp.i
new file mode 100644
index 0000000..cd878c9
--- /dev/null
+++ b/test/src/test/strcp.i
@@ -0,0 +1,42 @@
+#include <stdbool.h>
+
+static bool zaptest_test_strcp(void) {
+ char const str[] = "What in the world are you doing?";
+ zaptest_log(str,char const *,"%s")
+ char buf[sizeof (str)];
+ zap_strcp(str,buf);
+ zaptest_chk(buf[0x0u], 'W', char,"'%c'")
+ zaptest_chk(buf[0x1u], 'h', char,"'%c'")
+ zaptest_chk(buf[0x2u], 'a', char,"'%c'")
+ zaptest_chk(buf[0x3u], 't', char,"'%c'")
+ zaptest_chk(buf[0x4u], ' ', char,"'%c'")
+ zaptest_chk(buf[0x5u], 'i', char,"'%c'")
+ zaptest_chk(buf[0x6u], 'n', char,"'%c'")
+ zaptest_chk(buf[0x7u], ' ', char,"'%c'")
+ zaptest_chk(buf[0x8u], 't', char,"'%c'")
+ zaptest_chk(buf[0x9u], 'h', char,"'%c'")
+ zaptest_chk(buf[0xAu], 'e', char,"'%c'")
+ zaptest_chk(buf[0xBu], ' ', char,"'%c'")
+ zaptest_chk(buf[0xCu], 'w', char,"'%c'")
+ zaptest_chk(buf[0xDu], 'o', char,"'%c'")
+ zaptest_chk(buf[0xEu], 'r', char,"'%c'")
+ zaptest_chk(buf[0xFu], 'l', char,"'%c'")
+ zaptest_chk(buf[0x10u],'d', char,"'%c'")
+ zaptest_chk(buf[0x11u],' ', char,"'%c'")
+ zaptest_chk(buf[0x12u],'a', char,"'%c'")
+ zaptest_chk(buf[0x13u],'r', char,"'%c'")
+ zaptest_chk(buf[0x14u],'e', char,"'%c'")
+ zaptest_chk(buf[0x15u],' ', char,"'%c'")
+ zaptest_chk(buf[0x16u],'y', char,"'%c'")
+ zaptest_chk(buf[0x17u],'o', char,"'%c'")
+ zaptest_chk(buf[0x18u],'u', char,"'%c'")
+ zaptest_chk(buf[0x19u],' ', char,"'%c'")
+ zaptest_chk(buf[0x1Au],'d', char,"'%c'")
+ zaptest_chk(buf[0x1Bu],'o', char,"'%c'")
+ zaptest_chk(buf[0x1Cu],'i', char,"'%c'")
+ zaptest_chk(buf[0x1Du],'n', char,"'%c'")
+ zaptest_chk(buf[0x1Eu],'g', char,"'%c'")
+ zaptest_chk(buf[0x1Fu],'?', char,"'%c'")
+ zaptest_chk(buf[0x20u],'\x0',char,"'%c'")
+ return false;
+}
diff --git a/test/src/test/streq.i b/test/src/test/streq.i
new file mode 100644
index 0000000..f9f1d31
--- /dev/null
+++ b/test/src/test/streq.i
@@ -0,0 +1,17 @@
+#include <stdbool.h>
+
+static bool zaptest_test_streq(void) {
+ char const str0[] = "What's up, my guy?";
+ char const str1[] = "What's up, my guy?";
+ char const str2[] = "I don't know you!";
+ zaptest_log(str0,char const *,"%s")
+ zaptest_log(str1,char const *,"%s")
+ zaptest_log(str2,char const *,"%s")
+ zap_bool eq0 = zap_streq(str0,str1);
+ zap_bool eq1 = zap_streq(str0,str2);
+ zap_bool eq2 = zap_streq(str1,str2);
+ zaptest_chk(eq0,zap_true, unsigned char,"%hhX");
+ zaptest_chk(eq1,zap_false,unsigned char,"%hhX");
+ zaptest_chk(eq2,zap_false,unsigned char,"%hhX");
+ return false;
+}
diff --git a/test/src/test/strfill.i b/test/src/test/strfill.i
new file mode 100644
index 0000000..1e2764c
--- /dev/null
+++ b/test/src/test/strfill.i
@@ -0,0 +1,18 @@
+#include <stdbool.h>
+
+static bool zaptest_test_strfill(void) {
+ char str[] = {
+ 'H',
+ 'e',
+ 'y',
+ '!',
+ '\x0',
+ };
+ zap_strfill(str,'&');
+ zaptest_chk(str[0x0u],'&', char,"'%c'");
+ zaptest_chk(str[0x1u],'&', char,"'%c'");
+ zaptest_chk(str[0x2u],'&', char,"'%c'");
+ zaptest_chk(str[0x3u],'&', char,"'%c'");
+ zaptest_chk(str[0x4u],'\x0',char,"'%c'");
+ return false;
+}
diff --git a/test/src/test/strlen.i b/test/src/test/strlen.i
new file mode 100644
index 0000000..93bec76
--- /dev/null
+++ b/test/src/test/strlen.i
@@ -0,0 +1,13 @@
+#include <stdbool.h>
+
+bool zaptest_test_strlen(void) {
+ char const str0[] = "Hello there! General Kenobi?";
+ char const str1[] = "Hello there! General Gayballs?";
+ zaptest_log(str0,char const *,"%s")
+ zaptest_log(str1,char const *,"%s")
+ zap_sz const len0 = zap_strlen(str0);
+ zap_sz const len1 = zap_strlen(str1);
+ zaptest_chk(len0,0x1Cu,zap_sz,"%zX")
+ zaptest_chk(len1,0x1Eu,zap_sz,"%zX")
+ return false;
+}
diff --git a/test/src/test/utf8dec.i b/test/src/test/utf8dec.i
new file mode 100644
index 0000000..fdea169
--- /dev/null
+++ b/test/src/test/utf8dec.i
@@ -0,0 +1,43 @@
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static bool zaptest_test_utf8dec(void) {
+ zap_chr8 const utf8[] = {
+ 0x26u,
+ 0xC3u,
+ 0xB0u,
+ 0xE0u,
+ 0xB6u,
+ 0x9Eu,
+ 0xE2u,
+ 0x86u,
+ 0x8Au,
+ 0xE2u,
+ 0x86u,
+ 0x8Bu,
+ 0xF0u,
+ 0x9Fu,
+ 0x97u,
+ 0xBFu,
+ 0x0u,
+ };
+ zap_sz const enclen = zap_utf8declen(utf8);
+ zaptest_chk(enclen,0x6u,zap_sz,"%zX")
+ zap_chr20 * const utf20 = malloc(sizeof (zap_chr20) * (enclen + 0x1u));
+ if (utf20 == NULL) {
+ fputs("test.utf8dec: Memory allocation failed!\n\n",stderr);
+ return true;
+ }
+ zap_utf8dec(utf8,utf20);
+ zaptest_chk(utf20[0x0u],0x26u, zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x1u],0xF0u, zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x2u],0xD9Eu, zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x3u],0x218Au, zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x4u],0x218Bu, zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x5u],0x1F5FFu,zap_chr20,"%" PRIXLEAST32)
+ zaptest_chk(utf20[0x6u],0x0u, zap_chr20,"%" PRIXLEAST32)
+ free(utf20);
+ return false;
+}
diff --git a/test/src/test/utf8enc.i b/test/src/test/utf8enc.i
new file mode 100644
index 0000000..8bc7abb
--- /dev/null
+++ b/test/src/test/utf8enc.i
@@ -0,0 +1,42 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+static bool zaptest_test_utf8enc(void) {
+ zap_chr20 const utf20[] = {
+ 0x26u,
+ 0xF0u,
+ 0xD9Eu,
+ 0x218Au,
+ 0x218Bu,
+ 0x1F5FFu,
+ 0x0u,
+ };
+ zap_sz const enclen = zap_utf8enclen(utf20);
+ zaptest_chk(enclen,0x10u,zap_sz,"%zX")
+ zap_chr8 * const utf8 = malloc(enclen + 0x1u);
+ if (utf8 == NULL) {
+ fputs("test.utf8enc: Memory allocation failed!\n\n",stderr);
+ return true;
+ }
+ zap_utf8enc(utf20,utf8);
+ zaptest_log(utf8,char const *,"%s") /* UB? */
+ zaptest_chk(utf8[0x0u], 0x26u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x1u], 0xC3u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x2u], 0xB0u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x3u], 0xE0u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x4u], 0xB6u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x5u], 0x9Eu,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x6u], 0xE2u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x7u], 0x86u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x8u], 0x8Au,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x9u], 0xE2u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xAu], 0x86u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xBu], 0x8Bu,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xCu], 0xF0u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xDu], 0x9Fu,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xEu], 0x97u,unsigned char,"%hhX")
+ zaptest_chk(utf8[0xFu], 0xBFu,unsigned char,"%hhX")
+ zaptest_chk(utf8[0x10u],0x0u, unsigned char,"%hhX")
+ free(utf8);
+ return false;
+}
diff --git a/test/src/test/win1252dec.i b/test/src/test/win1252dec.i
new file mode 100644
index 0000000..23fbe2b
--- /dev/null
+++ b/test/src/test/win1252dec.i
@@ -0,0 +1,76 @@
+#include <inttypes.h>
+#include <stdbool.h>
+
+static bool zaptest_test_win1252dec(void) {
+ zap_chr8 const win1252[] = {
+ 0x26u,
+ 0xF0u,
+ 0x80u,
+ 0x82u,
+ 0x83u,
+ 0x84u,
+ 0x85u,
+ 0x86u,
+ 0x87u,
+ 0x88u,
+ 0x89u,
+ 0x8Au,
+ 0x8Bu,
+ 0x8Cu,
+ 0x8Eu,
+ 0x91u,
+ 0x92u,
+ 0x93u,
+ 0x94u,
+ 0x95u,
+ 0x96u,
+ 0x97u,
+ 0x98u,
+ 0x99u,
+ 0x9Au,
+ 0x9Bu,
+ 0x9Cu,
+ 0x9Eu,
+ 0x9Fu,
+ 0x0u,
+ };
+ zap_sz const enclen = sizeof (win1252) - 0x1u;
+ zaptest_chk(enclen,0x1Du,zap_sz,"%zX")
+ zap_chr20 * const utf20 = malloc(sizeof (zap_chr20) * (enclen + 0x1u));
+ if (utf20 == NULL) {
+ fputs("test.win1252dec: Memory allocation failed!\n\n",stderr);
+ return true;
+ }
+ zap_win1252dec(win1252,utf20);
+ zaptest_chk(utf20[0x0u], 0x26u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x1u], 0xF0u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x2u], 0x20ACu,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x3u], 0x201Au,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x4u], 0x192u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x5u], 0x201Eu,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x6u], 0x2026u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x7u], 0x2020u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x8u], 0x2021u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x9u], 0x2C6u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xAu], 0x2030u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xBu], 0x160u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xCu], 0x2039u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xDu], 0x152u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xEu], 0x17Du, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0xFu], 0x2018u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x10u],0x2019u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x11u],0x201Cu,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x12u],0x201Du,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x13u],0x2022u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x14u],0x2013u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x15u],0x2014u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x16u],0x2DCu, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x17u],0x2122u,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x18u],0x161u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x19u],0x203Au,zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x1Au],0x153u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x1Bu],0x17Eu, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x1Cu],0x178u, zap_chr20,"%" PRIXLEAST32);
+ zaptest_chk(utf20[0x1Du],0x0u, zap_chr20,"%" PRIXLEAST32);
+ return false;
+}
diff --git a/test/src/test/win1252enc.i b/test/src/test/win1252enc.i
new file mode 100644
index 0000000..2bfa211
--- /dev/null
+++ b/test/src/test/win1252enc.i
@@ -0,0 +1,76 @@
+#include <stdbool.h>
+
+static bool zaptest_test_win1252enc(void) {
+ zap_chr20 const utf20[] = {
+ 0x26u,
+ 0xF0u,
+ 0x20ACu,
+ 0x201Au,
+ 0x192u,
+ 0x201Eu,
+ 0x2026u,
+ 0x2020u,
+ 0x2021u,
+ 0x2C6u,
+ 0x2030u,
+ 0x160u,
+ 0x2039u,
+ 0x152u,
+ 0x17Du,
+ 0x2018u,
+ 0x2019u,
+ 0x201Cu,
+ 0x201Du,
+ 0x2022u,
+ 0x2013u,
+ 0x2014u,
+ 0x2DCu,
+ 0x2122u,
+ 0x161u,
+ 0x203Au,
+ 0x153u,
+ 0x17Eu,
+ 0x178u,
+ 0x0u,
+ };
+ zap_sz const enclen = sizeof (utf20) / sizeof (utf20[0x0u]) - 0x1u;
+ zaptest_chk(enclen,0x1Du,zap_sz,"%zX")
+ zap_chr8 * const win1252 = malloc(enclen + 0x1u);
+ if (win1252 == NULL) {
+ fputs("test.win1252enc: Memory allocation failed!\n\n",stderr);
+ return true;
+ }
+ zap_win1252enc(utf20,win1252);
+ zaptest_log(win1252,char const *,"%s"); /* UB? */
+ zaptest_chk(win1252[0x0u], 0x26u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x1u], 0xF0u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x2u], 0x80u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x3u], 0x82u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x4u], 0x83u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x5u], 0x84u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x6u], 0x85u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x7u], 0x86u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x8u], 0x87u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x9u], 0x88u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xAu], 0x89u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xBu], 0x8Au,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xCu], 0x8Bu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xDu], 0x8Cu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xEu], 0x8Eu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0xFu], 0x91u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x10u],0x92u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x11u],0x93u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x12u],0x94u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x13u],0x95u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x14u],0x96u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x15u],0x97u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x16u],0x98u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x17u],0x99u,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x18u],0x9Au,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x19u],0x9Bu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x1Au],0x9Cu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x1Bu],0x9Eu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x1Cu],0x9Fu,unsigned char,"%hhX");
+ zaptest_chk(win1252[0x1Du],0x0u, unsigned char,"%hhX");
+ return false;
+}
diff --git a/zap/GNUmakefile b/zap/GNUmakefile
new file mode 100644
index 0000000..58a85ce
--- /dev/null
+++ b/zap/GNUmakefile
@@ -0,0 +1,71 @@
+# Copyright 2022 Gabriel Jensen.
+# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+# If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+# TOOLS
+
+#CC = clang
+#CC = gcc
+
+# TOOL FLAGS
+
+ASFLAGS += \
+ -g \
+ -march=native
+
+CFLAGS += \
+ -Ofast \
+ -fPIC \
+ -ffreestanding \
+ -g \
+ -march=native \
+ -std=c90 \
+ -Wall \
+ -Wextra \
+ -Wpedantic
+
+CPPFLAGS += \
+ -Iinclude \
+ -Iinclude-private
+
+# ARTEFACTS
+
+OBJS = \
+ src/mem/fndbyte.o \
+ src/mem/fndchr.o \
+ src/mem/foreach.o \
+ src/mem/memcat.o \
+ src/mem/memcmp.o \
+ src/mem/memcp.o \
+ src/mem/memeq.o \
+ src/mem/memfill.o \
+ src/mem/memgen.o \
+ src/mem/strcat.o \
+ src/mem/strcmp.o \
+ src/mem/streq.o \
+ src/mem/strfill.o \
+ src/mem/strcp.o \
+ src/mem/strlen.o \
+ src/mem/utf8dec.o \
+ src/mem/utf8declen.o \
+ src/mem/utf8enc.o \
+ src/mem/utf8enclen.o \
+ src/mem/win1252dec.o \
+ src/mem/win1252enc.o
+
+LIB = libzap.a
+
+# OPTIONS
+
+# TARGETS
+
+.PHONY: clean purge
+
+$(LIB): $(OBJS)
+ $(AR) r $@ $^
+
+clean:
+ $(RM) $(OBJS)
+
+purge: clean
+ $(RM) $(LIB)
diff --git a/zap/Makefile b/zap/Makefile
deleted file mode 100644
index b7db3dc..0000000
--- a/zap/Makefile
+++ /dev/null
@@ -1,64 +0,0 @@
-# TOOLS
-
-#CC = clang
-#CC = gcc
-
-# TOOL FLAGS
-
-CFLAGS = \
- -Iinclude \
- -Iinclude-priv \
- -O3 \
- -fPIC \
- -g \
- -march=native \
- -std=c99 \
- -Wall \
- -Wextra \
- -Wpedantic
-
-# ARTIFACTS
-
-OBJS = \
- src/abs.o \
- src/fastimpl.o \
- src/fma.o \
- src/fndbyte.o \
- src/fndchr.o \
- src/foreach.o \
- src/memcmp.o \
- src/memcpy.o \
- src/memdup.o \
- src/memeq.o \
- src/memfill.o \
- src/strcmp.o \
- src/strdup.o \
- src/streq.o \
- src/strfill.o \
- src/strcpy.o \
- src/strlen.o
-
-LIB = libzap.a
-
-# OPTIONS
-
-# Uncomment to disable assembly algorithms:
-#CFLAGS += -Dzap_priv_noasm
-
-# Uncomment to enable freestanding mode (requries no runtime):
-#CFLAGS += \
- -Dzap_priv_nostdlib \
- -ffreestanding
-
-# TARGETS
-
-.PHONY: clean purge
-
-$(LIB): $(OBJS)
- ar r $@ $(OBJS)
-
-clean:
- rm -fr $(OBJS)
-
-purge: clean
- rm -fr $(LIB)
diff --git a/zap/include-priv/zap/priv.h b/zap/include-private/zap/priv.h
index 8ebbd39..c47d802 100644
--- a/zap/include-priv/zap/priv.h
+++ b/zap/include-private/zap/priv.h
@@ -7,12 +7,14 @@
#if !defined(zap_priv_hdr_priv)
#define zap_priv_hdr_priv
-#include <zap/base.h>
+#if !defined(__amd64__)
+#error zapq only supports AMD64!
+#endif
+
+#if !defined(__ASSEMBLER__)
+#include <zap/bs.h>
-#if (defined(sus_comp_gnu) || defined(sus_comp_llvm)) && defined(sus_os_unix) && !defined(zap_priv_noasm) && (defined(sus_arch_amd64) || defined(sus_arch_ia32))
-#define zap_priv_fastimpl (0x1u)
-#else
-#define zap_priv_fastimpl (0x0u)
+#include <sus/extra.h>
#endif
#endif
diff --git a/zap/include/zap/base.h b/zap/include/zap/base.h
deleted file mode 100644
index a52414b..0000000
--- a/zap/include/zap/base.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <stdbool.h>
-#include <susinfo.h>
-
-#if !defined(zap_priv_hdr_base)
-#define zap_priv_hdr_base
-
-#define zap_ver (0xFu)
-
-#if defined(sus_lang_cxx)
-extern "C" {
-#endif
-
-extern bool const zap_fastimpl;
-
-#if defined(sus_lang_cxx)
-}
-#endif
-
-#endif
diff --git a/zap/include/zap/bs.h b/zap/include/zap/bs.h
new file mode 100644
index 0000000..930b1a8
--- /dev/null
+++ b/zap/include/zap/bs.h
@@ -0,0 +1,43 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#if !defined(zap_priv_hdr_bs)
+#define zap_priv_hdr_bs
+
+#if defined(sus_lang_cxx)
+extern "C" {
+#endif
+
+typedef unsigned char zap_bool;
+#define zap_false ((zap_bool)+0x0u)
+#define zap_true ((zap_bool)+0xFFu)
+
+typedef unsigned short zap_chr10;
+typedef unsigned int zap_chr20;
+typedef unsigned char zap_chr8;
+
+typedef signed char zap_cmp;
+#define zap_eq ((zap_cmp)+0x0)
+#define zap_gt ((zap_cmp)+0x7F)
+#define zap_lt ((zap_cmp)-0x80)
+
+#define zap_nopos (~((zap_sz)+0u))
+
+#if defined(__cplusplus)
+#define zap_nullptr ((unsigned long)0x0u)
+#else
+#define zap_nullptr ((void *)0x0u)
+#endif
+
+typedef unsigned long zap_sz;
+
+#define zap_ver ((unsigned long)+0x10u)
+
+#if defined(sus_lang_cxx)
+}
+#endif
+
+#endif
diff --git a/zap/include/zap/math.h b/zap/include/zap/math.h
deleted file mode 100644
index 97afb66..0000000
--- a/zap/include/zap/math.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/base.h>
-
-#include <susinfo.h>
-
-#if !defined(zap_priv_hdr_math)
-#define zap_priv_hdr_math
-
-#if !defined(sus_langfeat_c_llng) && !defined(sus_langfeat_cxx_llng)
-#error The (long long) type is required but unsupported by the implementation !
-#endif
-
-#if defined(sus_lang_cxx)
-extern "C" {
-#endif
-
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret signed char zap_abs_c( signed char val);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret int zap_abs_i( int val);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long zap_abs_l( long val);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long long zap_abs_ll( long long val);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret short zap_abs_s( short val);
-
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret signed char zap_fma_c( signed char a,signed char b,signed char c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret int zap_fma_i( int a,int b,int c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long zap_fma_l( long a,long b,long c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long long zap_fma_ll( long long a,long long b,long long c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret short zap_fma_s( short a,short b,short c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned char zap_fma_uc( unsigned char a,unsigned char b,unsigned char c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned int zap_fma_ui( unsigned int a,unsigned int b,unsigned int c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned long zap_fma_ul( unsigned long a,unsigned long b,unsigned long c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned long long zap_fma_ull(unsigned long long a,unsigned long long b,unsigned long long c);
-sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned short zap_fma_us( unsigned short a,unsigned short b,unsigned short c);
-
-#if defined(sus_langfeat_c_generic)
-
-#define zap_abs_tg(_val) \
- (_Generic((_val), \
- signed char:zap_abs_c, \
- int: zap_abs_i, \
- long: zap_abs_l, \
- long long: zap_abs_ll,\
- short: zap_abs_s, \
- )((_val)))
-
-#define zap_fma_tg(_a,_b,_c) \
- (_Generic((_a), \
- signed char: zap_fma_c, \
- int: zap_fma_i, \
- long: zap_fma_l, \
- long long: zap_fma_ll, \
- short: zap_fma_s, \
- unsigned char: zap_fma_uc, \
- unsigned int: zap_fma_ui, \
- unsigned long: zap_fma_ul, \
- unsigned long long:zap_fma_ull,\
- unsigned short: zap_fma_us, \
- )((_a),(_b),(_c)))
-
-#elif defined(sus_lang_cxx)
-
-extern "C++" {
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline signed char zap_priv_cxxtg_abs(signed char const _val) {return ::zap_abs_c( _val);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline int zap_priv_cxxtg_abs(int const _val) {return ::zap_abs_i( _val);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline long zap_priv_cxxtg_abs(long const _val) {return ::zap_abs_l( _val);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline long long zap_priv_cxxtg_abs(long long const _val) {return ::zap_abs_ll(_val);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline short zap_priv_cxxtg_abs(short const _val) {return ::zap_abs_s( _val);};
-
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline signed char zap_priv_cxxtg_fma(signed char const _a,signed char const _b,signed char const _c) {return ::zap_fma_c( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline int zap_priv_cxxtg_fma(int const _a,int const _b,int const _c) {return ::zap_fma_i( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline long zap_priv_cxxtg_fma(long const _a,long const _b,long const _c) {return ::zap_fma_l( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline long long zap_priv_cxxtg_fma(long long const _a,long long const _b,long long const _c) {return ::zap_fma_ll( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline short zap_priv_cxxtg_fma(short const _a,short const _b,short const _c) {return ::zap_fma_s( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned char zap_priv_cxxtg_fma(unsigned char const _a,unsigned char const _b,unsigned char const _c) {return ::zap_fma_uc( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned int zap_priv_cxxtg_fma(unsigned int const _a,unsigned int const _b,unsigned int const _c) {return ::zap_fma_ui( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned long zap_priv_cxxtg_fma(unsigned long const _a,unsigned long const _b,unsigned long const _c) {return ::zap_fma_ul( _a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned long long zap_priv_cxxtg_fma(unsigned long long const _a,unsigned long long const _b,unsigned long long const _c) {return ::zap_fma_ull(_a,_b,_c);};
- sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned short zap_priv_cxxtg_fma(unsigned short const _a,unsigned short const _b,unsigned short const _c) {return ::zap_fma_us( _a,_b,_c);};
-}
-
-#define zap_abs_tg(_val) (::zap_priv_cxxtg_abs( _val))
-#define zap_fma_tg(_a, _b,_c) (::zap_priv_cxxtg_fma(_a, _b,_c))
-
-#endif
-
-#if defined(sus_lang_cxx)
-}
-#endif
-
-#endif
diff --git a/zap/include/zap/mem.h b/zap/include/zap/mem.h
index 20d7326..0580019 100644
--- a/zap/include/zap/mem.h
+++ b/zap/include/zap/mem.h
@@ -4,54 +4,37 @@
If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
-#include <zap/base.h>
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <susinfo.h>
-
#if !defined(zap_priv_hdr_mem)
#define zap_priv_hdr_mem
-#if defined(sus_lang_asm)
-
-.extern zap_fndbyte
-.extern zap_fndchr
-.extern zap_foreach
-.extern zap_memcmp
-.extern zap_memcpy
-.extern zap_memeq
-.extern zap_memfill
-.extern zap_memfill
-.extern zap_strcmp
-.extern zap_strcpy
-.extern zap_streq
-.extern zap_strfill
-.extern zap_strlen
-
-#else
+#include <zap/bs.h>
#if defined(sus_lang_cxx)
extern "C" {
#endif
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndbyte( void const * ptr, size_t num, unsigned char byte);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndchr( char const * str, char chr);
-sus_attr_hot void zap_foreach( void * ptr, size_t sz, size_t num, void (* fn)(void *));
-sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_memcmp( void const * lstr,size_t num, void const * rstr);
-sus_attr_hot sus_attr_nothrw void zap_memcpy( void const * in, size_t num, void * out);
-sus_attr_alloc sus_attr_allocsz(0x2) sus_attr_hot sus_attr_nothrw sus_attr_useret void * zap_memdup( void const * ptr, size_t num);
-sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_memeq( void const * lptr,size_t num, void const * rptr);
-sus_attr_hot sus_attr_nothrw void zap_memfill( void * ptr, size_t num, unsigned char val);
-sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_strcmp( char const * lstr,char const * rstr);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strcpy( char const * in, char * out);
-sus_attr_alloc sus_attr_hot sus_attr_nothrw sus_attr_useret char * zap_strdup( char const * str);
-sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_streq( char const * lstr,char const * rstr);
-sus_attr_hot sus_attr_nothrw void zap_strfill( char * lstr,char chr);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strlen( char const * str);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_sz zap_fndbyte( void const * ptr, zap_sz num, unsigned char byte);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_sz zap_fndchr( char const * str, char chr);
+__attribute__ ((hot)) void zap_foreach( void * ptr, zap_sz sz, zap_sz num, void (* fn)(void *));
+__attribute__ ((hot,nothrow)) void zap_memcat( void const * lptr, zap_sz llen,void const * rptr, zap_sz rlen, void * buf);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_cmp zap_memcmp( void const * lstr, zap_sz num, void const * rstr);
+__attribute__ ((hot,nothrow)) void zap_memcp( void const * in, zap_sz num, void * out);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_bool zap_memeq( void const * lptr, zap_sz num, void const * rptr);
+__attribute__ ((hot,nothrow)) void zap_memfill( void * ptr, zap_sz num, unsigned char val);
+__attribute__ ((hot)) void zap_memgen( void * ptr, zap_sz sz, zap_sz num, void (* fn)(zap_sz,void *));
+__attribute__ ((hot,nothrow)) void zap_strcat( char const * lstr, char const * rstr,char * buf);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_cmp zap_strcmp( char const * lstr, char const * rstr);
+__attribute__ ((hot,nothrow)) zap_sz zap_strcp( char const * in, char * out);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_bool zap_streq( char const * lstr, char const * rstr);
+__attribute__ ((hot,nothrow)) zap_sz zap_strfill( char * lstr, char chr);
+__attribute__ ((hot,nothrow,warn_unused_result)) zap_sz zap_strlen( char const * str);
+__attribute__ ((hot,nothrow)) void zap_utf8dec( zap_chr8 const * in, zap_chr20 * out);
+__attribute__ ((hot,nothrow)) zap_sz zap_utf8declen(zap_chr8 const * utf8);
+__attribute__ ((hot,nothrow)) void zap_utf8enc( zap_chr20 const * in, zap_chr8 * out);
+__attribute__ ((hot,nothrow)) zap_sz zap_utf8enclen(zap_chr20 const * utf20);
+__attribute__ ((hot,nothrow)) void zap_win1252dec(zap_chr8 const * in, zap_chr20 * out);
+__attribute__ ((hot,nothrow)) void zap_win1252enc(zap_chr20 const * in, zap_chr8 * out);
-#endif
#if defined(sus_lang_cxx)
}
#endif
diff --git a/zap/src/abs.c b/zap/src/abs.c
deleted file mode 100644
index 8fe97e6..0000000
--- a/zap/src/abs.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/math.h>
-
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_abs_c\n"
- ".globl zap_abs_i\n"
- ".globl zap_abs_l\n"
- ".globl zap_abs_ll\n"
- ".globl zap_abs_s\n"
-
- "zap_abs_c:\n"
- /*
- signed char val
- */
-#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
- "movb %dil,%al\n"
- "sarb $0x3F,%al\n"
- "xorb %al,%dil\n"
- "subb %al,%dil\n"
- "movb %dil,%al\n"
- "ret\n"
-#endif
-
- "zap_abs_i:\n"
- /*
- int val
- */
-#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
- "movl %edi,%eax\n"
- "sarl $0x3F,%eax\n"
- "xorl %eax,%edi\n"
- "subl %eax,%edi\n"
- "movl %edi,%eax\n"
- "ret\n"
-#endif
-
- "zap_abs_l:\n"
- /*
- long val
- */
-#if defined(sus_arch_amd64)
- "movq %rdi,%rax\n"
- "sarq $0x3F,%rax\n"
- "xorq %rax,%rdi\n"
- "subq %rax,%rdi\n"
- "movq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_abs_ll:\n"
- /*
- long long val
- */
-#if defined(sus_arch_amd64)
- "movq %rdi,%rax\n"
- "sarq $0x3F,%rax\n"
- "xorq %rax,%rdi\n"
- "subq %rax,%rdi\n"
- "movq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_abs_s:\n"
- /*
- short val
- */
-#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
- "movw %di,%ax\n"
- "sarw $0x3F,%ax\n"
- "xorw %ax,%di\n"
- "subw %ax,%di\n"
- "movw %di,%ax\n"
- "ret\n"
-#endif
-);
-#else
-#define zap_local_abs(_typ,_sufx) \
- _typ zap_abs_ ## _sufx (_typ const _val) {return _val > (_typ)0x0 ? _val : -_val;}
-
-zap_local_abs(signed char,c)
-zap_local_abs(int,i)
-zap_local_abs(long,l)
-zap_local_abs(long long,ll)
-zap_local_abs(short,s)
-
-#endif
diff --git a/zap/src/fastimpl.c b/zap/src/fastimpl.c
deleted file mode 100644
index 2541a41..0000000
--- a/zap/src/fastimpl.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-
-bool const zap_fastimpl = zap_priv_fastimpl;
diff --git a/zap/src/fma.c b/zap/src/fma.c
deleted file mode 100644
index b2f45ad..0000000
--- a/zap/src/fma.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/math.h>
-
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_fma_c\n"
- ".globl zap_fma_i\n"
- ".globl zap_fma_l\n"
- ".globl zap_fma_ll\n"
- ".globl zap_fma_s\n"
- ".globl zap_fma_uc\n"
- ".globl zap_fma_ui\n"
- ".globl zap_fma_ul\n"
- ".globl zap_fma_ull\n"
- ".globl zap_fma_us\n"
-
- "zap_fma_c:\n"
- /*
- signed char a
- signed char b
- signed char c
- */
-#if defined(sus_arch_amd64)
- "movb %sil,%al\n"
- "imulb %dl\n"
- "addb %dil,%al\n"
- "ret\n"
-#endif
-
- "zap_fma_i:\n"
- /*
- int a
- int b
- int c
- */
-#if defined(sus_arch_amd64)
- "movl %edx,%eax\n"
- "imull %esi\n"
- "addl %edi,%eax\n"
- "ret\n"
-#endif
-
- "zap_fma_l:\n"
- /*
- long a
- long b
- long c
- */
-#if defined(sus_arch_amd64)
- "movq %rdx,%rax\n"
- "imulq %rsi\n"
- "addq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_fma_ll:\n"
- /*
- long long a
- long long b
- long long c
- */
-#if defined(sus_arch_amd64)
- "movq %rdx,%rax\n"
- "imulq %rsi\n"
- "addq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_fma_s:\n"
- /*
- short a
- short b
- short c
- */
-#if defined(sus_arch_amd64)
- "movw %dx,%ax\n"
- "imulw %si\n"
- "addw %di,%ax\n"
- "ret\n"
-#endif
-
- "zap_fma_uc:\n"
- /*
- unsigned char a
- unsigned char b
- unsigned char c
- */
-#if defined(sus_arch_amd64)
- "movb %sil,%al\n" /* mulb uses ax instead of al:dl (like the other variants), so we don't need to worry about it overwritting dl. */
- "mulb %dl\n"
- "addb %dil,%al\n"
- "ret\n"
-#endif
-
- "zap_fma_ui:\n"
- /*
- unsigned int a
- unsigned int b
- unsigned int c
- */
-#if defined(sus_arch_amd64)
- "movl %edx,%eax\n"
- "mull %esi\n"
- "addl %edi,%eax\n"
- "ret\n"
-#endif
-
- "zap_fma_ul:\n"
- /*
- unsigned long a
- unsigned long b
- unsigned long c
- */
-#if defined(sus_arch_amd64)
- "movq %rdx,%rax\n"
- "mulq %rsi\n"
- "addq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_fma_ull:\n"
- /*
- unsigned long long a
- unsigned long long b
- unsigned long long c
- */
-#if defined(sus_arch_amd64)
- "movq %rdx,%rax\n" /* rdx get overwritten by mulq, so might as well just make it the first operand (in multiplication, the order is meaningless). */
- "mulq %rsi\n"
- "addq %rdi,%rax\n"
- "ret\n"
-#endif
-
- "zap_fma_us:\n"
- /*
- unsigned short a
- unsigned short b
- unsigned short c
- */
-#if defined(sus_arch_amd64)
- "movw %dx,%ax\n"
- "mulw %si\n"
- "addw %di,%ax\n"
- "ret\n"
-#endif
-);
-#else
-#define zap_local_fma(_typ,_sufx) \
- _typ zap_fma_ ## _sufx (_typ const _a,_typ const _b,_typ const _c) {return _a + _b * _c;}
-
-zap_local_fma(signed char,c)
-zap_local_fma(int,i)
-zap_local_fma(long,l)
-zap_local_fma(long long,ll)
-zap_local_fma(short,s)
-zap_local_fma(unsigned char,uc)
-zap_local_fma(unsigned int,ui)
-zap_local_fma(unsigned long,ul)
-zap_local_fma(unsigned long long,ull)
-zap_local_fma(unsigned short,us)
-
-#endif
diff --git a/zap/src/fndbyte.c b/zap/src/fndbyte.c
deleted file mode 100644
index e6e6070..0000000
--- a/zap/src/fndbyte.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_fndbyte\n"
-
- "zap_fndbyte:\n"
- /*
- void const * pos
- size_t num
- unsigned char byte
- */
-#if defined(sus_arch_amd64)
- /* rax: Address of the current element. */
- "movq %rdi,%rax\n"
- /* rsi: Address of the element after the last element. */
- "addq %rdi,%rsi\n"
- /* rcx: Current element. */
- ".loop:\n"
- "cmpq %rax,%rsi\n"
- "je .nfnd\n" /* We have went through the entire array without finding the byte. */
- "movb (%rax),%cl\n"
- "cmpb %cl,%dl\n"
- "je .fnd\n" /* We have found the byte. */
- "incq %rax\n"
- "jmp .loop\n"
- ".fnd:\n"
- "subq %rdi,%rax\n"
- "ret\n"
- ".nfnd:\n"
- "movq $0xFFFFFFFFFFFFFFFF,%rax\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current element. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Address of the element after the last element. */
- "movl 0x8(%esp),%ecx\n"
- "addl %eax,%ecx\n"
- /* edx: Byte value. */
- "movb 0xC(%esp),%dl\n"
- /* ebx: Current element. */
- "pushl %ebx\n"
- ".loop:\n"
- "cmpl %eax,%ecx\n"
- "je .nfnd\n" /* We have went through the entire array without finding the byte. */
- "movb (%eax),%bl\n"
- "cmpb %bl,%dl\n"
- "je .fnd\n" /* We have found the byte. */
- "incl %eax\n"
- "jmp .loop\n"
- ".fnd:\n"
- "popl %ebx\n"
- "subl 0x4(%esp),%eax\n"
- "ret\n"
- ".nfnd:\n"
- "popl %ebx\n"
- "movl $0xFFFFFFFF,%eax\n"
- "ret\n"
-#endif
-);
-#else
-size_t zap_fndbyte(void const * const _ptr,size_t const _num,unsigned char const _byte) {
- unsigned char const * startpos = _ptr;
- unsigned char const * pos = startpos;
- unsigned char const * const afterbuf = pos + _num;
- for (;pos != afterbuf;++pos) {sus_unlikely (*pos == _byte) {return pos - startpos;}}
- return SIZE_MAX;
-}
-#endif
diff --git a/zap/src/fndchr.c b/zap/src/fndchr.c
deleted file mode 100644
index fc4eb2b..0000000
--- a/zap/src/fndchr.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_fndchr\n"
-
- "zap_fndchr:\n"
- /*
- char const * str
- char chr
- */
-#if defined(sus_arch_amd64)
- /* rax: Address of the current character. */
- "movq %rdi,%rax\n"
- /* rdx: Current character. */
- ".loop:\n"
- "movb (%rax),%dl\n"
- "cmpb %dl,%sil\n"
- "je .fnd\n" /* Exit loop if we have found the character. */
- "testb %dl,%dl\n"
- "je .nfnd\n" /* We encountered the null-terminator but not the specified character. */
- "incq %rax\n"
- "jmp .loop\n"
- ".fnd:\n"
- "subq %rdi,%rax\n"
- "ret\n"
- ".nfnd:\n"
- "movq $0xFFFFFFFFFFFFFFFF,%rax\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current character. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Character. */
- "movb 0x8(%esp),%cl\n"
- /* edx: Current character. */
- ".loop:\n"
- "movb (%eax),%dl\n"
- "cmpb %dl,%cl\n"
- "je .fnd\n" /* Exit loop if we have found the character. */
- "testb %dl,%dl\n"
- "je .nfnd\n" /* We encountered the null-terminator but not the specified character. */
- "incl %eax\n"
- "jmp .loop\n"
- ".fnd:\n"
- "subl 0x4(%esp),%eax\n"
- "ret\n"
- ".nfnd:\n"
- "movl $0xFFFFFFFF,%eax\n"
- "ret\n"
-#endif
-);
-#else
-size_t zap_fndchr(char const * const _str,char const _chr) {
- char const * pos = _str;
- for (;;++pos) {
- char const chr = *pos;
- sus_unlikely (chr == _chr) {return (size_t)(pos - _str);}
- sus_unlikely (chr == '\x0') {return SIZE_MAX;}
- }
- sus_unreach();
-}
-#endif
diff --git a/zap/src/mem/fndbyte.S b/zap/src/mem/fndbyte.S
new file mode 100644
index 0000000..4413b42
--- /dev/null
+++ b/zap/src/mem/fndbyte.S
@@ -0,0 +1,59 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_fndbyte
+
+zap_fndbyte:
+
+ /*
+ void const * ptr
+ zap_sz num
+ unsigned char byte
+ */
+
+#if defined(__amd64__)
+
+ # rax: Address of the current element.
+ # rdi: Address of the first element.
+ # rsi: Address of the element after the last element.
+ # rdx: Byte value.
+ # rcx: Current byte.
+
+ movq %rdi,%rax
+
+ addq %rdi,%rsi
+
+ # Iterate over the array:
+.loop:
+
+ # Check if we have reached the end of the array:
+ cmpq %rax,%rsi
+ je .nfnd
+
+ # Check if we have found the byte value:
+ movb (%rax),%cl
+ cmpb %cl,%dl
+ je .fnd
+
+ # Continue to the next byte:
+ incq %rax
+ jmp .loop
+
+ # Found:
+.fnd:
+
+ subq %rdi,%rax
+ ret
+
+ # Not found:
+.nfnd:
+
+ movq $0xFFFFFFFFFFFFFFFF,%rax
+ ret
+
+#endif
diff --git a/zap/src/mem/fndchr.S b/zap/src/mem/fndchr.S
new file mode 100644
index 0000000..2982e7e
--- /dev/null
+++ b/zap/src/mem/fndchr.S
@@ -0,0 +1,57 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Pudhic License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_fndchr
+
+zap_fndchr:
+
+ /*
+ char const * str
+ char chr
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Address of the first character.
+ # rsi: Character to be found.
+ # rax: Address of the current character.
+ # rdx: Current character.
+
+ movq %rdi,%rax
+
+ # Iterate over the string:
+.loop:
+
+ # Copy the character into a register:
+ movb (%rax),%dl
+
+ # Check if we have found the character:
+ cmpb %dl,%sil
+ je .fnd
+
+ # Check if we have found the null-terminator:
+ testb %dl,%dl
+ jz .nfnd
+
+ # Continue to the next character:
+ incq %rax
+ jmp .loop
+
+ # Found:
+.fnd:
+
+ subq %rdi,%rax
+ ret
+
+ # Not found:
+.nfnd:
+
+ movq $0xFFFFFFFFFFFFFFFF,%rax
+ ret
+
+#endif
diff --git a/zap/src/mem/foreach.S b/zap/src/mem/foreach.S
new file mode 100644
index 0000000..fe96538
--- /dev/null
+++ b/zap/src/mem/foreach.S
@@ -0,0 +1,71 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_foreach
+
+zap_foreach:
+
+ /*
+ void * ptr
+ zap_sz sz
+ zap_sz num
+ void (* fn)(void *)
+ */
+
+#if defined(__amd64__)
+
+ # rbx: Address of the current element.
+ # r12: Address of the element after the last input element.
+ # r13: Size of each input element.
+ # r14: Address of the function.
+
+ # We're gonna use callee-saved registers for storing values so they don't get overwritten with each function call.
+
+ # Push the callee-saved registers:
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ pushq %r14
+
+ # Move registers into place:
+ movq %rdi,%rbx
+ movq %rsi,%r13
+ movq %rcx,%r14
+
+ # Get the one-past-the-end address:
+ movq %rdx,%r12
+ imulq %r13,%r12 # Calculate the array size in bytes (sz * num). We're using signed multiply because the equivalent using the unsigned instruction would use more instructions.
+ addq %rbx,%r12
+
+ # Iterate through the array:
+.loop:
+
+ # Check if we have reached the one-past-the-end address:
+ cmpq %rbx,%r12
+ je .done
+
+ # Call the provided function:
+ movq %rbx,%rdi # Provide the current address to the function.
+ call *%r14 # We don't need to save any registers for this as we only use callee-saved registers.
+
+ # Continue to the next element:
+ addq %r13,%rbx
+ jmp .loop
+
+ # Finish:
+.done:
+
+ # Restore the callee-saved registers:
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbx
+
+ ret
+
+#endif
diff --git a/zap/src/strdup.c b/zap/src/mem/memcat.c
index 183a909..f3e9a9b 100644
--- a/zap/src/strdup.c
+++ b/zap/src/mem/memcat.c
@@ -8,12 +8,9 @@
#include <zap/mem.h>
-#include <stdlib.h>
+#include <stddef.h>
-char * zap_strdup(sus_attr_unused char const * const _str) {
-#if !defined(zap_priv_nostdlib)
- return zap_memdup(_str,zap_strlen(_str) + 0x1u);
-#else
- return NULL;
-#endif
+void zap_memcat(void const * const _lptr,zap_sz const _llen,void const * const _rptr,zap_sz const _rlen,void * const _buf) {
+ zap_memcp(_lptr,_llen,_buf);
+ zap_memcp(_rptr,_rlen,(unsigned char *)_buf + _llen);
}
diff --git a/zap/src/memcmp.c b/zap/src/mem/memcmp.c
index 0fdf13a..601da99 100644
--- a/zap/src/memcmp.c
+++ b/zap/src/mem/memcmp.c
@@ -8,16 +8,14 @@
#include <zap/mem.h>
-#include <stddef.h>
-
-int_least8_t zap_memcmp(void const * const _lstr,size_t const _num,void const * const _rstr) {
+zap_cmp zap_memcmp(void const * const _lstr,zap_sz const _num,void const * const _rstr) {
unsigned char const * lpos = _lstr;
unsigned char const * rpos = _rstr;
unsigned char const * const afterlbuf = lpos + _num;
for (;lpos != afterlbuf;++lpos,++rpos) {
unsigned char const lbyte = *lpos;
unsigned char const rbyte = *rpos;
- sus_likely (lbyte != rbyte) {return lbyte < rbyte ? INT_LEAST8_MIN : INT_LEAST8_MAX;}
+ sus_likely (lbyte != rbyte) {return lbyte < rbyte ? zap_lt : zap_gt;}
}
- return 0x0;
+ return zap_eq;
}
diff --git a/zap/src/mem/memcp.S b/zap/src/mem/memcp.S
new file mode 100644
index 0000000..ead0718
--- /dev/null
+++ b/zap/src/mem/memcp.S
@@ -0,0 +1,107 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_memcp
+
+zap_memcp:
+
+ /*
+ void const * in
+ zap_sz num
+ void * out
+ */
+#if defined(__amd64__)
+
+ # rdi: Address of the current input element.
+ # rsi: Number of remaining elements.
+ # rdx: Address of the current output element.
+ # rcx: Current element.
+ # xmm0: Current element.
+ # ymm0: Current element.
+
+#if defined(__AVX__)
+ # AVX support 256-bit moves.
+
+ # Copy 32 bytes:
+.big20cp:
+
+ # Check if there are at least 32 bytes remaining:
+ cmpq $0x20,%rsi
+ jl .big10cp # If not, skip to the 10 byte copying.
+
+ # Copy:
+ vmovups (%rdi),%ymm0 # Move into a register.
+ vmovups %ymm0,(%rdx) # And then back into memory.
+
+ # Continue:
+ addq $0x20,%rdi
+ addq $0x20,%rdx
+ subq $0x20,%rsi
+ jmp .big20cp
+
+#endif
+
+ # AMD64 requires SSE(2).
+
+ # Copy 16 bytes:
+.big10cp:
+
+ # Check if there are at least 16 bytes remaining:
+ cmpq $0x10,%rsi
+ jl .wrdcp
+
+ # Copy:
+ movdqu (%rdi),%xmm0
+ movdqu %xmm0,(%rdx)
+
+ # Continue:
+ addq $0x10,%rdi
+ addq $0x10,%rdx
+ subq $0x10,%rsi
+ jmp .big10cp
+
+ # Copy one word (8 bytes):
+.wrdcp:
+
+ # Check if there are at least 8 bytes remaining:
+ cmpq $0x8,%rsi
+ jl .bytecp
+
+ # Copy:
+ movq (%rdi),%rcx
+ movq %rcx,(%rdx)
+
+ # Continue:
+ addq $0x8,%rdi
+ addq $0x8,%rdx
+ subq $0x8,%rsi
+ jmp .wrdcp
+
+ # Copy one byte:
+.bytecp:
+
+ # Check if we have any bytes remaining:
+ testq %rsi,%rsi
+ jz .done
+
+ # Copy:
+ movb (%rdi),%cl
+ movb %cl,(%rdx)
+
+ # Continue:
+ incq %rdi
+ incq %rdx
+ decq %rsi
+ jmp .bytecp
+
+ # Finish:
+.done:
+
+ ret
+
+#endif
diff --git a/zap/src/mem/memeq.S b/zap/src/mem/memeq.S
new file mode 100644
index 0000000..cf554c2
--- /dev/null
+++ b/zap/src/mem/memeq.S
@@ -0,0 +1,82 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_memeq
+
+zap_memeq:
+
+ /*
+ void const * lptr
+ zap_sz num
+ void const * rptr
+ */
+
+#if defined(__amd64__)
+
+ /* rdi: Left pointer. */
+ /* rsi: Number of remaining elements. */
+ /* rdx: Right pointer. */
+ /* rax: Current left element. */
+ /* rcx: Current right element. */
+
+ /* Compare words: */
+.wrdcmp:
+
+ /* Check if there's at least one word left: */
+ cmpq $0x8,%rsi
+ jl .bytecmp /* If not, skip to byte checks: */
+
+ /* Copy the values into registers: */
+ movq (%rdi),%rax
+ movq (%rdx),%rcx
+
+ /* Check if the words are equal: */
+ cmpq %rax,%rcx
+ jne .neq
+
+ /* Mark eight more bytes as equal: */
+ addq $0x8,%rdi
+ addq $0x8,%rdx
+ subq $0x8,%rsi
+
+ /* Continue to the next word: */
+ jmp .wrdcmp
+
+ /* Compare bytes: */
+.bytecmp:
+
+ /* Check if there are any bytes left: */
+ testq %rsi,%rsi
+ jz .eq /* If we have reached the final element, all previous elements have compared equal, and the memory sequences are equal. */
+
+ /* Copy the values into registers: */
+ movb (%rdi),%al
+ movb (%rdx),%cl
+
+ cmpb %al,%cl
+ jne .neq
+
+ /* Mark another byte as equal: */
+ incq %rdi
+ incq %rdx
+ decq %rsi
+
+ /* Continue to the next byte: */
+ jmp .bytecmp
+
+ /* The memory sequences have compared equal: */
+.eq:
+ movb $0xFF,%al
+ ret
+
+ /* The memory sequences have compared NOT equal: */
+.neq:
+ movb $0x0,%al
+ ret
+
+#endif
diff --git a/zap/src/mem/memfill.S b/zap/src/mem/memfill.S
new file mode 100644
index 0000000..63a1aad
--- /dev/null
+++ b/zap/src/mem/memfill.S
@@ -0,0 +1,45 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_memfill
+
+zap_memfill:
+
+ /*
+ void const * ptr
+ zap_sz num
+ unsigned char val
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Address of the current element.
+ # rsi: Address of the element after the last element.
+ # rdx: Byte value.
+
+ addq %rdi,%rsi
+
+ # Iterate over buffer:
+.loop:
+
+ # Check if we have reached the final element:
+ cmpq %rdi,%rsi
+ je .done # Exit loop if we have.
+
+ # Set the value of the current element:
+ movb %dl,(%rdi)
+
+ # Continue to next element:
+ incq %rdi
+ jmp .loop
+
+ # Finish:
+.done:
+ ret
+
+#endif
diff --git a/zap/src/mem/memgen.c b/zap/src/mem/memgen.c
new file mode 100644
index 0000000..a39e326
--- /dev/null
+++ b/zap/src/mem/memgen.c
@@ -0,0 +1,25 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+/*.globl zap_memgen
+
+zap_memgen:*/
+
+ /*
+ void * ptr
+ zap_sz sz
+ zap_sz num
+ void (* fn)(zap_sz,void *)
+ */
+
+void zap_memgen(void * const _ptr,zap_sz const _sz,zap_sz const _num,void (* const _fn)(zap_sz,void *)) {
+ unsigned char * ptr = _ptr;
+ unsigned char * const afterbuf = ptr + _sz * _num;
+ for (;ptr != afterbuf;ptr += _sz) {_fn((ptr - (unsigned char *)_ptr) / _sz,ptr);}
+}
+
diff --git a/zap/src/foreach.c b/zap/src/mem/strcat.c
index 5e281d4..f7f66c8 100644
--- a/zap/src/foreach.c
+++ b/zap/src/mem/strcat.c
@@ -10,9 +10,10 @@
#include <stddef.h>
-void zap_foreach(void * const _ptr,size_t const _sz,size_t const _num,void (* const _fn)(void *)) {
- unsigned char * pos = _ptr;
- size_t const numbyte = _sz * _num;
- unsigned char * const afterbuf = pos + numbyte;
- for (;pos != afterbuf;pos += _sz) {_fn(pos);}
+void zap_strcat(char const * const _lstr,char const * const _rstr,char * const _buf) {
+ zap_sz const llen = zap_strlen (_lstr);
+ zap_sz const rlen = zap_strlen (_rstr);
+ zap_memcp(_lstr,llen,_buf);
+ zap_memcp(_rstr,rlen,_buf + llen);
+ _buf[llen + rlen] = '\x0';
}
diff --git a/zap/src/strcmp.c b/zap/src/mem/strcmp.c
index 0ed0a59..691717a 100644
--- a/zap/src/strcmp.c
+++ b/zap/src/mem/strcmp.c
@@ -10,14 +10,14 @@
#include <stdint.h>
-int_least8_t zap_strcmp(char const * const _lstr,char const * const _rstr) {
+zap_cmp zap_strcmp(char const * const _lstr,char const * const _rstr) {
unsigned char const * lpos = (unsigned char const *)_lstr;
unsigned char const * rpos = (unsigned char const *)_rstr;
for (;;++lpos,++rpos) {
unsigned char const lchr = *lpos;
unsigned char const rchr = *rpos;
- sus_likely (lchr != rchr) {return lchr < rchr ? INT_LEAST8_MIN : INT_LEAST8_MAX;}
- sus_unlikely (lchr == (unsigned char)0x0) {return 0x0;}
+ sus_likely (lchr != rchr) {return lchr < rchr ? zap_lt : zap_gt;}
+ sus_unlikely (lchr == (unsigned char)0x0) {return zap_eq;}
}
sus_unreach();
}
diff --git a/zap/src/mem/strcp.S b/zap/src/mem/strcp.S
new file mode 100644
index 0000000..04c3198
--- /dev/null
+++ b/zap/src/mem/strcp.S
@@ -0,0 +1,53 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_strcp
+
+zap_strcp:
+
+ /*
+ char const * in
+ char const * out
+ */
+
+#if defined(__amd64__)
+
+ # rax: Address of the current input character.
+ # rdi: Address of the first input character.
+ # rsi: Address of the current output character.
+ # rdx: Current character.
+
+ movq %rdi,%rax
+
+ # Iterate over the strings:
+.loop:
+
+ # Copy character:
+ movb (%rax),%dl # Move it into a register...
+ movb %dl,(%rsi) # ... and then back into memory.
+
+ # Check if we have reached the null-terminator:
+ testb %dl,%dl
+ jz .done
+
+ # Continue to the next character:
+
+ incq %rax
+ incq %rsi
+ jmp .loop
+
+ # Finish:
+.done:
+
+ # Get the length of the (input) string:
+ subq %rdi,%rax
+ decq %rax # We do not count the null-terminator in the string length.
+
+ ret
+
+#endif
diff --git a/zap/src/mem/streq.S b/zap/src/mem/streq.S
new file mode 100644
index 0000000..d331e93
--- /dev/null
+++ b/zap/src/mem/streq.S
@@ -0,0 +1,57 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_streq
+
+zap_streq:
+
+ /*
+ char const * lstr
+ char const * rstr
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Address of the current left character.
+ # rsi: Address of the current right character.
+ # rax: Current left character.
+ # rdx: Current right character.
+
+ # Iterate over the strings:
+.loop:
+
+ # Copy the characters into registers:
+ movb (%rdi),%al
+ movb (%rsi),%dl
+
+ # Check if the characters are equal:
+ cmpb %al,%dl
+ jne .neq # If not, the strings also aren't equal.
+
+ # Check if we have reached the null-terminator:
+ testb %al,%al
+ jz .eq # If so, all previous characters have compared equal, and the strings are equal.
+
+ # Continue to the next characters:
+ incq %rdi
+ incq %rsi
+ jmp .loop
+
+ # The strings have compared equal:
+.eq:
+
+ movb $0xFF,%al
+ ret
+
+ /* The strings have compared unequal: */
+.neq:
+
+ movb $0x0,%al
+ ret
+
+#endif
diff --git a/zap/src/mem/strfill.S b/zap/src/mem/strfill.S
new file mode 100644
index 0000000..277865e
--- /dev/null
+++ b/zap/src/mem/strfill.S
@@ -0,0 +1,48 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_strfill
+
+zap_strfill:
+
+ /*
+ char * str
+ char chr
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Address of the first character of the string.
+ # rsi: Fill character.
+ # rax: Address of the current character.
+
+ movq %rdi,%rax
+
+ # Iterate over string:
+.loop:
+
+ # Check if we have reached the null-terminator:
+ cmpb $0x0,(%rax)
+ je .done # Exit loop if we have.
+
+ # Set the value of the current element:
+ movb %sil,(%rax)
+
+ # Continue to next character:
+ incq %rax
+ jmp .loop
+
+ # Finish:
+.done:
+
+ # Get the length of the string:
+ subq %rdi,%rax
+
+ ret
+
+#endif
diff --git a/zap/src/mem/strlen.S b/zap/src/mem/strlen.S
new file mode 100644
index 0000000..4cb435f
--- /dev/null
+++ b/zap/src/mem/strlen.S
@@ -0,0 +1,46 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_strlen
+
+zap_strlen:
+
+ /*
+ char const * str
+ */
+
+#if defined(__amd64__)
+
+ # rax: Address of the current character.
+ # rdx: Current character.
+
+ movq %rdi,%rax
+
+ # Iterate over the string:
+.loop:
+
+ # Move the character into a register:
+ movb (%rax),%dl
+
+ # Check if we have reached the null-terminator:
+ testb %dl,%dl
+ jz .done # If so, we are done.
+
+ # Continue to the next character:
+ incq %rax
+ jmp .loop
+
+ # Done:
+.done:
+
+ # Get the length:
+ subq %rdi,%rax
+
+ ret
+
+#endif
diff --git a/zap/src/mem/utf8dec.c b/zap/src/mem/utf8dec.c
new file mode 100644
index 0000000..32ebd00
--- /dev/null
+++ b/zap/src/mem/utf8dec.c
@@ -0,0 +1,51 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/mem.h>
+
+void zap_utf8dec(zap_chr8 const * const _in,zap_chr20 * const _out) {
+ zap_chr8 const * in = _in;
+ zap_chr20 * out = _out;
+ for (;;++out) {
+ zap_chr8 const oct = *in;
+ if (oct >= 0xF0u) { /* Four octets. */
+ zap_chr20 chr = ((zap_chr20)oct ^ 0xF0u) << 0x12u;
+ ++in;
+ chr += ((zap_chr20)*in ^ 0x80u) << 0xCu;
+ ++in;
+ chr += ((zap_chr20)*in ^ 0x80u) << 0x6u;
+ ++in;
+ chr += (zap_chr20)*in ^ 0x80u;
+ ++in;
+ *out = chr;
+ continue;
+ }
+ if (oct >= 0xE0u) { /* Three octets. */
+ zap_chr20 chr = ((zap_chr20)oct ^ 0xE0u) << 0xCu;
+ ++in;
+ chr += ((zap_chr20)*in ^ 0x80u) << 0x6u;
+ ++in;
+ chr += (zap_chr20)*in ^ 0x80u;
+ ++in;
+ *out = chr;
+ continue;
+ }
+ if (oct >= 0xC0u) { /* Two octets. */
+ zap_chr20 chr = ((zap_chr20)oct ^ 0xC0u) << 0x6u;
+ ++in;
+ chr += (zap_chr20)*in ^ 0x80u;
+ ++in;
+ *out = chr;
+ continue;
+ }
+ /* One octet. */
+ *out = oct;
+ ++in;
+ sus_unlikely (oct == 0x0u) {break;}
+ }
+}
diff --git a/zap/src/mem/utf8declen.c b/zap/src/mem/utf8declen.c
new file mode 100644
index 0000000..202e995
--- /dev/null
+++ b/zap/src/mem/utf8declen.c
@@ -0,0 +1,35 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/mem.h>
+
+#include <stddef.h>
+
+zap_sz zap_utf8declen(zap_chr8 const * const _in) {
+ zap_sz len = 0x0u;
+ zap_chr8 const * in;
+ for (in = _in;;++len) {
+ zap_chr8 const oct = *in;
+ sus_unlikely (oct == 0x0u) {break;}
+ if (oct >= 0xF0u) {
+ in += 0x4u;
+ continue;
+ }
+ if (oct >= 0xE0u) {
+ in += 0x3u;
+ continue;
+ }
+ if (oct >= 0xC0u) {
+ in += 0x2u;
+ continue;
+ }
+ ++in;
+ continue;
+ }
+ return len;
+}
diff --git a/zap/src/mem/utf8enc.S b/zap/src/mem/utf8enc.S
new file mode 100644
index 0000000..24e09d8
--- /dev/null
+++ b/zap/src/mem/utf8enc.S
@@ -0,0 +1,152 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_utf8enc
+
+zap_utf8enc:
+
+ /*
+ zap_chr20 const * in
+ zap_chr8 * out
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Current input codepoint.
+ # rsi: Current output octet.
+ # rax: Current codepoint.
+ # rdx: Temporary.
+
+ # Iterate over the input:
+.loop:
+
+ movl (%rdi),%eax
+
+ cmpl $0xFFFF,%eax
+ jg .oct4
+
+ cmpl $0x7FF,%eax
+ jg .oct3
+
+ cmpl $0x7F,%eax
+ jg .oct2 # Otherwise, only one octet is needed.
+
+ # One octet:
+.oct1:
+
+ # Octet #0:
+ movb %al,(%rsi) # No conversion needed:
+
+ incq %rsi
+
+ # Test if we have reached the null-terminator:
+ testb %al,%al
+ jz .done
+
+ jmp .cnt
+
+ # Two octets:
+.oct2:
+
+ /* Octet #0: */
+ movl %eax,%edx
+ shrl $0x6,%edx
+ orb $0xC0,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #1:
+ movl %eax,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ jmp .cnt
+
+ # Three octets:
+.oct3:
+
+ # Octet #0:
+ movl %eax,%edx
+ shrl $0xC,%edx
+ orb $0xE0,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #1:
+ movl %eax,%edx
+ shrl $0x6,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #2:
+ movl %eax,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ jmp .cnt
+
+ # Four octets:/
+.oct4:
+
+ # Octet #0:
+ movl %eax,%edx
+ shrl $0x12,%edx
+ orb $0xF0,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #1:
+ movl %eax,%edx
+ shrl $0xC,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #2:
+ movl %eax,%edx
+ shrl $0x6,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Octet #3:
+ movl %eax,%edx
+ andb $0x3F,%dl
+ orb $0x80,%dl
+ movb %dl,(%rsi)
+
+ incq %rsi
+
+ # Continue to the next codepoint:
+.cnt:
+
+ addq $0x4,%rdi
+ jmp .loop
+
+ # Done:
+.done:
+
+ ret
+
+#endif
diff --git a/zap/src/mem/utf8enclen.S b/zap/src/mem/utf8enclen.S
new file mode 100644
index 0000000..1c80e6a
--- /dev/null
+++ b/zap/src/mem/utf8enclen.S
@@ -0,0 +1,80 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+.globl zap_utf8enclen
+
+zap_utf8enclen:
+
+ /*
+ zap_chr20 const * utf20
+ */
+
+#if defined(__amd64__)
+
+ # rdi: Address of the current character.
+ # rax: Length of the string.
+ # rsi: Current character.
+
+ movq $0x0,%rax
+
+ # Iterate over the input:
+.loop:
+
+ movl (%rdi),%esi
+
+ # Test if we have reached the null-terminator:
+ testl %esi,%esi
+ jz .done
+
+ cmpl $0xFFFF,%esi
+ jg .oct4
+
+ cmpl $0x7FF,%esi
+ jg .oct3
+
+ cmpl $0x7F,%esi
+ jg .oct2
+
+ # One octet:
+.oct1:
+
+ incq %rax
+
+ jmp .cnt
+
+ # Two octets:
+.oct2:
+
+ addq $0x2,%rax
+
+ jmp .cnt
+
+ # Three octets:
+.oct3:
+
+ addq $0x3,%rax
+
+ jmp .cnt
+
+ # Four octets:
+.oct4:
+
+ addq $0x4,%rax
+
+ # Continue to the next codepoint:
+.cnt:
+
+ addq $0x4,%rdi
+ jmp .loop
+
+ # Done:
+.done:
+
+ ret
+
+#endif
diff --git a/zap/src/mem/win1252dec.c b/zap/src/mem/win1252dec.c
new file mode 100644
index 0000000..529bbe3
--- /dev/null
+++ b/zap/src/mem/win1252dec.c
@@ -0,0 +1,111 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/mem.h>
+
+void zap_win1252dec(zap_chr8 const * const _in,zap_chr20 * const _out) {
+ zap_chr8 const * in = _in;
+ zap_chr20 * out = _out;
+ for (;;++in,++out) {
+ zap_chr8 const chr = *in;
+ switch (chr) {
+ default:
+ *out = *in;
+ break;
+ case 0x81: /* Bad characters. */
+ case 0x8D:
+ case 0x8F:
+ case 0x90:
+ case 0x9D:
+ *out = 0xFFFDu; /* REPLACEMENT CHARACTER */
+ break;
+ case 0x80:
+ *out = 0x20ACu;
+ break;
+ case 0x82:
+ *out = 0x201Au;
+ break;
+ case 0x83:
+ *out = 0x192u;
+ break;
+ case 0x84:
+ *out = 0x201Eu;
+ break;
+ case 0x85:
+ *out = 0x2026u;
+ break;
+ case 0x86:
+ *out = 0x2020u;
+ break;
+ case 0x87:
+ *out = 0x2021u;
+ break;
+ case 0x88:
+ *out = 0x2C6u;
+ break;
+ case 0x89:
+ *out = 0x2030u;
+ break;
+ case 0x8A:
+ *out = 0x160u;
+ break;
+ case 0x8B:
+ *out = 0x2039u;
+ break;
+ case 0x8C:
+ *out = 0x152u;
+ break;
+ case 0x8E:
+ *out = 0x17Du;
+ break;
+ case 0x91:
+ *out = 0x2018u;
+ break;
+ case 0x92:
+ *out = 0x2019u;
+ break;
+ case 0x93:
+ *out = 0x201Cu;
+ break;
+ case 0x94:
+ *out = 0x201Du;
+ break;
+ case 0x95:
+ *out = 0x2022u;
+ break;
+ case 0x96:
+ *out = 0x2013u;
+ break;
+ case 0x97:
+ *out = 0x2014u;
+ break;
+ case 0x98:
+ *out = 0x2DCu;
+ break;
+ case 0x99:
+ *out = 0x2122u;
+ break;
+ case 0x9A:
+ *out = 0x161u;
+ break;
+ case 0x9B:
+ *out = 0x203Au;
+ break;
+ case 0x9C:
+ *out = 0x153u;
+ break;
+ case 0x9E:
+ *out = 0x17Eu;
+ break;
+ case 0x9F:
+ *out = 0x178u;
+ break;
+ }
+ sus_unlikely (chr == 0x0u) {break;}
+ }
+}
diff --git a/zap/src/mem/win1252enc.c b/zap/src/mem/win1252enc.c
new file mode 100644
index 0000000..147ddaf
--- /dev/null
+++ b/zap/src/mem/win1252enc.c
@@ -0,0 +1,113 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/mem.h>
+
+void zap_win1252enc(zap_chr20 const * const _in,zap_chr8 * const _out) {
+ zap_chr20 const * in = _in;
+ zap_chr8 * out = _out;
+ for (;;++in,++out) {
+ zap_chr20 const chr = *in;
+ zap_chr8 const bad = 0x3Fu;
+ switch (chr) {
+ default:
+ sus_unlikely (chr > 0xFFu) {
+ *out = bad;
+ break;
+ }
+ sus_unlikely (chr >= 0x80u && chr <= 0x9Fu) {
+ *out = bad;
+ break;
+ }
+ *out = *in;
+ break;
+ case 0x20ACu:
+ *out = 0x80u;
+ break;
+ case 0x201Au:
+ *out = 0x82u;
+ break;
+ case 0x192u:
+ *out = 0x83u;
+ break;
+ case 0x201Eu:
+ *out = 0x84u;
+ break;
+ case 0x2026u:
+ *out = 0x85u;
+ break;
+ case 0x2020u:
+ *out = 0x86u;
+ break;
+ case 0x2021u:
+ *out = 0x87u;
+ break;
+ case 0x2C6u:
+ *out = 0x88u;
+ break;
+ case 0x2030u:
+ *out = 0x89u;
+ break;
+ case 0x160u:
+ *out = 0x8Au;
+ break;
+ case 0x2039u:
+ *out = 0x8Bu;
+ break;
+ case 0x152u:
+ *out = 0x8Cu;
+ break;
+ case 0x17Du:
+ *out = 0x8Eu;
+ break;
+ case 0x2018u:
+ *out = 0x91u;
+ break;
+ case 0x2019u:
+ *out = 0x92u;
+ break;
+ case 0x201Cu:
+ *out = 0x93u;
+ break;
+ case 0x201Du:
+ *out = 0x94u;
+ break;
+ case 0x2022u:
+ *out = 0x95u;
+ break;
+ case 0x2013u:
+ *out = 0x96u;
+ break;
+ case 0x2014u:
+ *out = 0x97u;
+ break;
+ case 0x2DCu:
+ *out = 0x98u;
+ break;
+ case 0x2122u:
+ *out = 0x99u;
+ break;
+ case 0x161u:
+ *out = 0x9Au;
+ break;
+ case 0x203Au:
+ *out = 0x9Bu;
+ break;
+ case 0x153u:
+ *out = 0x9Cu;
+ break;
+ case 0x17Eu:
+ *out = 0x9Eu;
+ break;
+ case 0x178u:
+ *out = 0x9Fu;
+ break;
+ }
+ sus_unlikely (chr == 0x0u) {break;}
+ }
+}
diff --git a/zap/src/memcpy.c b/zap/src/memcpy.c
deleted file mode 100644
index ae923c3..0000000
--- a/zap/src/memcpy.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_memcpy\n"
-
- "zap_memcpy:\n"
- /*
- void const * in
- size_t num
- void * out
- */
-#if defined(sus_arch_amd64)
- /* rdi: Address of the current input element. */
- /* rsi: Number of remaining elements. */
- /* rdx: Address of the current output element. */
- /* rcx: Current element. */
- /* xmm0: Current element. */
- /* ymm0: Current element. */
-#if defined(sus_archfeat_avx)
- ".big256cpy:\n"
- "cmpq $0x20,%rsi\n"
- "jl .big128cpy\n"
- "vmovups (%rdi),%ymm0\n"
- "vmovups %ymm0,(%rdx)\n"
- "addq $0x20,%rdi\n"
- "addq $0x20,%rdx\n"
- "subq $0x20,%rsi\n"
- "jmp .big256cpy\n"
-#endif
- ".big128cpy:\n"
- "cmpq $0x10,%rsi\n"
- "jl .wrdcpy\n"
- "movdqu (%rdi),%xmm0\n"
- "movdqu %xmm0,(%rdx)\n"
- "addq $0x10,%rdi\n"
- "addq $0x10,%rdx\n"
- "subq $0x10,%rsi\n"
- "jmp .big128cpy\n"
- ".wrdcpy:\n"
- "cmpq $0x8,%rsi\n"
- "jl .bytecpy\n"
- "movq (%rdi),%rcx\n"
- "movq %rcx,(%rdx)\n"
- "addq $0x8,%rdi\n"
- "addq $0x8,%rdx\n"
- "subq $0x8,%rsi\n"
- "jmp .wrdcpy\n"
- ".bytecpy:\n"
- "testq %rsi,%rsi\n"
- "jz .done\n"
- "movb (%rdi),%cl\n"
- "movb %cl,(%rdx)\n"
- "incq %rdi\n"
- "incq %rdx\n"
- "decq %rsi\n"
- "jmp .bytecpy\n"
- ".done:\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current input element. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Number of remaining elements. */
- "movl 0x8(%esp),%ecx\n"
- /* edx: Address of the current output element. */
- "movl 0xC(%esp),%edx\n"
- /* ebx: Current element. */
- "pushl %ebx\n" /* ebx must be restored. */
- /* xmm0: Current element. */
- /* ymm0: Current element. */
-#if defined(sus_archfeat_avx)
- ".big256cpy:\n"
- "cmpl $0x20,%ecx\n"
-#if defined(sus_archfeat_sse)
- "jl .big128cpy\n"
-#else
- "jl .wrdcpy\n"
-#endif
- "vmovdqu (%eax),%ymm0\n"
- "vmovdqu %ymm0,(%edx)\n"
- "addl $0x20,%eax\n"
- "addl $0x20,%edx\n"
- "subl $0x20,%ecx\n"
- "jmp .big256cpy\n"
-#endif
-#if defined(sus_archfeat_sse)
- ".big128cpy:\n"
- "cmpl $0x10,%ecx\n"
- "jl .wrdcpy\n"
-#if defined(sus_archfeat_sse2)
- "movdqu (%eax),%xmm0\n"
- "movdqu %xmm0,(%edx)\n"
-#else
- "movups (%eax),%xmm0\n"
- "movups %xmm0,(%edx)\n"
-#endif
- "addl $0x10,%eax\n"
- "addl $0x10,%edx\n"
- "subl $0x10,%ecx\n"
- "jmp .big128cpy\n"
-#endif
- ".wrdcpy:\n"
- "cmpl $0x4,%ecx\n"
- "jl .bytecpy\n"
- "movl (%eax),%ebx\n"
- "movl %ebx,(%edx)\n"
- "addl $0x4,%eax\n"
- "addl $0x4,%edx\n"
- "subl $0x4,%ecx\n"
- "jmp .wrdcpy\n"
- ".bytecpy:\n"
- "testl %ecx,%ecx\n"
- "jz .done\n"
- "movb (%eax),%bl\n"
- "movb %bl,(%edx)\n"
- "incl %eax\n"
- "incl %edx\n"
- "decl %ecx\n"
- "jmp .bytecpy\n"
- ".done:\n"
- "popl %ebx\n"
- "ret\n"
-#endif
-);
-#else
-void zap_memcpy(void const * const _in,size_t const _num,void * const _out) {
- unsigned char const * in = _in;
- unsigned char * out = _out;
- unsigned char const * const afterbuf = in + _num;
- for (;in != afterbuf;++in,++out) {*out = *in;}
-}
-#endif
diff --git a/zap/src/memdup.c b/zap/src/memdup.c
deleted file mode 100644
index 9b56314..0000000
--- a/zap/src/memdup.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stdlib.h>
-
-void * zap_memdup(sus_attr_unused void const * const _ptr,sus_attr_unused size_t const _num) {
-#if !defined(zap_priv_nostdlib)
- void * const dup = malloc(_num);
- sus_unlikely (dup == NULL) {return NULL;}
- zap_memcpy(_ptr,_num,dup);
- return dup;
-#else
- return NULL;
-#endif
-}
-
-
diff --git a/zap/src/memeq.c b/zap/src/memeq.c
deleted file mode 100644
index 7dce213..0000000
--- a/zap/src/memeq.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_memeq\n"
-
- "zap_memeq:\n"
- /*
- void const * lptr
- size_t num
- void const * rptr
- */
-#if defined(sus_arch_amd64)
- /* rdi: Address of the current left element. */
- /* rsi: Number of remaining elements. */
- /* rdx: Address of the current right element. */
- /* rax: Current left element. */
- /* rcx: Current right element. */
- ".wrdcmp:\n"
- "cmpq $0x8,%rsi\n"
- "jl .bytecmp\n"
- "movq (%rdi),%rax\n"
- "movq (%rdx),%rcx\n"
- "cmpq %rax,%rcx\n"
- "jne .neq\n"
- "addq $0x8,%rdi\n"
- "addq $0x8,%rdx\n"
- "subq $0x8,%rsi\n"
- "jmp .wrdcmp\n"
- ".bytecmp:\n"
- "testq %rsi,%rsi\n"
- "jne .eq\n" /* If we have reached the final element, all previous elements have compared equal, and the memory sequences are equal. */
- "movb (%rdi),%al\n"
- "movb (%rdx),%cl\n"
- "cmpb %al,%cl\n"
- "jne .neq\n"
- "incq %rdi\n"
- "incq %rdx\n"
- "decq %rsi\n"
- "jmp .bytecmp\n"
- ".eq:\n"
- "movb $0x1,%al\n"
- "ret\n"
- ".neq:\n"
- "movb $0x0,%al\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current left element. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Number of remaining elements. */
- "movl 0x8(%esp),%ecx\n"
- /* edx: Address of the current right element. */
- "movl 0xC(%esp),%edx\n"
- /* ebx: Current left element. */
- "pushl %ebx\n"
- /* ebx/esi: Current right element. */
- "pushl %esi\n"
- ".wrdcmp:\n"
- "cmpl $0x4,%ecx\n"
- "jl .bytecmp\n"
- "movl (%eax),%ebx\n"
- "movl (%edx),%esi\n"
- "cmpl %ebx,%esi\n"
- "jne .neq\n"
- "addl $0x4,%eax\n"
- "addl $0x4,%edx\n"
- "subl $0x4,%ecx\n"
- "jmp .wrdcmp\n"
- ".bytecmp:\n"
- "testl %ecx,%ecx\n"
- "jne .eq\n" /* If we have reached the final element, all previous elements have compared equal, and the memory sequences are equal. */
- "movb (%eax),%bl\n"
- "movb (%edx),%bh\n"
- "cmpb %bl,%bh\n"
- "jne .neq\n"
- "incl %eax\n"
- "incl %edx\n"
- "decl %ecx\n"
- "jmp .bytecmp\n"
- ".eq:\n"
- "popl %ebx\n"
- "popl %esi\n"
- "movb $0x1,%al\n"
- "ret\n"
- ".neq:\n"
- "popl %ebx\n"
- "popl %esi\n"
- "movb $0x0,%al\n"
- "ret\n"
-#endif
-);
-#else
-bool zap_memeq(void const * const _lptr,size_t const _num,void const * const _rptr) {
- unsigned char const * lpos = _lptr;
- unsigned char const * rpos = _rptr;
- unsigned char const * const afterbuf = lpos + _num;
- for (;lpos != afterbuf;++lpos,++rpos) {sus_likely (*lpos != *rpos) {return false;}}
- return true;
-}
-#endif
diff --git a/zap/src/memfill.c b/zap/src/memfill.c
deleted file mode 100644
index 1aebd29..0000000
--- a/zap/src/memfill.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_memfill\n"
-
- "zap_memfill:\n"
- /*
- void const * ptr
- size_t num
- unsigned char val
- */
-#if defined(sus_arch_amd64)
- /* rdi: Address of the current element. */
- /* rsi: Address of the element after the last element. */
- "addq %rdi,%rsi\n"
- ".loop:\n"
- "cmpq %rdi,%rsi\n"
- "je .done\n" /* Exit loop if we have reached the final element. */
- "movb %dl,(%rdi)\n"
- "incq %rdi\n"
- "jmp .loop\n" /* Continue to next element. */
- ".done:\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current element. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Address of the element after the last element. */
- "movl 0x4(%esp),%ecx\n"
- "addl 0x8(%esp),%ecx\n"
- /* edx: Byte value. */
- "movb 0xC(%esp),%dl\n"
- ".loop:\n"
- "cmpl %eax,%ecx\n"
- "je .done\n" /* Exit loop if we have reached the final element. */
- "movb %dl,(%eax)\n"
- "incl %eax\n"
- "jmp .loop\n" /* Continue to next element. */
- ".done:\n"
- "ret\n"
-#endif
-);
-#else
-void zap_memfill(void * const _ptr,size_t const _num,unsigned char const _byte) {
- unsigned char * pos = _ptr;
- unsigned char * const afterbuf = pos + _num;
- for (;pos != afterbuf;++pos) {*pos = _byte;}
-}
-#endif
diff --git a/zap/src/strcpy.c b/zap/src/strcpy.c
deleted file mode 100644
index 616af7f..0000000
--- a/zap/src/strcpy.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_strcpy\n"
-
- "zap_strcpy:\n"
- /*
- char const * in
- char const * out
- */
-#if defined(sus_arch_amd64)
- /* rax: Address of the current input character. */
- "movq %rdi,%rax\n"
- /* rsi: Address of the current output character. */
- "movq %rsi,%rsi\n"
- /* rdx: Current character. */
- ".loop:\n"
- "movb (%rax),%dl\n" /* Move current the character into a register... */
- "movb %dl,(%rsi)\n" /* ... and then back into memory. */
- "testb %dl,%dl\n" /* Check if we have reached the null-terminator... */
- "jz .done\n" /* ... and if so, we are finished copying. */
- "incq %rax\n" /* Increment the positions. */
- "incq %rsi\n"
- "jmp .loop\n" /* Restart the loop. */
- ".done:\n"
- "subq %rdi,%rax\n" /* Get the length of the string we copyied. */
- "decq %rdi\n" /* We do not count the null-terminator in the string length. */
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current input character. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Address of the current output character. */
- "movl 0x8(%esp),%ecx\n"
- /* edx: Current character. */
- ".loop:\n"
- "movb (%eax),%dl\n" /* Move current the character into a register... */
- "movb %dl,(%ecx)\n" /* ... and then back into memory. */
- "testb %dl,%dl\n" /* Check if we have reached the null-terminator... */
- "jz .done\n" /* ... and if so, we are finished copying. */
- "incl %eax\n" /* Increment the positions. */
- "incl %ecx\n"
- "jmp .loop\n" /* Restart the loop. */
- ".done:\n"
- "subl 0x4(%esp),%eax\n" /* Get the length of the string we copyied. */
- "decl %ecx \n" /* We do not count the null-terminator in the string length. */
- "ret\n"
-#endif
-);
-#else
-size_t zap_strcpy(char const * const _in,char * const _out) {
- char const * inpos = _in;
- char * outpos = _out;
- for (;;++inpos,++outpos) {
- char const chr = *inpos;
- *outpos = chr;
- if (chr == '\x0') {return inpos - _in;}
- }
- sus_unreach();
-}
-#endif
diff --git a/zap/src/streq.c b/zap/src/streq.c
deleted file mode 100644
index 1ff4420..0000000
--- a/zap/src/streq.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_streq\n"
-
- "zap_streq:\n"
- /*
- char const * lstr
- char const * rstr
- */
-#if defined(sus_arch_amd64)
- /* rax: Address of the current input character. */
- "movq %rdi,%rax\n"
- /* rsi: Address of the current output character. */
- "movq %rsi,%rsi\n"
- /* rdx: Current input character. */
- /* rcx: Current output character. */
- ".loop:\n"
- "movb (%rax),%dl\n" /* Move the characters into registers. */
- "movb (%rsi),%cl\n"
- "cmpb %dl,%cl\n" /* Check if the characters are equal... */
- "jne .neq\n" /* ... indicate inequality if they are not. */
- "testb %dl,%dl\n" /* Check if we have reached the null-terminator... */
- "jz .eq\n" /* ... indicate equality if we have. */
- "incq %rax\n" /* Increment positions. */
- "incq %rsi\n"
- "jmp .loop\n" /* Restart loop. */
- ".eq:\n" /* Indicate equality. */
- "movb $0x1,%al\n"
- "ret\n"
- ".neq:\n" /* Indicate inequality. */
- "movb $0x0,%al\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current input character. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Address of the current output character. */
- "movl 0x8(%esp),%ecx\n"
- /* edx: Current input character. */
- /* edx: Current output character. */
- ".loop:\n"
- "movb (%eax),%dl\n" /* Move the characters into registers. */
- "movb (%ecx),%dh\n"
- "cmpb %dl,%dh\n" /* Check if the characters are equal... */
- "jne .neq\n" /* ... indicate inequality if they are not. */
- "testb %dl,%dl\n" /* Check if we have reached the null-terminator... */
- "jz .eq\n" /* ... indicate equality if we have. */
- "incl %eax\n" /* Increment positions. */
- "incl %ecx\n"
- "jmp .loop\n" /* Restart loop. */
- ".eq:\n" /* Indicate equality. */
- "movb $0x1,%al\n"
- "ret\n"
- ".neq:\n" /* Indicate inequality. */
- "movb $0x0,%al\n"
- "ret\n"
-#endif
-);
-#else
-bool zap_streq(char const * const _lstr,char const * const _rstr) {
- char const * lpos = _lstr;
- char const * rpos = _rstr;
- for (;;++lpos,++rpos) {
- char const lchr = *lpos;
- char const rchr = *rpos;
- sus_likely (lchr != rchr) {return false;}
- if (lchr == '\x0') {return true;}
- }
- sus_unreach();
-}
-#endif
diff --git a/zap/src/strfill.c b/zap/src/strfill.c
deleted file mode 100644
index bd0af33..0000000
--- a/zap/src/strfill.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stdint.h>
-
-void zap_strfill(char * const _str,char const _chr) {zap_memfill(_str,zap_strlen(_str),(unsigned char)_chr);}
diff --git a/zap/src/strlen.c b/zap/src/strlen.c
deleted file mode 100644
index 84b7d28..0000000
--- a/zap/src/strlen.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- Copyright 2022 Gabriel Jensen.
- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
- If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-*/
-
-#include <zap/priv.h>
-
-#include <zap/mem.h>
-
-#include <stddef.h>
-
-#if zap_priv_fastimpl
-__asm__ (
- ".globl zap_strlen\n"
-
- "zap_strlen:\n"
- /*
- char const * str
- */
-#if defined(sus_arch_amd64)
- /* rax: Address of the current character. */
- "movq %rdi,%rax\n"
- /* rdx: Current character. */
- ".loop:\n"
- "movb (%rax),%dl\n"
- "testb %dl,%dl\n"
- "jz .done\n" /* Exit loop if we have reached the null-terminator. */
- "incq %rax\n" /* Continue to the next character. */
- "jmp .loop\n"
- ".done:\n"
- "subq %rdi,%rax\n"
- "ret\n"
-#elif defined(sus_arch_ia32)
- /* eax: Address of the current character. */
- "movl 0x4(%esp),%eax\n"
- /* ecx: Current character. */
- ".loop:\n"
- "movb (%eax),%cl\n"
- "testb %cl,%cl\n"
- "jz .done\n" /* Exit loop if we have reached the null-terminator. */
- "incl %eax\n" /* Continue to the next character. */
- "jmp .loop\n"
- ".done:\n"
- "subl 0x4(%esp),%eax\n"
- "ret\n"
-#endif
-);
-#else
-size_t zap_strlen(char const * const _str) {
- char const * pos = _str;
- for (;;++pos) {
- char const chr = *pos;
- sus_unlikely (chr == '\x0') {return (size_t)(pos - _str);}
- }
- sus_unreach();
-}
-#endif