@crossbind/port-zlib 2.0.0-beta.60 → 2.0.0-beta.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -13
- package/build.mjs +15 -1
- package/mergeConfig.mjs +5 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
# @crossbind/port-zlib
|
|
2
|
-
**Precompiled zlib library built with crossbind for seamless integration in JavaScript, WebAssembly and React Native projects.**
|
|
2
|
+
**Precompiled zlib library built with crossbind for seamless integration in JavaScript, WebAssembly and React Native projects.**
|
|
3
3
|
|
|
4
4
|
<a href="https://www.npmjs.com/package/@crossbind/port-zlib">
|
|
5
|
-
<img alt="NPM version" src="https://img.shields.io/npm/v/@crossbind/port-zlib?style=for-the-badge" />
|
|
5
|
+
<img alt="NPM version" src="https://img.shields.io/npm/v/@crossbind/port-zlib/beta?style=for-the-badge" />
|
|
6
6
|
</a>
|
|
7
7
|
<a href="https://zlib.net/">
|
|
8
|
-
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%
|
|
8
|
+
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2F%40crossbind%2Fport-zlib%2Fbeta&query=%24.nativeVersion&style=for-the-badge&label=zlib" />
|
|
9
9
|
</a>
|
|
10
10
|
<a href="https://zlib.net/zlib_license.html">
|
|
11
|
-
<img alt="License" src="https://img.shields.io/
|
|
11
|
+
<img alt="License" src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2F%40crossbind%2Fport-zlib%2Fbeta&query=%24.license&style=for-the-badge&label=license" />
|
|
12
12
|
</a>
|
|
13
13
|
|
|
14
14
|
> Use it together with **[crossbind](https://crossbind.dev)** — the toolchain for using C++ libraries from JavaScript, TypeScript, WebAssembly, Node.js and React Native. Learn more at **[crossbind.dev](https://crossbind.dev)**.
|
|
15
15
|
|
|
16
|
+
## See it run
|
|
17
|
+
Three apps on **[crossbind.dev/ports/zlib](https://crossbind.dev/ports/zlib/#apps)** run this package in your browser, on the same generated data every time:
|
|
18
|
+
|
|
19
|
+
- **Seekable gzip.** Gzips a generated 16,000,000-byte log to 3,001,352 B and indexes it in one pass, the technique of zlib's own `examples/zran.c`. Reading line 123,456 then decompresses 864,773 B instead of the 7,901,183 B before it.
|
|
20
|
+
- **PNG squeezer.** Filters a PNG's rows again and deflates them at level 9, copying every other chunk as it was. The sample chart goes from 17,191 B to 4,989 B, and both zlib and the browser's own PNG decoder confirm the pixels are unchanged.
|
|
21
|
+
- **ZIP inspector.** Reads a ZIP's central directory, inflates one entry with raw deflate and checks every CRC-32, as `unzip -t` does. A .docx, .xlsx, .epub or .jar opens the same way.
|
|
22
|
+
|
|
23
|
+
Their C++ wrappers, and the self-check the site build runs against values computed independently of this package, are in [`landing/demos/lib-zlib`](https://github.com/crossbind/crossbind/tree/main/landing/demos/lib-zlib).
|
|
24
|
+
|
|
16
25
|
## Integration
|
|
17
26
|
Install the main package together with the platform builds:
|
|
18
27
|
|
|
19
28
|
```sh
|
|
20
|
-
npm install @crossbind/port-zlib @crossbind/port-zlib-wasm @crossbind/port-zlib-android @crossbind/port-zlib-ios
|
|
29
|
+
npm install @crossbind/port-zlib@beta @crossbind/port-zlib-wasm@beta @crossbind/port-zlib-android@beta @crossbind/port-zlib-ios@beta
|
|
21
30
|
```
|
|
22
31
|
|
|
23
32
|
Then import all three platforms in `crossbind.config.js` — crossbind compiles only the one matching each build target:
|
|
@@ -39,18 +48,89 @@ export default {
|
|
|
39
48
|
};
|
|
40
49
|
```
|
|
41
50
|
|
|
51
|
+
A native Node.js addon (`crossbind build -e node`) links the build of its platform: `-p darwin`, `-p linux`, `-p linuxmusl` or `-p win32` takes `@crossbind/port-zlib-darwin`, `-linux`, `-linuxmusl` or `-win32`; `-linuxmusl` is the one for Alpine and other musl distributions. Install it and import its `crossbind.config.js` the same way.
|
|
52
|
+
|
|
42
53
|
## Usage
|
|
43
|
-
|
|
54
|
+
crossbind binds your C++ headers to JavaScript, so the usual pattern is a small wrapper around the library. This one compresses and decompresses in one call. Put it in your project's native folder (`src/native/` by default):
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
```cpp
|
|
57
|
+
// src/native/zlib_codec.h
|
|
58
|
+
#pragma once
|
|
59
|
+
|
|
60
|
+
#include <zlib.h>
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
#include <stdexcept>
|
|
63
|
+
#include <string>
|
|
64
|
+
|
|
65
|
+
// One-shot zlib: compress2 and uncompress, in the zlib format (RFC 1950). Bytes cross the binding as
|
|
66
|
+
// a byte string: one UTF-16 code unit (0-255) per byte.
|
|
67
|
+
class Zlib {
|
|
68
|
+
public:
|
|
69
|
+
static std::string version() { return zlibVersion(); }
|
|
70
|
+
|
|
71
|
+
static std::u16string compress(const std::string& text, int level) {
|
|
72
|
+
uLongf size = compressBound(static_cast<uLong>(text.size()));
|
|
73
|
+
std::string out(size, '\0');
|
|
74
|
+
const int status = compress2(reinterpret_cast<Bytef*>(&out[0]), &size, reinterpret_cast<const Bytef*>(text.data()), static_cast<uLong>(text.size()), level);
|
|
75
|
+
if (status != Z_OK) throw std::runtime_error(status == Z_STREAM_ERROR ? "level must be between -1 and 9" : zError(status));
|
|
76
|
+
std::u16string bytes(size, u'\0');
|
|
77
|
+
for (uLongf i = 0; i < size; ++i) bytes[i] = static_cast<unsigned char>(out[i]);
|
|
78
|
+
return bytes;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The zlib format does not record the original size, so the caller keeps it next to the data.
|
|
82
|
+
static std::string decompress(const std::u16string& bytes, int originalSize) {
|
|
83
|
+
if (originalSize < 0 || originalSize > (256 << 20)) throw std::invalid_argument("originalSize must be between 0 and 256 MiB");
|
|
84
|
+
std::string in(bytes.size(), '\0');
|
|
85
|
+
for (size_t i = 0; i < bytes.size(); ++i) {
|
|
86
|
+
if (bytes[i] > 0xFF) throw std::invalid_argument("not a byte string");
|
|
87
|
+
in[i] = static_cast<char>(bytes[i]);
|
|
88
|
+
}
|
|
89
|
+
std::string out(static_cast<size_t>(originalSize), '\0');
|
|
90
|
+
uLongf size = static_cast<uLongf>(out.size());
|
|
91
|
+
const int status = uncompress(reinterpret_cast<Bytef*>(&out[0]), &size, reinterpret_cast<const Bytef*>(in.data()), static_cast<uLong>(in.size()));
|
|
92
|
+
if (status == Z_BUF_ERROR) throw std::runtime_error("the data is larger than originalSize");
|
|
93
|
+
if (status != Z_OK) throw std::runtime_error(status == Z_DATA_ERROR ? "corrupt or incomplete zlib data" : zError(status));
|
|
94
|
+
out.resize(size);
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Then call it from JavaScript:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
import { initNative, Zlib } from './native/zlib_codec.h';
|
|
104
|
+
|
|
105
|
+
await initNative();
|
|
106
|
+
const text = 'crossbind '.repeat(100);
|
|
107
|
+
const packed = await Zlib.compress(text, 9);
|
|
108
|
+
const bytes = Uint8Array.from(packed, (c) => c.charCodeAt(0));
|
|
109
|
+
console.log(await Zlib.version(), bytes.length, [...bytes.slice(0, 2)].map((b) => b.toString(16)).join(' ')); // 1.3.2 27 78 da
|
|
110
|
+
console.log((await Zlib.decompress(packed, text.length)) === text); // true
|
|
52
111
|
```
|
|
53
112
|
|
|
113
|
+
- Binary data crosses the binding as a string with one UTF-16 code unit (0-255) per byte, which is why `compress` returns `std::u16string`. `Uint8Array.from(packed, (c) => c.charCodeAt(0))` turns it into bytes.
|
|
114
|
+
- `compress2` writes the zlib format (RFC 1950): the bytes Python's `zlib.decompress` and the browser's `DecompressionStream('deflate')` read.
|
|
115
|
+
- The zlib format does not store the original size, so `decompress` takes it from the caller and refuses anything above 256 MiB. When the size is not known, loop over `inflate()` instead, as the gzip examples below do.
|
|
116
|
+
- For files, pass paths instead of bytes: mount the file into the module's filesystem (`autoMountFiles`) and read it in C++ with `fopen`. The three apps above work that way.
|
|
117
|
+
|
|
118
|
+
### More examples
|
|
119
|
+
Each one runs in your browser on [crossbind.dev/ports/zlib](https://crossbind.dev/ports/zlib/#usage), next to the code shown there:
|
|
120
|
+
|
|
121
|
+
- [Write a .gz that remembers its file name](https://crossbind.dev/ports/zlib/#02-gzip): `deflateInit2` with windowBits 15 + 16 for gzip, `deflateSetHeader` for the name and date, `inflateGetHeader` to read them back.
|
|
122
|
+
- [Stream a file through gzip](https://crossbind.dev/ports/zlib/#03-stream): the `deflate()` and `inflate()` loops of zlib's `zpipe.c`, file to file in 64 KB steps, reading every member of a concatenated .gz.
|
|
123
|
+
- [Compress small messages with a preset dictionary](https://crossbind.dev/ports/zlib/#04-dictionary): raw deflate with `deflateSetDictionary` and `inflateSetDictionary`; a 59-byte message goes from 59 B to 11 B.
|
|
124
|
+
- [Checksum data in pieces](https://crossbind.dev/ports/zlib/#05-checksum): `crc32` and `adler32` as running values, and `crc32_combine` and `adler32_combine` to join pieces checksummed separately.
|
|
125
|
+
|
|
126
|
+
Setup and differences per platform: [WebAssembly](https://crossbind.dev/ports/zlib/wasm/) · [Android](https://crossbind.dev/ports/zlib/android/) · [iOS](https://crossbind.dev/ports/zlib/ios/) · [macOS](https://crossbind.dev/ports/zlib/darwin/) · [Linux](https://crossbind.dev/ports/zlib/linux/) · [Windows](https://crossbind.dev/ports/zlib/win32/) · [WASI](https://crossbind.dev/ports/zlib/wasi/), which also has a gzip command-line program built with `crossbind build -p wasi -e wasi`.
|
|
127
|
+
|
|
128
|
+
## What this build includes
|
|
129
|
+
- zlib 1.3.2 from the release tarball, pinned by SHA-256, built with zlib's own CMake options at their defaults apart from `ZLIB_BUILD_TESTING=OFF` and the library type: static on every platform. On Android the archive is position-independent and goes into the libraries that use it, because the app process already holds the system's own `libz.so`, which would shadow a shared build. Its symbols are hidden there, so every library that links it keeps its copy private and calls its own.
|
|
130
|
+
- The stock `zlib.h` and `zconf.h`, unchanged. The examples and apps here use `deflateSetHeader`, `inflateGetHeader`, `deflateSetDictionary`, `inflatePrime`, `crc32_combine` and, in the WASI program, the `gz*` file functions.
|
|
131
|
+
- No `contrib/minizip` (`ZLIB_BUILD_MINIZIP` is off by default) and none of the programs in zlib's `examples/`, such as `zran.c`. The ZIP inspector and the seekable gzip app bring their own code for those jobs.
|
|
132
|
+
- Every compressed byte the examples and apps above produce is identical to what stock zlib 1.3.2, built natively from the same tarball, produces, except the operating-system byte in a gzip header: zlib writes 3 (Unix) in the WebAssembly and WASI builds, and its `zutil.h` writes 19 wherever `__APPLE__` is defined, which includes iOS. Set the byte with `deflateSetHeader` when files must match across platforms.
|
|
133
|
+
|
|
54
134
|
## Supported platforms
|
|
55
135
|
This is the main package; the precompiled binaries are shipped per platform:
|
|
56
136
|
|
|
@@ -59,8 +139,14 @@ This is the main package; the precompiled binaries are shipped per platform:
|
|
|
59
139
|
| WebAssembly | [`@crossbind/port-zlib-wasm`](https://www.npmjs.com/package/@crossbind/port-zlib-wasm) | `wasm32` — single-threaded & multi-threaded |
|
|
60
140
|
| Android | [`@crossbind/port-zlib-android`](https://www.npmjs.com/package/@crossbind/port-zlib-android) | `arm64-v8a` (64-bit ARM), `x86_64` (emulator) |
|
|
61
141
|
| iOS | [`@crossbind/port-zlib-ios`](https://www.npmjs.com/package/@crossbind/port-zlib-ios) | device (`arm64`), simulator (`arm64`) |
|
|
142
|
+
| macOS | [`@crossbind/port-zlib-darwin`](https://www.npmjs.com/package/@crossbind/port-zlib-darwin) | `arm64` (Apple silicon), `x64` (Intel) — native Node.js addons |
|
|
143
|
+
| Linux | [`@crossbind/port-zlib-linux`](https://www.npmjs.com/package/@crossbind/port-zlib-linux) | `x64`, `arm64` — glibc 2.28 or later, native Node.js addons |
|
|
144
|
+
| Linux (musl) | [`@crossbind/port-zlib-linuxmusl`](https://www.npmjs.com/package/@crossbind/port-zlib-linuxmusl) | `x64`, `arm64` — musl 1.2.5 or later (Alpine 3.21 and later), native Node.js addons |
|
|
145
|
+
| Windows | [`@crossbind/port-zlib-win32`](https://www.npmjs.com/package/@crossbind/port-zlib-win32) | `x64`, `arm64` — Windows 10 or later, native Node.js addons |
|
|
146
|
+
| WASI library | [`@crossbind/port-zlib-wasi`](https://www.npmjs.com/package/@crossbind/port-zlib-wasi) | `wasm32-wasip3` — single-threaded |
|
|
147
|
+
| Node.js, ready-made | [`@crossbind/port-zlib-standalone-napi`](https://www.npmjs.com/package/@crossbind/port-zlib-standalone-napi) | prebuilt addons for macOS, Linux (glibc and musl) and Windows, `arm64` and `x64`: nothing to build |
|
|
62
148
|
|
|
63
149
|
## License
|
|
64
150
|
This project includes the precompiled zlib library, which is distributed under the [zlib License](https://zlib.net/zlib_license.html).
|
|
65
151
|
|
|
66
|
-
|
|
152
|
+
zlib Homepage: [https://zlib.net/](https://zlib.net/)
|
package/build.mjs
CHANGED
|
@@ -3,8 +3,22 @@ export default {
|
|
|
3
3
|
// zlib.net drops superseded releases and its edge occasionally serves other bytes; the GitHub asset is stable.
|
|
4
4
|
getURL: (version) => `https://github.com/madler/zlib/releases/download/v${version}/zlib-${version}.tar.gz`,
|
|
5
5
|
buildType: 'cmake',
|
|
6
|
+
// On Windows zlib names its static library zs; every consumer links it as z.
|
|
7
|
+
replaceList: [
|
|
8
|
+
{
|
|
9
|
+
regex: 'set\\(zlib_static_suffix "s"\\)',
|
|
10
|
+
replacement: 'set(zlib_static_suffix "")',
|
|
11
|
+
paths: ['CMakeLists.txt'],
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
// Static on every platform, as OpenSSL is: an Android app process already holds the system libz.so, which would
|
|
15
|
+
// shadow a shared build of this one. The archive goes into shared libraries there, so it must be PIC, and its
|
|
16
|
+
// symbols are hidden so that each of those libraries keeps its copy private instead of exporting it.
|
|
6
17
|
getBuildParams: (target) => [
|
|
7
|
-
|
|
18
|
+
'-DZLIB_BUILD_SHARED=OFF',
|
|
19
|
+
...(target.platform === 'android'
|
|
20
|
+
? ['-DCMAKE_POSITION_INDEPENDENT_CODE=ON', '-DCMAKE_C_VISIBILITY_PRESET=hidden']
|
|
21
|
+
: []),
|
|
8
22
|
'-DZLIB_BUILD_TESTING=OFF',
|
|
9
23
|
],
|
|
10
24
|
};
|
package/mergeConfig.mjs
CHANGED
|
@@ -6,11 +6,15 @@ export default (newConfig = {}) => ({
|
|
|
6
6
|
},
|
|
7
7
|
export: {
|
|
8
8
|
type: 'cmake',
|
|
9
|
-
|
|
9
|
+
publicHeaders: ['zlib.h'],
|
|
10
10
|
...(newConfig.export || {}),
|
|
11
11
|
},
|
|
12
12
|
paths: {
|
|
13
13
|
output: 'dist',
|
|
14
14
|
...(newConfig.paths || {}),
|
|
15
15
|
},
|
|
16
|
+
targetSpecs: [
|
|
17
|
+
{ platform: 'android', specs: { libType: 'static' } },
|
|
18
|
+
...(newConfig.targetSpecs || []),
|
|
19
|
+
],
|
|
16
20
|
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossbind/port-zlib",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.63",
|
|
4
4
|
"nativeVersion": "1.3.2",
|
|
5
5
|
"description": "This package provides the precompiled zlib library, built using crossbind, for easy integration into JavaScript, WebAssembly and React Native projects. It offers compression and decompression functionalities through the zlib API, ensuring high performance and cross-platform compatibility. Ideal for use in web and mobile applications.",
|
|
6
|
-
"homepage": "https://
|
|
6
|
+
"homepage": "https://crossbind.dev/ports/zlib/",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/crossbind/crossbind.git"
|