Compare commits

...

5 Commits

Author SHA1 Message Date
Nuno Cruces
69a2881a10 SQLite 3.50.1. 2025-06-08 00:38:01 +01:00
dependabot[bot]
24ad4445f1 Bump golang.org/x/crypto from 0.38.0 to 0.39.0 (#285)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/crypto/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-05 23:49:59 +01:00
Nuno Cruces
c159bbd88f Docs, tweaks. 2025-06-04 12:19:01 +01:00
Nuno Cruces
c90f8205f7 Remove. 2025-06-03 12:54:56 +01:00
Nuno Cruces
b64b9b0415 Better strcasestr. 2025-06-02 10:25:10 +01:00
28 changed files with 238 additions and 169 deletions

View File

@@ -1,6 +1,6 @@
# Embeddable Wasm build of SQLite
This folder includes an embeddable Wasm build of SQLite 3.50.0 for use with
This folder includes an embeddable Wasm build of SQLite 3.50.1 for use with
[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
The following optional features are compiled in:

Binary file not shown.

View File

@@ -53,7 +53,7 @@ func Test_bcw2(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if version != "3.50.0" {
if version != "3.51.0" {
t.Error(version)
}
}

View File

@@ -13,8 +13,8 @@ mkdir -p build/ext/
cp "$ROOT"/sqlite3/*.[ch] build/
cp "$ROOT"/sqlite3/*.patch build/
# https://sqlite.org/src/info/54b8888080d99a87
curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=54b8888080 | tar xz
# https://sqlite.org/src/info/93740658c8c6f531
curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=93740658c8 | tar xz
cd sqlite
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then

View File

@@ -4,11 +4,11 @@ go 1.23.0
toolchain go1.24.0
require github.com/ncruces/go-sqlite3 v0.25.0
require github.com/ncruces/go-sqlite3 v0.26.0
require (
github.com/ncruces/julianday v1.0.0 // indirect
github.com/ncruces/sort v0.1.5 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/sys v0.33.0 // indirect
)

View File

@@ -1,12 +1,12 @@
github.com/ncruces/go-sqlite3 v0.25.0 h1:trugKUs98Zwy9KwRr/EUxZHL92LYt7UqcKqAfpGpK+I=
github.com/ncruces/go-sqlite3 v0.25.0/go.mod h1:n6Z7036yFilJx04yV0mi5JWaF66rUmXn1It9Ux8dx68=
github.com/ncruces/go-sqlite3 v0.26.0 h1:dY6ASfuhSEbtSge6kJwjyJVC7bXCpgEVOycmdboKJek=
github.com/ncruces/go-sqlite3 v0.26.0/go.mod h1:46HIzeCQQ+aNleAxCli+vpA2tfh7ttSnw24kQahBc1o=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/ncruces/sort v0.1.5 h1:fiFWXXAqKI8QckPf/6hu/bGFwcEPrirIOFaJqWujs4k=
github.com/ncruces/sort v0.1.5/go.mod h1:obJToO4rYr6VWP0Uw5FYymgYGt3Br4RXcs/JdKaXAPk=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=

View File

@@ -19,7 +19,7 @@ func Test_init(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if version != "3.50.0" {
if version != "3.50.1" {
t.Error(version)
}
}

Binary file not shown.

View File

@@ -30,7 +30,7 @@ you can load into your database connections.
- [`github.com/ncruces/go-sqlite3/ext/statement`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/statement)
creates [parameterized views](https://github.com/0x09/sqlite-statement-vtab).
- [`github.com/ncruces/go-sqlite3/ext/stats`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats)
provides [statistics](https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html) functions.
provides [statistics](https://oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html) functions.
- [`github.com/ncruces/go-sqlite3/ext/unicode`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode)
provides [Unicode aware](https://sqlite.org/src/dir/ext/icu) functions.
- [`github.com/ncruces/go-sqlite3/ext/uuid`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/uuid)

View File

@@ -38,7 +38,7 @@ func TestRegister(t *testing.T) {
{`regexp_instr('Hello', '.', 6)`, ""},
{`regexp_substr('Hello', 'el.')`, "ell"},
{`regexp_replace('Hello', 'llo', 'll')`, "Hell"},
// https://www.postgresql.org/docs/current/functions-matching.html
// https://postgresql.org/docs/current/functions-matching.html
{`regexp_count('ABCABCAXYaxy', 'A.')`, "3"},
{`regexp_count('ABCABCAXYaxy', '(?i)A.', 1)`, "4"},
{`regexp_instr('number of your street, town zip, FR', '[^,]+', 1, 2)`, "23"},

View File

@@ -1,6 +1,6 @@
# ANSI SQL Aggregate Functions
https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html
https://oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html
## Built in aggregates

View File

@@ -47,7 +47,7 @@
//
// [Built-in Aggregate Functions]: https://sqlite.org/lang_aggfunc.html
// [Built-in Window Functions]: https://sqlite.org/windowfunctions.html#builtins
// [ANSI SQL Aggregate Functions]: https://www.oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html
// [ANSI SQL Aggregate Functions]: https://oreilly.com/library/view/sql-in-a/9780596155322/ch04s02.html
package stats
import (

6
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/ncruces/julianday v1.0.0
github.com/ncruces/sort v0.1.5
github.com/tetratelabs/wazero v1.9.0
golang.org/x/crypto v0.38.0
golang.org/x/crypto v0.39.0
golang.org/x/sys v0.33.0
)
@@ -16,8 +16,8 @@ require (
github.com/dchest/siphash v1.2.3 // ext/bloom
github.com/google/uuid v1.6.0 // ext/uuid
github.com/psanford/httpreadat v0.1.0 // example
golang.org/x/sync v0.14.0 // test
golang.org/x/text v0.25.0 // ext/unicode
golang.org/x/sync v0.15.0 // test
golang.org/x/text v0.26.0 // ext/unicode
lukechampine.com/adiantum v1.1.1 // vfs/adiantum
)

12
go.sum
View File

@@ -10,13 +10,13 @@ github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIw
github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
lukechampine.com/adiantum v1.1.1 h1:4fp6gTxWCqpEbLy40ExiYDDED3oUNWx5cTqBCtPdZqA=
lukechampine.com/adiantum v1.1.1/go.mod h1:LrAYVnTYLnUtE/yMp5bQr0HstAf060YUF8nM0B6+rUw=

View File

@@ -5,8 +5,8 @@ go 1.23.0
toolchain go1.24.0
require (
github.com/ncruces/go-sqlite3 v0.25.0
gorm.io/gorm v1.25.12
github.com/ncruces/go-sqlite3 v0.26.0
gorm.io/gorm v1.30.0
)
require (
@@ -14,6 +14,6 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.26.0 // indirect
)

View File

@@ -2,15 +2,15 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/ncruces/go-sqlite3 v0.25.0 h1:trugKUs98Zwy9KwRr/EUxZHL92LYt7UqcKqAfpGpK+I=
github.com/ncruces/go-sqlite3 v0.25.0/go.mod h1:n6Z7036yFilJx04yV0mi5JWaF66rUmXn1It9Ux8dx68=
github.com/ncruces/go-sqlite3 v0.26.0 h1:dY6ASfuhSEbtSge6kJwjyJVC7bXCpgEVOycmdboKJek=
github.com/ncruces/go-sqlite3 v0.26.0/go.mod h1:46HIzeCQQ+aNleAxCli+vpA2tfh7ttSnw24kQahBc1o=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=

View File

@@ -1,4 +1,3 @@
// Package gormlite provides a GORM driver for SQLite.
package gormlite
import (
@@ -52,7 +51,9 @@ func (dialector _Dialector) Initialize(db *gorm.DB) (err error) {
})
for k, v := range dialector.ClauseBuilders() {
db.ClauseBuilders[k] = v
if _, ok := db.ClauseBuilders[k]; !ok {
db.ClauseBuilders[k] = v
}
}
return
}

View File

@@ -7,7 +7,7 @@ rm -rf gorm/ tests/
go work use -r .
go test
git clone --branch v1.25.12 --filter=blob:none https://github.com/go-gorm/gorm.git
git clone --branch v1.30.0 --filter=blob:none https://github.com/go-gorm/gorm.git
mv gorm/tests tests
rm -rf gorm/

View File

@@ -3,12 +3,12 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/ddlmod.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/ddlmod_test.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/ddlmod_parse_all_columns.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/ddlmod_parse_all_columns_test.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/error_translator.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/migrator.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/sqlite.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.5.7/sqlite_test.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/ddlmod.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/ddlmod_test.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/ddlmod_parse_all_columns.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/ddlmod_parse_all_columns_test.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/error_translator.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/migrator.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/sqlite.go"
curl -#OL "https://github.com/go-gorm/sqlite/raw/v1.6.0/sqlite_test.go"
curl -#L "https://github.com/glebarez/sqlite/raw/v1.11.0/sqlite_error_translator_test.go" > error_translator_test.go

View File

@@ -3,7 +3,7 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
curl -#OL "https://sqlite.org/2025/sqlite-amalgamation-3500000.zip"
curl -#OL "https://sqlite.org/2025/sqlite-amalgamation-3500100.zip"
unzip -d . sqlite-amalgamation-*.zip
mv sqlite-amalgamation-*/sqlite3.c .
mv sqlite-amalgamation-*/sqlite3.h .
@@ -19,30 +19,30 @@ rm -rf sqlite-amalgamation-*
mkdir -p ext/
cd ext/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/anycollseq.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/base64.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/decimal.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/ieee754.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/regexp.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/series.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/spellfix.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/ext/misc/uint.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/anycollseq.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/base64.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/decimal.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/ieee754.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/regexp.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/series.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/spellfix.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/uint.c"
cd ~-
cd ../vfs/tests/mptest/testdata/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/config01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/config02.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/crash01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/crash02.subtest"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/multiwrite01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/config01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/config02.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/crash01.test"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/crash02.subtest"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/multiwrite01.test"
cd ~-
cd ../vfs/tests/mptest/wasm/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/mptest/mptest.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/mptest.c"
cd ~-
cd ../vfs/tests/speedtest1/wasm/
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.0/test/speedtest1.c"
curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/test/speedtest1.c"
cd ~-
cat *.patch | patch -p0 --no-backup-if-mismatch

41
sqlite3/libc/README.md Normal file
View File

@@ -0,0 +1,41 @@
# Using SIMD for libc
I found that implementing some libc functions with Wasm SIMD128 can make them significantly faster.
Rough numbers for [wazero](https://wazero.io/):
function | speedup
------------ | -----
`strlen` | 4.1×
`memchr` | 4.1×
`strchr` | 4.0×
`strrchr` | 9.1×
`memcmp` | 13.0×
`strcmp` | 10.4×
`strncmp` | 15.7×
`strcasecmp` | 8.8×
`strncasecmp`| 8.6×
`strspn` | 9.9×
`strcspn` | 9.0×
`memmem` | 2.2×
`strstr` | 5.5×
`strcasestr` | 25.2×
For functions where musl uses SWAR on a 4-byte `size_t`,
the improvement is around 4×.
This is very close to the expected theoretical improvement,
as we're processing 4× the bytes per cycle (16 _vs._ 4).
For other functions where there's no algorithmic change,
the improvement is around 8×.
These functions are harder to optimize
(which is why musl doesn't bother with SWAR),
so getting an 8× improvement from processing 16× bytes seems decent.
String search is harder to compare, since there are algorithmic changes,
and different needles produce very different numbers.
We use [Quick Search](https://igm.univ-mlv.fr/~lecroq/string/node19.html) for `memmem`,
and a [RabinKarp](https://igm.univ-mlv.fr/~lecroq/string/node5.html) for `strstr` and `strcasestr`;
musl uses [Two Way](https://igm.univ-mlv.fr/~lecroq/string/node26.html) for `memmem` and `strstr`,
and [brute force](https://igm.univ-mlv.fr/~lecroq/string/node3.html) for `strcasestr`.
Unlike Two-Way, both replacements can go quadratic for long, periodic needles.

Binary file not shown.

View File

@@ -3700,10 +3700,13 @@
(local $6 i32)
(local $7 i32)
(local $8 i32)
(local $9 v128)
(local $9 i32)
(local $10 v128)
(local $11 v128)
(local $12 v128)
(local $13 v128)
(local $14 v128)
(local $15 v128)
(if
(i32.eqz
(local.tee $2
@@ -3718,7 +3721,7 @@
)
)
)
(local.set $5
(local.set $3
(i32.extend8_s
(local.get $2)
)
@@ -3738,17 +3741,17 @@
)
)
)
(local.set $4
(local.set $5
(local.get $6)
)
(loop $label
(if
(i32.ne
(local.tee $3
(local.tee $4
(i32.load8_u
(i32.add
(local.get $1)
(local.get $4)
(local.get $5)
)
)
)
@@ -3756,15 +3759,15 @@
)
(then
(local.set $2
(local.get $3)
(local.get $4)
)
(br $block)
)
)
(br_if $label
(local.tee $4
(local.tee $5
(i32.sub
(local.get $4)
(local.get $5)
(i32.const 1)
)
)
@@ -3778,27 +3781,43 @@
)
)
)
(local.set $4
(local.set $5
(local.get $6)
)
)
(local.set $3
(local.set $4
(select
(i32.or
(local.get $5)
(local.get $3)
(i32.const 32)
)
(local.get $5)
(local.get $3)
(i32.lt_u
(i32.sub
(local.get $5)
(local.get $3)
(i32.const 65)
)
(i32.const 26)
)
)
)
(local.set $2
(local.set $3
(select
(i32.and
(local.get $3)
(i32.const 95)
)
(local.get $3)
(i32.lt_u
(i32.sub
(local.get $3)
(i32.const 97)
)
(i32.const 26)
)
)
)
(local.set $8
(select
(i32.or
(local.tee $2
@@ -3818,19 +3837,35 @@
)
)
)
(local.set $2
(select
(i32.and
(local.get $2)
(i32.const 95)
)
(local.get $2)
(i32.lt_u
(i32.sub
(local.get $2)
(i32.const 97)
)
(i32.const 26)
)
)
)
(block $block3
(block $block4
(block $block1
(br_if $block1
(i32.lt_u
(local.tee $5
(local.tee $9
(i32.sub
(i32.sub
(i32.shl
(memory.size)
(i32.const 16)
)
(local.get $4)
(local.get $5)
)
(i32.const 16)
)
@@ -3838,17 +3873,27 @@
(local.get $0)
)
)
(local.set $10
(local.set $11
(i8x16.splat
(local.get $4)
)
)
(local.set $12
(i8x16.splat
(local.get $3)
)
)
(local.set $11
(local.set $13
(i8x16.splat
(local.get $8)
)
)
(local.set $14
(i8x16.splat
(local.get $2)
)
)
(local.set $8
(local.set $3
(i32.add
(local.get $1)
(i32.const 1)
@@ -3857,24 +3902,9 @@
(loop $label2
(local.set $2
(i8x16.all_true
(local.tee $9
(v128.or
(v128.bitselect
(v128.const i32x4 0x20202020 0x20202020 0x20202020 0x20202020)
(v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
(i8x16.gt_s
(i8x16.add
(local.tee $9
(v128.load align=1
(local.get $0)
)
)
(v128.const i32x4 0x25252525 0x25252525 0x25252525 0x25252525)
)
(v128.const i32x4 0x65656565 0x65656565 0x65656565 0x65656565)
)
)
(local.get $9)
(local.tee $10
(v128.load align=1
(local.get $0)
)
)
)
@@ -3882,35 +3912,34 @@
(block $block2
(if
(v128.any_true
(local.tee $9
(local.tee $10
(v128.and
(i8x16.eq
(local.get $11)
(v128.or
(v128.bitselect
(v128.const i32x4 0x20202020 0x20202020 0x20202020 0x20202020)
(v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
(i8x16.gt_s
(i8x16.add
(local.tee $12
(v128.load align=1
(i32.add
(local.get $0)
(local.get $4)
)
)
)
(v128.const i32x4 0x25252525 0x25252525 0x25252525 0x25252525)
(v128.or
(i8x16.eq
(local.get $13)
(local.tee $15
(v128.load align=1
(i32.add
(local.get $0)
(local.get $5)
)
(v128.const i32x4 0x65656565 0x65656565 0x65656565 0x65656565)
)
)
(local.get $12)
)
(i8x16.eq
(local.get $14)
(local.get $15)
)
)
(i8x16.eq
(local.get $10)
(local.get $9)
(v128.or
(i8x16.eq
(local.get $11)
(local.get $10)
)
(i8x16.eq
(local.get $12)
(local.get $10)
)
)
)
)
@@ -3925,7 +3954,7 @@
(i32.eqz
(local.tee $2
(i8x16.bitmask
(local.get $9)
(local.get $10)
)
)
)
@@ -3935,7 +3964,7 @@
(i32.eqz
(call $strncasecmp
(i32.add
(local.tee $3
(local.tee $4
(i32.add
(local.get $0)
(i32.ctz
@@ -3945,7 +3974,7 @@
)
(i32.const 1)
)
(local.get $8)
(local.get $3)
(local.get $6)
)
)
@@ -3979,12 +4008,12 @@
(i32.const 16)
)
)
(local.get $5)
(local.get $9)
)
)
)
)
(local.set $3
(local.set $4
(local.get $0)
)
(local.set $2
@@ -3997,7 +4026,7 @@
(i32.load8_s
(i32.add
(local.get $2)
(local.get $3)
(local.get $4)
)
)
)
@@ -4007,7 +4036,7 @@
(i32.eq
(select
(i32.or
(local.tee $4
(local.tee $5
(i32.load8_s
(i32.add
(local.get $1)
@@ -4017,10 +4046,10 @@
)
(i32.const 32)
)
(local.get $4)
(local.get $5)
(i32.lt_u
(i32.sub
(local.get $4)
(local.get $5)
(i32.const 65)
)
(i32.const 26)
@@ -4055,9 +4084,9 @@
)
)
(else
(local.set $3
(local.set $4
(i32.add
(local.get $3)
(local.get $4)
(i32.const 1)
)
)
@@ -4070,11 +4099,11 @@
)
(unreachable)
)
(local.set $3
(local.set $4
(i32.const 0)
)
)
(local.get $3)
(local.get $4)
)
(func $memccpy (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
(memory.copy

View File

@@ -402,8 +402,8 @@ size_t strspn(const char *s, const char *c) {
__wasm_v128_bitmap256_t bitmap = {};
for (; *c; c++) {
__wasm_v128_setbit(&bitmap, *c);
// Terminator IS NOT on the bitmap.
__wasm_v128_setbit(&bitmap, *c);
}
for (; N >= sizeof(v128_t); N -= sizeof(v128_t)) {
@@ -433,11 +433,10 @@ size_t strcspn(const char *s, const char *c) {
__wasm_v128_bitmap256_t bitmap = {};
for (;;) {
__wasm_v128_setbit(&bitmap, *c);
do {
// Terminator IS on the bitmap.
if (!*c++) break;
}
__wasm_v128_setbit(&bitmap, *c);
} while (*c++);
for (; N >= sizeof(v128_t); N -= sizeof(v128_t)) {
const v128_t cmp = __wasm_v128_chkbits(bitmap, wasm_v128_load(w));
@@ -465,13 +464,13 @@ size_t strcspn(const char *s, const char *c) {
// We augment the SIMD algorithm with Quick Search's
// bad-character shift.
//
// https://www-igm.univ-mlv.fr/~lecroq/string/node14.html
// https://www-igm.univ-mlv.fr/~lecroq/string/node18.html
// https://www-igm.univ-mlv.fr/~lecroq/string/node19.html
// https://www-igm.univ-mlv.fr/~lecroq/string/node22.html
// https://igm.univ-mlv.fr/~lecroq/string/node14.html
// https://igm.univ-mlv.fr/~lecroq/string/node18.html
// https://igm.univ-mlv.fr/~lecroq/string/node19.html
// https://igm.univ-mlv.fr/~lecroq/string/node22.html
static const char *__memmem(const char *haystk, size_t sh,
const char *needle, size_t sn,
static const char *__memmem(const char *haystk, size_t sh, //
const char *needle, size_t sn, //
uint8_t bmbc[256]) {
// We've handled empty and single character needles.
// The needle is not longer than the haystack.
@@ -490,8 +489,8 @@ static const char *__memmem(const char *haystk, size_t sh,
const v128_t lst = wasm_i8x16_splat(needle[i]);
// The last haystack offset for which loading blk_lst is safe.
const char *H = (char *)(__builtin_wasm_memory_size(0) * PAGESIZE - i -
sizeof(v128_t));
const char *H = (char *)(__builtin_wasm_memory_size(0) * PAGESIZE - //
(sizeof(v128_t) + i));
while (haystk <= H) {
const v128_t blk_fst = wasm_v128_load((v128_t *)(haystk));
@@ -616,18 +615,22 @@ char *strcasestr(const char *haystk, const char *needle) {
while (i > 0 && needle[0] == needle[i]) i--;
if (i == 0) i = sn - 1;
const v128_t fst = wasm_i8x16_splat(tolower(needle[0]));
const v128_t lst = wasm_i8x16_splat(tolower(needle[i]));
const v128_t fstl = wasm_i8x16_splat(tolower(needle[0]));
const v128_t fstu = wasm_i8x16_splat(toupper(needle[0]));
const v128_t lstl = wasm_i8x16_splat(tolower(needle[i]));
const v128_t lstu = wasm_i8x16_splat(toupper(needle[i]));
// The last haystk offset for which loading blk_lst is safe.
const char *H =
(char *)(__builtin_wasm_memory_size(0) * PAGESIZE - i - sizeof(v128_t));
const char *H = (char *)(__builtin_wasm_memory_size(0) * PAGESIZE - //
(sizeof(v128_t) + i));
while (haystk <= H) {
const v128_t blk_fst = __tolower8x16(wasm_v128_load((v128_t *)(haystk)));
const v128_t blk_lst = __tolower8x16(wasm_v128_load((v128_t *)(haystk + i)));
const v128_t eq_fst = wasm_i8x16_eq(fst, blk_fst);
const v128_t eq_lst = wasm_i8x16_eq(lst, blk_lst);
const v128_t blk_fst = wasm_v128_load((v128_t *)(haystk));
const v128_t blk_lst = wasm_v128_load((v128_t *)(haystk + i));
const v128_t eq_fst =
wasm_i8x16_eq(fstl, blk_fst) | wasm_i8x16_eq(fstu, blk_fst);
const v128_t eq_lst =
wasm_i8x16_eq(lstl, blk_lst) | wasm_i8x16_eq(lstu, blk_lst);
const v128_t cmp = eq_fst & eq_lst;
if (wasm_v128_any_true(cmp)) {
@@ -676,7 +679,8 @@ char *strcasestr(const char *haystk, const char *needle) {
// - strtok
__attribute__((weak))
void *memccpy(void *__restrict dest, const void *__restrict src, int c, size_t n) {
void *memccpy(void *__restrict dest, const void *__restrict src, int c,
size_t n) {
const void *m = memchr(src, c, n);
if (m != NULL) {
n = (char *)m - (char *)src + 1;
@@ -713,7 +717,8 @@ static char *__stpcpy(char *__restrict dest, const char *__restrict src) {
return dest + slen;
}
static char *__stpncpy(char *__restrict dest, const char *__restrict src, size_t n) {
static char *__stpncpy(char *__restrict dest, const char *__restrict src,
size_t n) {
size_t strnlen(const char *s, size_t n);
size_t slen = strnlen(src, n);
memcpy(dest, src, slen);

View File

@@ -32,10 +32,3 @@ func (FS) Stat(name string) (fs.FileInfo, error) {
func (FS) ReadFile(name string) ([]byte, error) {
return os.ReadFile(name)
}
// OpenFile behaves the same as [os.OpenFile].
//
// Deprecated: use os.OpenFile instead.
func OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
return os.OpenFile(name, flag, perm)
}

View File

@@ -23,7 +23,7 @@ POSIX advisory locks,
which SQLite uses on [Unix](https://github.com/sqlite/sqlite/blob/5d60f4/src/os_unix.c#L13-L14),
are [broken by design](https://github.com/sqlite/sqlite/blob/5d60f4/src/os_unix.c#L1074-L1162).
Instead, on Linux and macOS, this package uses
[OFD locks](https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html)
[OFD locks](https://gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html)
to synchronize access to database files.
This package can also use

Binary file not shown.