diff --git a/README.md b/README.md
index 7fc8481..8e00b50 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,39 @@
is a high-level wrapper around [zlib](https://zlib.net/).
+## Installation
+
+```clojure
+(load "https://veitheller.de/git/carpentry/zlib.git@0.0.1")
+```
+
## Usage
-The `ZLib` module provides only two functions
+The `ZLib` module provides only two functions, `inflate` and `deflate`. These
+functions work in tandem to provide you with data compression.
+
+```clojure
+; deflate returns a Result of either binary data or an error message
+(let [deflated (ZLib.deflate "mystring")]
+ (match deflated
+ ; inflate returns a Result of either a string or an error message
+ (Success bin) (println* &(inflate bin))
+ (Error msg) (IO.errorln &msg)))
+```
+
+Because it’s a `Result` type, we can apply combinators to it.
+
+```clojure
+(=> (ZLib.deflate "mystring")
+ (Result.and-then &ZLib.inflate)
+ (Result.map-error &(fn [msg] (do (println* &msg) msg)))
+)
+```
+
+You can also choose different levels of compression using `deflate-with`. The
+levels are defined in `ZLib.ZLevel`, and are `NoCompression`, `BestSpeed`,
+`BestCompression`, and `DefaultCompression`, which is, well, the default.
+
+
+
+
+
+
+
+ zlib
+
+
+
+
+ ZLib
+
+
+
is a high-level wrapper around zlib.
+
Installation
+
(load "https://veitheller.de/git/carpentry/zlib.git@0.0.1")
+
+
Usage
+
The ZLib
module provides only two functions, inflate
and
+deflate
. These functions work in tandem to provide you with data
+compression.
+
; deflate returns a Result of either binary data or an error message
+(let [deflated (ZLib.deflate "mystring")]
+ (match deflated
+ ; inflate returns a Result of either a string or an error message
+ (Success bin) (println* &(inflate bin))
+ (Error msg) (IO.errorln &msg)))
+
+
Because it’s a Result
type, we can apply combinators to it.
+
(=> (ZLib.deflate "mystring")
+ (Result.and-then &ZLib.inflate)
+ (Result.map-error &(fn [msg] (do (println* &msg) msg)))
+)
+
+
You can also choose different levels of compression using inflate-with
. The
+levels are defined in ZLib.ZLevel
, and are NoCompression
,
+BestSpeed
, BestCompression
, and DefaultCompression
, which is, well, the
+default.
+
+
+
+
+
+
+ ZLevel
+
+
+
+ module
+
+
+ Module
+
+
+
+
+
+
is a type used in conjunction with
+deflate-with
. It controls the compression level.
+
The constructors are NoCompression
, BestSpeed
, BestCompression
, and
+DefaultCompression
, which is, well, the default.
+
+
+
+
+
+
+ deflate
+
+
+
+ defn
+
+
+ (λ [&String] (Result ZBytes String))
+
+
+ (deflate s)
+
+
+
takes a bytes object s
and returns a Result
.
+
The Result
will be a Success
containing the deflated bytes if all goes
+well, and an Error
returning an error message otherwise.
+
It is equivalent to calling deflate-with
with
+(ZLevel.DefaultCompression)
.
+
+
+
+
+
+
+ deflate-with
+
+
+
+ defn
+
+
+ (λ [&String, ZLevel] (Result ZBytes String))
+
+
+ (deflate-with s level)
+
+
+
takes a bytes object s
, a Zlevel
level
and returns
+a Result
.
+
The Result
will be a Success
containing the deflated bytes if all goes
+well, and an Error
returning an error message otherwise.
+
+
+
+
+
+
+ inflate
+
+
+
+ defn
+
+
+ (λ [ZBytes] (Result String String))
+
+
+ (inflate s)
+
+
+
takes a bytes object s
and returns a Result
.
+
The Result
will be a Success
containing the inflated string if all goes
+well, and an Error
returning an error message otherwise.
+
+
+
+
+
+
diff --git a/docs/style.css b/docs/style.css
new file mode 100644
index 0000000..ed4f963
--- /dev/null
+++ b/docs/style.css
@@ -0,0 +1,110 @@
+html {
+ font-family: "Helvetica", sans-serif;
+ font-size: 16px;
+}
+
+a {
+ color: #000;
+}
+
+.logo {
+ display: none;
+}
+
+ul {
+ list-style-type: none;
+ font-family: "Hasklig", "Lucida Console", monospace;
+ line-height: 1.4em;
+}
+
+.module-description {
+ margin-bottom: 3em;
+}
+
+.content {
+ margin: 3em auto auto auto;
+ width: 80%;
+ max-width: 610px;
+ min-width: 400px
+}
+
+h1 {
+ margin-bottom: 1em;
+ font-weight: 400;
+}
+
+h2 {
+ font-weight: 400;
+ margin-bottom: 0em;
+}
+
+h3 {
+ margin: 0em;
+ font-weight: 400;
+}
+
+.binder {
+ margin: 0em 0em 3.5em 0em;
+}
+
+.sig {
+ font-family: "Hasklig", "Lucida Console", monospace;
+ margin: 0.5em 0em 0.5em 0em;
+}
+
+.args {
+ background-color: #eee;
+ display: inline-block;
+ white-space: normal;
+ margin: 0;
+ margin-bottom: 1em;
+}
+
+code {
+ background-color: #eee;
+}
+
+pre {
+ background-color: #eee;
+ overflow-y: scroll;
+}
+
+.description {
+ margin-top: 0.3em;
+ font-size: 0.8em;
+ color: #aaa;
+}
+
+.huge {
+ font-size: 15em;
+ margin: 0em;
+}
+
+/* Smaller screens */
+@media only screen and (max-width: 600px) {
+ .logo {
+ margin: 1em;
+ text-align: left;
+ float: left;
+ width: 100%;
+ }
+ .logo img {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ width: 50%;
+ }
+ .content {
+ margin: 0.5em;
+ }
+ .binder {
+ margin: 0em 0em 1.5em 0em;
+ }
+ .sig {
+ font-size: 0.9em;
+ }
+ ul {
+ padding: 0px;
+ }
+}
+.title, .index { display: none; }
diff --git a/gendocs.carp b/gendocs.carp
new file mode 100644
index 0000000..d8d0c45
--- /dev/null
+++ b/gendocs.carp
@@ -0,0 +1,13 @@
+(load "zlib.carp")
+
+(defndynamic gendocs []
+ (do
+ (Project.config "title" "zlib")
+ (Project.config "docs-directory" "./docs/")
+ (Project.config "docs-logo" "")
+ (Project.config "docs-styling" "style.css")
+ (Project.config "docs-generate-index" false)
+ (save-docs ZLib)))
+
+(gendocs)
+(quit)
diff --git a/tests/zlib.carp b/tests/zlib.carp
index c75d373..2438147 100644
--- a/tests/zlib.carp
+++ b/tests/zlib.carp
@@ -6,11 +6,11 @@
(deftest test
(assert-true test
- (Result.success? &(deflate @"hi"))
+ (Result.success? &(deflate "hi"))
"deflation returns success"
)
(assert-true test
- (Result.success? &(inflate (Result.unsafe-from-success (deflate @"hi"))))
+ (Result.success? &(inflate (Result.unsafe-from-success (deflate "hi"))))
"deflation->inflation returns success"
)
(assert-equal test
@@ -20,7 +20,7 @@
)
(assert-equal test
&(Result.Success @"hi")
- &(inflate (Result.unsafe-from-success (deflate @"hi")))
+ &(inflate (Result.unsafe-from-success (deflate "hi")))
"deflation->inflation works"
)
)
diff --git a/zlib.carp b/zlib.carp
index e21d39e..d968515 100644
--- a/zlib.carp
+++ b/zlib.carp
@@ -1,14 +1,54 @@
(relative-include "zlib_helper.h")
(add-cflag "-lz")
+
+(doc ZLib "is a high-level wrapper around [zlib](https://zlib.net/).
+
+## Installation
+
+```clojure
+(load \"https://veitheller.de/git/carpentry/zlib.git@0.0.1\")
+```
+
+## Usage
+
+The `ZLib` module provides only two functions, [`inflate`](#inflate) and
+[`deflate`](#deflate). These functions work in tandem to provide you with data
+compression.
+
+```clojure
+; deflate returns a Result of either binary data or an error message
+(let [deflated (ZLib.deflate \"mystring\")]
+ (match deflated
+ ; inflate returns a Result of either a string or an error message
+ (Success bin) (println* &(inflate bin))
+ (Error msg) (IO.errorln &msg)))
+```
+
+Because it’s a `Result` type, we can apply combinators to it.
+
+```clojure
+(=> (ZLib.deflate \"mystring\")
+ (Result.and-then &ZLib.inflate)
+ (Result.map-error &(fn [msg] (do (println* &msg) msg)))
+)
+```
+
+You can also choose different levels of compression using `inflate-with`. The
+levels are defined in [`ZLib.ZLevel`](#ZLevel), and are `NoCompression`,
+`BestSpeed`, `BestCompression`, and `DefaultCompression`, which is, well, the
+default.")
; i tried doing this in carp, but it’s a bit of a pain to wrap the API
; idiomatically, so for now you’ll only get regular inflation and deflation
(defmodule ZLib
+ (doc ZBytes "is an opaque bytes type with an associated length.")
(register-type ZBytes [
len Int
bytes String
])
+ (private ZRes)
+ (hidden ZRes)
(register-type ZRes)
(defmodule ZRes
(register ok? (Fn [&ZRes] Bool) "ZRes_is_ok")
@@ -17,6 +57,11 @@
(register err (Fn [ZRes] String) "ZRes_err")
)
+ (doc ZLevel "is a type used in conjunction with
+[`deflate-with`](#deflate-with). It controls the compression level.
+
+The constructors are `NoCompression`, `BestSpeed`, `BestCompression`, and
+`DefaultCompression`, which is, well, the default.")
(deftype ZLevel
(NoCompression [])
(BestSpeed [])
@@ -32,19 +77,39 @@
(BestCompression) 9
(DefaultCompression) -1)))
+ (private inflate-)
+ (hidden inflate-)
(register inflate- (Fn [ZBytes] ZRes) "ZLib_inflate_c")
+ (doc inflate "takes a bytes object `s` and returns a `Result`.
+
+The `Result` will be a `Success` containing the inflated string if all goes
+well, and an `Error` returning an error message otherwise.")
(defn inflate [s]
(let [r (inflate- s)]
(if (ZRes.ok? &r)
(Result.Success (ZRes.str r))
(Result.Error (ZRes.err r)))))
- (register deflate- (Fn [String Int] ZRes) "ZLib_deflate_c")
+ (private deflate-)
+ (hidden deflate-)
+ (register deflate- (Fn [&String Int] ZRes) "ZLib_deflate_c")
+ (doc deflate-with "takes a bytes object `s`, a `Zlevel` `level` and returns
+a `Result`.
+
+The `Result` will be a `Success` containing the deflated bytes if all goes
+well, and an `Error` returning an error message otherwise.")
(defn deflate-with [s level]
(let [r (deflate- s (ZLevel.to-int level))]
(if (ZRes.ok? &r)
(Result.Success (ZRes.bytes r))
(Result.Error (ZRes.err r)))))
+ (doc deflate "takes a bytes object `s` and returns a `Result`.
+
+The `Result` will be a `Success` containing the deflated bytes if all goes
+well, and an `Error` returning an error message otherwise.
+
+It is equivalent to calling [`deflate-with`](#deflate-with) with
+`(ZLevel.DefaultCompression)`.")
(defn deflate [s] (deflate-with s (ZLevel.DefaultCompression)))
)
diff --git a/zlib_helper.h b/zlib_helper.h
index 09a6b48..a51c7c0 100644
--- a/zlib_helper.h
+++ b/zlib_helper.h
@@ -134,7 +134,7 @@ err:
return res;
}
-ZRes ZLib_deflate_c(char* s, int level) {
+ZRes ZLib_deflate_c(String* s, int level) {
int ret, flush;
unsigned have;
z_stream strm;
@@ -142,7 +142,7 @@ ZRes ZLib_deflate_c(char* s, int level) {
unsigned char in[CHUNK];
unsigned char out[CHUNK];
int offs = 0;
- int len = strlen(s);
+ int len = strlen(*s);
ZBytes* bytes = malloc(sizeof(ZBytes));
bytes->bytes = NULL;
bytes->len = 0;
@@ -158,7 +158,7 @@ ZRes ZLib_deflate_c(char* s, int level) {
do {
strm.avail_in = min(CHUNK, len-offs);
if (strm.avail_in <= 0) break;
- memcpy(in, s+offs, strm.avail_in);
+ memcpy(in, (*s)+offs, strm.avail_in);
offs += strm.avail_in;
flush = offs >= len-1 ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;