Skip to content

Commits on Source 5

2.2
2.3 (October 2019)
o Malformed file reading for files with content before the header now works
o Switches to disable malformed file reading or always read as if malformed
o Fix to preserve integers > 2^30 or < -2^30 on 32 bit systems
o Allow [/DCT] as well as /DCT in inline image filter specifications
o Improvements to text width calculation (thanks Alain Frisch)
2.2 (patchlevel 1, September 2017)
o Code for adding annotations (thanks @waclena)
o Indirect encryption dictionaries
o Workaround for Adobe "Error 21" on re-saving encrypted files
o Fix reading of null objects in streams
2.2 (2017)
o Keeps was_linearized flag with every loaded PDF
o Can count the number of revisions in a PDF, and load a specified revision
2.1 (November 2014)
......
......@@ -520,7 +520,7 @@ That's all there is to it!
---
In addition, this program contains the sha2 implemention by Olivier Gay:
In addition, this program contains the sha2 implementation by Olivier Gay:
* FIPS 180-2 SHA-224/256/384/512 implementation
* Last update: 02/02/2007
......
......@@ -12,19 +12,18 @@ PACKS = bigarray
RESULT = camlpdf
LIBINSTALL_FILES = camlpdf.a camlpdf.cma camlpdf.cmxa libcamlpdf_stubs.a \
dllcamlpdf_stubs.* $(foreach x,$(PDFMODS),$x.mli) \
dllcamlpdf_stubs.* $(foreach x,$(PDFMODS),$x.mli) $(foreach x,$(PDFMODS),$x.cmt) \
$(foreach x,$(PDFMODS),$x.cmi) $(foreach x,$(PDFMODS),$x.cmx)
OCAMLNCFLAGS = -g -annot -w -3
OCAMLBCFLAGS = -g -annot -w -3
OCAMLNCFLAGS = -g -safe-string -bin-annot -w -3
OCAMLBCFLAGS = -g -safe-string -bin-annot -w -3
OCAMLLDFLAGS = -g
all : native-code-library byte-code-library htdoc
clean ::
rm -rf doc foo foo2 out.pdf out2.pdf
rm -rf doc foo foo2 out.pdf out2.pdf *.cmt
install : libinstall
-include OCamlMakefile
......@@ -9,13 +9,13 @@ License
---
Copyright Coherent Graphics Ltd 2007 - 2013. Released under the LGPL with
special linking exception. See "LICENCE" for details.
special linking exception. See "LICENSE" for details.
To Build
---
If downloading from Github, obtain the correct source. This means choosing the tag for a
particaular version, such as "v2.1.1". The head of the master branch is
particular version, such as "v2.1.1". The head of the master branch is
unstable.
1. Run "make". This will build camlpdf.a, camlpdf.cma, camlpdf.cmxa and the
......@@ -46,7 +46,7 @@ Acknowledgments
---
The file miniz.c is a (very slightly modified) version of the miniz.c zlib
implementation by Rich Geldreich, avalable here:
implementation by Rich Geldreich, available here:
[http://code.google.com/p/miniz/](http://code.google.com/p/miniz/)
......
camlpdf (2.3-1) unstable; urgency=medium
* Team upload.
* New upstream release, which fixes compilation with OCaml 4.08
(closes: #944276)
* Also install *.cmt files.
* Add a simple as-installed test
-- Ralf Treinen <treinen@debian.org> Tue, 12 Nov 2019 21:37:48 +0100
camlpdf (2.2.1-1) unstable; urgency=medium
* New upstream release
......
......@@ -2,6 +2,7 @@
@OCamlStdlibDir@/camlpdf/*.cmi
@OCamlStdlibDir@/camlpdf/*.mli
@OCamlStdlibDir@/camlpdf/*.cma
@OCamlStdlibDir@/camlpdf/*.cmt
@OCamlStdlibDir@/camlpdf/*.a
OPT: @OCamlStdlibDir@/camlpdf/*.cmx
OPT: @OCamlStdlibDir@/camlpdf/*.cmxa
Tests: upstream-examples
Depends: @, ocaml-nox, ocaml-findlib, poppler-utils
#!/bin/sh
set -e
testdir=${AUTOPKGTEST_TMP:-/tmp}
cp -r examples ${testdir}
cd ${testdir}/examples
echo "** Compiling examples."
make
echo -n "** Executing pdfhello ... "
./pdfhello
echo "done."
echo -n "** Checking generated PDF ... "
pdftotext -layout hello.pdf - | grep -q 'Hello, World!'
echo "OK."
This diff is collapsed.
This diff is collapsed.
......@@ -56,7 +56,7 @@ type toget =
crypt : toget_crypt}
let toget ?(crypt = NoChange) input position length =
{input; position; length; crypt}
{input = input; position = position; length = length; crypt = crypt}
let length_of_toget t = t.length
let position_of_toget t = t.position
......@@ -228,6 +228,7 @@ let rec remove_dict_entry dict key =
for streams. *)
let rec replace_dict_entry dict key value =
match dict with
| Null -> Dictionary (replace key value [])
| Dictionary d -> Dictionary (replace key value d)
| Stream ({contents = (dict', stream)} as s) ->
s := (replace_dict_entry dict' key value, stream);
......@@ -237,6 +238,7 @@ let rec replace_dict_entry dict key value =
(* Add a dict entry, replacing if there. Also works for streams. *)
let rec add_dict_entry dict key value =
match dict with
| Null -> Dictionary (add key value [])
| Dictionary d -> Dictionary (add key value d)
| Stream ({contents = (dict', stream)} as s) ->
s := (add_dict_entry dict' key value, stream);
......@@ -245,7 +247,7 @@ let rec add_dict_entry dict key value =
(* Get a stream from disk if it hasn't already been got. *)
let getstream = function
| Stream ({contents = (d, ToGet {input = i; position = o; length = l; crypt})} as stream) ->
| Stream ({contents = (d, ToGet {input = i; position = o; length = l; crypt = crypt})} as stream) ->
if l = 0 then stream := (d, Got (mkbytes 0)) else
begin try
let data =
......@@ -439,7 +441,7 @@ let lookup_exception (exp : exn) pdf key dict =
let dict' =
match direct pdf dict with
| Dictionary d | Stream {contents = Dictionary d, _} -> d
| _ -> raise (PDFError "not a dictionary")
| _ -> raise (PDFError ("lookup_exception: not a dictionary, key = " ^ key))
in
match lookup key dict' with
| None -> raise exp
......
......@@ -188,6 +188,60 @@ let annotations_of_page pdf page =
| _ -> []
(* Add an annotation to a page *)
(*i let add_annotation pdf page annotation = () i*)
let string_of_subtype = function
| Text -> "/Text" | Link -> "/Link" | FreeText -> "/FreeText" | Line -> "/Line"
| Square -> "/Square" | Circle -> "/Circle" | Polygon -> "/Polygon"
| PolyLine -> "/PolyLine" | Highlight -> "/Highlight" | Underline -> "/Underline"
| Squiggly -> "/Squiggly" | StrikeOut -> "/StrikeOut" | Stamp -> "/Stamp"
| Caret -> "/Caret" | Ink -> "/Ink" | FileAttachment -> "/FileAttachment" | Sound -> "/Sound"
| Movie -> "/Movie" | Widget -> "/Widget" | Screen -> "/Screen"
| PrinterMark -> "/PrinterMark" | TrapNet -> "/TrapNet" | Watermark -> "/Watermark"
| Unknown -> "/Unknown" | Popup _ -> "/Popup" | ThreeDee -> "/3D"
let obj_of_annot t =
let d = [
"/Subtype", Pdf.Name (string_of_subtype t.subtype);
"/Contents", (match t.annot_contents with None -> Pdf.Null | Some s -> Pdf.String s);
"/Rect", (let a,b,c,d = t.rectangle in Pdf.Array [Pdf.Real a; Pdf.Real b; Pdf.Real c; Pdf.Real d]);
"/Border", match t.border.dasharray with
| [||] -> Pdf.Array [Pdf.Real t.border.hradius; Pdf.Real t.border.vradius; Pdf.Real t.border.width;]
| _ -> raise (Pdf.PDFError "non-empty dash array unsupported")
] in
let d = match t.annotrest with
| Pdf.Null -> d
| Pdf.Dictionary d' -> d @ d'
| _ -> raise (Pdf.PDFError "Bad annotation dictionary") in
let colorize d = match t.colour with
| None -> d
| Some (r,g,b) -> (("/C", Pdf.Array [Pdf.Integer r; Pdf.Integer g; Pdf.Integer b])) :: d
in
let subject d = match t.subject with
| None -> d
| Some s -> (("/Subj", Pdf.String s) :: d)
in
Pdf.Dictionary (subject (colorize d))
let make_border ?(vradius=0.0) ?(hradius=0.0) ?(style=NoStyle) ?(dasharray = [||]) width =
{ width = width; vradius = vradius; hradius = hradius; style = style; dasharray = dasharray;}
let make ?content ?(border=make_border 0.0) ?(rectangle=0.,0.,0.,0.) ?colour ?subject subtype = {
subtype = subtype;
annot_contents = content;
subject = subject;
rectangle = rectangle;
border = border;
colour = colour;
annotrest = Pdf.Null;
}
let add_annotation pdf page anno =
let obj = obj_of_annot anno in
match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with
| Some (Pdf.Array annotations) -> { page with
Pdfpage.rest = Pdf.add_dict_entry page.Pdfpage.rest
"/Annots" (Pdf.Array (obj :: annotations)) }
| Some _ -> raise (Pdf.PDFError "Bad annotation dictionary")
| None -> { page with
Pdfpage.rest = Pdf.add_dict_entry page.Pdfpage.rest
"/Annots" (Pdf.Array [obj]) }
......@@ -53,5 +53,15 @@ and t =
val annotations_of_page : Pdf.t -> Pdfpage.t -> t list
(** Return the annotations on a page in a document. *)
(*i val add_annotation : Pdf.pdfdoc -> Pdfdoc.page -> annotation -> unit i*)
val add_annotation : Pdf.t -> Pdfpage.t -> t -> Pdfpage.t
(** Add an annotation to a page in a document. *)
val make_border : ?vradius:float ->
?hradius:float -> ?style:style -> ?dasharray:int array -> float -> border
(** Make a border. *)
val make : ?content:string ->
?border:border ->
?rectangle:float * float * float * float ->
?colour:int * int * int -> ?subject:string -> subtype -> t
(** Make an annotation of a given [subtype]. *)
......@@ -242,17 +242,17 @@ let flate_process f data =
and inlength = bytes_size data in
let input =
(fun buf ->
let s = String.length buf in
let s = Bytes.length buf in
let towrite = min (inlength - !pos) s in
for x = 0 to towrite - 1 do
String.unsafe_set
Bytes.unsafe_set
buf x (Char.unsafe_chr (bget_unsafe data !pos));
incr pos
done;
towrite)
and output =
(fun buf length ->
if length > 0 then strings =| String.sub buf 0 length)
if length > 0 then strings =| Bytes.sub_string buf 0 length)
in
f input output;
bytes_of_strings_rev !strings
......@@ -264,17 +264,17 @@ let decode_flate_input i =
let strings = ref [] in
let input =
(fun buf ->
let s = String.length buf in
let s = Bytes.length buf in
if s > 0 then
begin
match i.input_byte () with
| x when x = Pdfio.no_more -> raise End_of_file
| x -> String.unsafe_set buf 0 (char_of_int x); 1
| x -> Bytes.unsafe_set buf 0 (char_of_int x); 1
end
else 0)
and output =
(fun buf length ->
if length > 0 then strings =| String.sub buf 0 length)
if length > 0 then strings =| Bytes.sub_string buf 0 length)
in
Pdfflate.uncompress input output;
bytes_of_strings_rev !strings
......@@ -286,7 +286,7 @@ let decode_flate stream =
if bytes_size stream = 0 then mkbytes 0 else (* Accept the empty stream. *)
try flate_process Pdfflate.uncompress stream with
Pdfflate.Error (a, b) ->
raise (Couldn'tDecodeStream ("Flate" ^ " " ^ a ^ " " ^ b))
raise (Couldn'tDecodeStream ("Flate" ^ " " ^ a ^ " " ^ b ^ " length " ^ string_of_int (bytes_size stream)))
(* LZW *)
......
......@@ -207,7 +207,16 @@ and decrypt_stream
if is_identity no_encrypt_metadata pdf d then stream else
let data' =
let rec f unhashed_key key data =
let crypt = Pdf.ToDecrypt {Pdf.crypt_type; file_encryption_key; obj; gen; key = unhashed_key; keylength; r} in
let crypt =
Pdf.ToDecrypt
{Pdf.crypt_type = crypt_type;
Pdf.file_encryption_key = file_encryption_key;
Pdf.obj = obj;
Pdf.gen = gen;
Pdf.key = unhashed_key;
Pdf.keylength = keylength;
Pdf.r = r}
in
match data with
Pdf.Got data ->
(*Printf.printf "decrypt_stream: Got, encrypt = %b\n" encrypt;*)
......@@ -247,7 +256,13 @@ and decrypt_stream
(* Otherwise, do the deferred decryption magic *)
let crypt =
Pdf.ToDecrypt
{Pdf.crypt_type; file_encryption_key; obj; gen; key; keylength; r}
{Pdf.crypt_type = crypt_type;
Pdf.file_encryption_key = file_encryption_key;
Pdf.obj = obj;
Pdf.gen = gen;
Pdf.key = key;
Pdf.keylength = keylength;
Pdf.r = r}
in
Pdf.ToGet
(Pdf.toget ~crypt
......@@ -863,10 +878,11 @@ let encrypt_pdf_40bit_inner owner user p user_pw id pdf =
in
match process_cryption false true pdf (Pdfcryptprimitives.ARC4 (40, 2)) user_pw 2 user owner p id 40 None with
| Some pdf ->
let crypt_dict_num = Pdf.addobj pdf crypt_dict in
{pdf with
Pdf.trailerdict =
Pdf.add_dict_entry
pdf.Pdf.trailerdict "/Encrypt" crypt_dict}
pdf.Pdf.trailerdict "/Encrypt" (Pdf.Indirect crypt_dict_num)}
| None -> raise (Pdf.PDFError "Encryption 40 failed")
let encrypt_pdf_40bit user_pw owner_pw banlist pdf =
......@@ -890,9 +906,10 @@ let encrypt_pdf_128bit_inner owner user p user_pw id pdf =
in
match process_cryption false true pdf (Pdfcryptprimitives.ARC4 (128, 3)) user_pw 3 user owner p id 128 None with
| Some pdf ->
let crypt_dict_num = Pdf.addobj pdf crypt_dict in
{pdf with
Pdf.trailerdict =
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" crypt_dict}
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" (Pdf.Indirect crypt_dict_num)}
| None -> raise (Pdf.PDFError "Encryption 128 failed")
let encrypt_pdf_128bit_inner_r4 owner user p user_pw id pdf encrypt_metadata =
......@@ -918,9 +935,10 @@ let encrypt_pdf_128bit_inner_r4 owner user p user_pw id pdf encrypt_metadata =
in
match process_cryption (not encrypt_metadata) true pdf (Pdfcryptprimitives.ARC4 (128, 4)) user_pw 4 user owner p id 128 None with
| Some pdf ->
let crypt_dict_num = Pdf.addobj pdf crypt_dict in
{pdf with
Pdf.trailerdict =
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" crypt_dict}
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" (Pdf.Indirect crypt_dict_num)}
| None -> raise (Pdf.PDFError "Encryption 128 r4 failed")
let encrypt_pdf_128bit user_pw owner_pw banlist pdf =
......@@ -957,9 +975,10 @@ let encrypt_pdf_AES_inner owner user p user_pw id encrypt_metadata pdf =
(not encrypt_metadata) true pdf Pdfcryptprimitives.AESV2 user_pw 4 user owner p id 128 None
with
| Some pdf ->
let crypt_dict_num = Pdf.addobj pdf crypt_dict in
{pdf with
Pdf.trailerdict =
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" crypt_dict}
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" (Pdf.Indirect crypt_dict_num)}
| None -> raise (Pdf.PDFError "Encryption AES failed")
let encrypt_pdf_AES encrypt_metadata user_pw owner_pw banlist pdf =
......@@ -999,9 +1018,10 @@ let encrypt_pdf_AES256_inner iso encrypt_metadata owner user p perms oe ue id ke
(not encrypt_metadata) true pdf (Pdfcryptprimitives.AESV3 iso) "" (if iso then 6 else 5) user owner p id 256 (Some key)
with
| Some pdf ->
let crypt_dict_num = Pdf.addobj pdf crypt_dict in
{pdf with
Pdf.trailerdict =
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" crypt_dict}
Pdf.add_dict_entry pdf.Pdf.trailerdict "/Encrypt" (Pdf.Indirect crypt_dict_num)}
| None -> raise (Pdf.PDFError "256 bit Encryption AES failed")
(* Algorithm 3.10 *)
......
......@@ -11,10 +11,10 @@ external aes_cook_encrypt_key : string -> string = "caml_aes_cook_encrypt_key"
external aes_cook_decrypt_key : string -> string = "caml_aes_cook_decrypt_key"
external aes_encrypt : string -> string -> int -> string -> int -> unit =
external aes_encrypt : string -> caml_bytes -> int -> caml_bytes -> int -> unit =
"caml_aes_encrypt"
external aes_decrypt : string -> string -> int -> string -> int -> unit =
external aes_decrypt : string -> caml_bytes -> int -> caml_bytes -> int -> unit =
"caml_aes_decrypt"
external sha_256 : string -> string = "caml_sha256"
......@@ -155,14 +155,14 @@ let aes_decrypt_data ?(remove_padding = true) nk key data =
done;
let pos = ref 16 in
while !pos < len do
let i = String.make 16 ' '
and o = String.make 16 ' ' in
let i = Bytes.make 16 ' '
and o = Bytes.make 16 ' ' in
for x = 0 to 15 do
i.[x] <- char_of_int (bget_unsafe data (x + !pos))
Bytes.set i x (char_of_int (bget_unsafe data (x + !pos)))
done;
aes_decrypt key i 0 o 0;
for x = 0 to 15 do
bset_unsafe output (x + !pos - 16) (int_of_char o.[x])
bset_unsafe output (x + !pos - 16) (int_of_char (Bytes.get o x))
done;
for x = 0 to 15 do
bset_unsafe
......@@ -184,14 +184,15 @@ let aes_decrypt_data_ecb ?(remove_padding = true) nk key data =
let output = mkbytes size
and pos = ref 0 in
while !pos < size do
let i = String.make 16 ' '
and o = String.make 16 ' ' in
for x = 0 to 15 do i.[x] <-
char_of_int (bget_unsafe data (x + !pos))
let i = Bytes.make 16 ' '
and o = Bytes.make 16 ' ' in
for x = 0 to 15 do
Bytes.set i x
(char_of_int (bget_unsafe data (x + !pos)))
done;
aes_decrypt key i 0 o 0;
for x = 0 to 15 do
bset_unsafe output (x + !pos) (int_of_char o.[x])
bset_unsafe output (x + !pos) (int_of_char (Bytes.get o x))
done;
pos += 16
done;
......@@ -206,10 +207,12 @@ let aes_encrypt_data ?(firstblock = mkiv ()) nk key data =
(fun block ->
let ciphertext =
let src =
string_of_int_array ((array_map2 (lxor)) block !prev_ciphertext)
and dst = String.make 16 ' ' in
let a = array_map2 (lxor) block !prev_ciphertext in
Bytes.init (Array.length a) (fun i -> Char.unsafe_chr a.(i))
and dst = Bytes.make 16 ' ' in
aes_encrypt key src 0 dst 0;
(int_array_of_string dst)
Array.init (Bytes.length dst)
(fun i -> int_of_char (Bytes.unsafe_get dst i))
in
prev_ciphertext := ciphertext;
outblocks =| ciphertext)
......@@ -224,14 +227,15 @@ let aes_encrypt_data_ecb nk key data =
let output = mkbytes size
and pos = ref 0 in
while !pos < size do
let i = String.make 16 ' '
and o = String.make 16 ' ' in
for x = 0 to 15 do i.[x] <-
char_of_int (bget data (x + !pos))
let i = Bytes.make 16 ' '
and o = Bytes.make 16 ' ' in
for x = 0 to 15 do
Bytes.set i x
(char_of_int (bget data (x + !pos)))
done;
aes_encrypt key i 0 o 0;
for x = 0 to 15 do
bset output (x + !pos) (int_of_char o.[x])
bset output (x + !pos) (int_of_char (Bytes.get o x))
done;
pos += 16
done;
......@@ -303,4 +307,3 @@ let decrypt_stream_data crypt_type encrypt file_encryption_key obj gen key keyle
find_hash crypt_type (i32ofi obj) (i32ofi gen) key keylength
in
f hash data
(* Read and Write Destinations *)
(*TODO: Be able to read all destinations from the document (well, all from the
name tree or /Dests in catalog). To be able to write a name tree or dests
similarly. *)
(* TODO: Destinations which are actions -- keep the /Rect etc. *)
open Pdfutil
type targetpage =
......@@ -12,7 +6,9 @@ type targetpage =
| OtherDocPageNumber of int
type t =
| Action of Pdf.pdfobject
| NullDestination
| NamedDestinationElsewhere of string
| XYZ of targetpage * float option * float option * float option
| Fit of targetpage
| FitH of targetpage * float
......@@ -52,6 +48,11 @@ let rec read_destination pdf pdfobject =
Pdf.Name "/XYZ"; l; t; z] ->
XYZ
(read_targetpage p, option_getnum l, option_getnum t, option_getnum z)
| Pdf.Array (* Read common malformed one. *)
[(Pdf.Indirect _ | Pdf.Integer _) as p;
Pdf.Name "/XYZ"; l; t] ->
XYZ
(read_targetpage p, option_getnum l, option_getnum t, None)
| Pdf.Array [(Pdf.Indirect _ | Pdf.Integer _) as p; Pdf.Name "/Fit"] ->
Fit (read_targetpage p)
| Pdf.Array [(Pdf.Indirect _ | Pdf.Integer _) as p; Pdf.Name "/FitH"; t] ->
......@@ -77,11 +78,11 @@ let rec read_destination pdf pdfobject =
| Some dests ->
begin match Pdf.lookup_direct pdf n dests with
| Some dest' -> read_destination pdf dest'
| None -> read_destination_error "A" n
| None -> NamedDestinationElsewhere n
end
| None -> read_destination_error "B" n
| None -> NamedDestinationElsewhere n
end
| None -> read_destination_error "C" n
| None -> raise (Pdf.PDFError "read_destination: no catalog")
end
| Pdf.String s ->
(* PDF 1.2. String object *)
......@@ -93,12 +94,12 @@ let rec read_destination pdf pdfobject =
begin match
Pdf.nametree_lookup pdf (Pdf.String s) destsdict
with
| None -> read_destination_error "D" s
| None -> NamedDestinationElsewhere s
| Some dest -> read_destination pdf (Pdf.direct pdf dest)
end
| _ -> read_destination_error "E" s
| _ -> NamedDestinationElsewhere s
end
| _ -> read_destination_error "F" s
| _ -> NamedDestinationElsewhere s
end
| p -> read_destination_error "G" (Pdfwrite.string_of_pdf p)
......@@ -107,7 +108,9 @@ let pdf_of_targetpage = function
| OtherDocPageNumber i -> Pdf.Integer i
let pdfobject_of_destination = function
| Action a -> a
| NullDestination -> Pdf.Null
| NamedDestinationElsewhere s -> Pdf.String s
| XYZ (p, left, top, zoom) ->
let f = function None -> Pdf.Null | Some n -> Pdf.Real n in
Pdf.Array [pdf_of_targetpage p; Pdf.Name "/XYZ"; f left; f top; f zoom]
......
......@@ -6,9 +6,11 @@ type targetpage =
| PageObject of int
| OtherDocPageNumber of int
(** Destinations. See ISO-32000 for details. *)
(** Destinations (and actions) *)
type t =
| Action of Pdf.pdfobject
| NullDestination
| NamedDestinationElsewhere of string
| XYZ of targetpage * float option * float option * float option
| Fit of targetpage
| FitH of targetpage * float
......
......@@ -14,14 +14,14 @@ type flush_command =
external deflate_init: int -> bool -> stream = "camlzip_deflateInit"
external deflate:
stream -> string -> int -> int -> string -> int -> int -> flush_command
stream -> bytes -> int -> int -> bytes -> int -> int -> flush_command
-> bool * int * int
= "camlzip_deflate_bytecode" "camlzip_deflate"
external deflate_end: stream -> unit = "camlzip_deflateEnd"
external inflate_init: bool -> stream = "camlzip_inflateInit"
external inflate:
stream -> string -> int -> int -> string -> int -> int -> flush_command
stream -> bytes -> int -> int -> bytes -> int -> int -> flush_command
-> bool * int * int
= "camlzip_inflate_bytecode" "camlzip_inflate"
external inflate_end: stream -> unit = "camlzip_inflateEnd"
......@@ -29,8 +29,8 @@ external inflate_end: stream -> unit = "camlzip_inflateEnd"
let buffer_size = 1024
let compress ?(level = 6) ?(header = true) refill flush =
let inbuf = String.create buffer_size
and outbuf = String.create buffer_size in
let inbuf = Bytes.create buffer_size
and outbuf = Bytes.create buffer_size in
let zs = deflate_init level header in
let rec compr inpos inavail =
if inavail = 0 then begin
......@@ -53,8 +53,8 @@ let compress ?(level = 6) ?(header = true) refill flush =
let uncompress ?(header = true) refill flush =
let inbuf = String.create buffer_size
and outbuf = String.create buffer_size in
let inbuf = Bytes.create buffer_size
and outbuf = Bytes.create buffer_size in
let zs = inflate_init header in
let rec uncompr inpos inavail =
if inavail = 0 then begin
......
......@@ -12,11 +12,10 @@ bytes written. The optional argument [level] gives the zlib compression level
zlib header (the default is [true]). *)
val compress:
?level: int -> ?header: bool ->
(string -> int) -> (string -> int -> unit) -> unit
(bytes -> int) -> (bytes -> int -> unit) -> unit
(** Uncompress data. The input and output functions are as described for
[compress]. If [header] is [true], a zlib header is expected (the default is
[true]). *)
val uncompress:
?header: bool -> (string -> int) -> (string -> int -> unit) -> unit
?header: bool -> (bytes -> int) -> (bytes -> int -> unit) -> unit