]>
git.proxmox.com Git - libgit2.git/blob - src/zstream.c
2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
13 #define ZSTREAM_BUFFER_SIZE (1024 * 1024)
14 #define ZSTREAM_BUFFER_MIN_EXTRA 8
16 static int zstream_seterr(git_zstream
*zs
)
18 if (zs
->zerr
== Z_OK
|| zs
->zerr
== Z_STREAM_END
)
21 if (zs
->zerr
== Z_MEM_ERROR
)
24 giterr_set(GITERR_ZLIB
, zs
->z
.msg
);
26 giterr_set(GITERR_ZLIB
, "Unknown compression error");
31 int git_zstream_init(git_zstream
*zstream
)
33 zstream
->zerr
= deflateInit(&zstream
->z
, Z_DEFAULT_COMPRESSION
);
34 return zstream_seterr(zstream
);
37 void git_zstream_free(git_zstream
*zstream
)
39 deflateEnd(&zstream
->z
);
42 void git_zstream_reset(git_zstream
*zstream
)
44 deflateReset(&zstream
->z
);
47 zstream
->zerr
= Z_STREAM_END
;
50 int git_zstream_set_input(git_zstream
*zstream
, const void *in
, size_t in_len
)
53 zstream
->in_len
= in_len
;
58 bool git_zstream_done(git_zstream
*zstream
)
60 return (!zstream
->in_len
&& zstream
->zerr
== Z_STREAM_END
);
63 size_t git_zstream_suggest_output_len(git_zstream
*zstream
)
65 if (zstream
->in_len
> ZSTREAM_BUFFER_SIZE
)
66 return ZSTREAM_BUFFER_SIZE
;
67 else if (zstream
->in_len
> ZSTREAM_BUFFER_MIN_EXTRA
)
68 return zstream
->in_len
;
70 return ZSTREAM_BUFFER_MIN_EXTRA
;
73 int git_zstream_get_output(void *out
, size_t *out_len
, git_zstream
*zstream
)
75 int zflush
= Z_FINISH
;
76 size_t out_remain
= *out_len
;
78 while (out_remain
> 0 && zstream
->zerr
!= Z_STREAM_END
) {
79 size_t out_queued
, in_queued
, out_used
, in_used
;
82 zstream
->z
.next_in
= (Bytef
*)zstream
->in
;
83 zstream
->z
.avail_in
= (uInt
)zstream
->in_len
;
84 if ((size_t)zstream
->z
.avail_in
!= zstream
->in_len
) {
85 zstream
->z
.avail_in
= INT_MAX
;
90 in_queued
= (size_t)zstream
->z
.avail_in
;
93 zstream
->z
.next_out
= out
;
94 zstream
->z
.avail_out
= (uInt
)out_remain
;
95 if ((size_t)zstream
->z
.avail_out
!= out_remain
)
96 zstream
->z
.avail_out
= INT_MAX
;
97 out_queued
= (size_t)zstream
->z
.avail_out
;
99 /* compress next chunk */
100 zstream
->zerr
= deflate(&zstream
->z
, zflush
);
102 if (zstream
->zerr
== Z_STREAM_ERROR
)
103 return zstream_seterr(zstream
);
105 out_used
= (out_queued
- zstream
->z
.avail_out
);
106 out_remain
-= out_used
;
107 out
= ((char *)out
) + out_used
;
109 in_used
= (in_queued
- zstream
->z
.avail_in
);
110 zstream
->in_len
-= in_used
;
111 zstream
->in
+= in_used
;
114 /* either we finished the input or we did not flush the data */
115 assert(zstream
->in_len
> 0 || zflush
== Z_FINISH
);
117 /* set out_size to number of bytes actually written to output */
118 *out_len
= *out_len
- out_remain
;
123 int git_zstream_deflatebuf(git_buf
*out
, const void *in
, size_t in_len
)
125 git_zstream zs
= GIT_ZSTREAM_INIT
;
128 if ((error
= git_zstream_init(&zs
)) < 0)
131 if ((error
= git_zstream_set_input(&zs
, in
, in_len
)) < 0)
134 while (!git_zstream_done(&zs
)) {
135 size_t step
= git_zstream_suggest_output_len(&zs
), written
;
137 if ((error
= git_buf_grow_by(out
, step
)) < 0)
140 written
= out
->asize
- out
->size
;
142 if ((error
= git_zstream_get_output(
143 out
->ptr
+ out
->size
, &written
, &zs
)) < 0)
146 out
->size
+= written
;
149 /* NULL terminate for consistency if possible */
150 if (out
->size
< out
->asize
)
151 out
->ptr
[out
->size
] = '\0';
154 git_zstream_free(&zs
);