📄 stream.c
字号:
{
/* Empty, since we allocate on the pool */
}
/* Converts a zlib error to an svn_error_t. zerr is the error code,
function is the function name, and stream is the z_stream we are
using. */
static svn_error_t *
zerr_to_svn_error (int zerr, const char *function, z_stream *stream)
{
apr_status_t status;
const char *message;
if (zerr == Z_OK)
return SVN_NO_ERROR;
switch (zerr)
{
case Z_STREAM_ERROR:
status = SVN_ERR_STREAM_MALFORMED_DATA;
message = "stream error";
break;
case Z_MEM_ERROR:
status = APR_ENOMEM;
message = "out of memory";
break;
case Z_BUF_ERROR:
status = APR_ENOMEM;
message = "buffer error";
break;
case Z_VERSION_ERROR:
status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
message = "version error";
break;
case Z_DATA_ERROR:
status = SVN_ERR_STREAM_MALFORMED_DATA;
message = "corrupted data";
break;
default:
status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
message = "error";
break;
}
if (stream->msg != NULL)
return svn_error_createf (status, NULL, "zlib (%s): %s: %s", function,
message, stream->msg);
else
return svn_error_createf (status, NULL, "zlib (%s): %s", function,
message);
}
/* Helper function to figure out the sync mode */
static svn_error_t *
read_helper_gz (svn_read_fn_t read_fn,
void *baton,
char *buffer,
uInt *len, int *zflush)
{
uInt orig_len = *len;
/* There's no reason this value should grow bigger than the range of
uInt, but Subversion's API requires apr_size_t. */
apr_size_t apr_len = (apr_size_t) *len;
SVN_ERR ((*read_fn) (baton, buffer, &apr_len));
/* Type cast back to uInt type that zlib uses. On LP64 platforms
apr_size_t will be bigger than uInt. */
*len = (uInt) apr_len;
/* I wanted to use Z_FINISH here, but we need to know our buffer is
big enough */
*zflush = (*len) < orig_len ? Z_SYNC_FLUSH : Z_SYNC_FLUSH;
return SVN_NO_ERROR;
}
/* Handle reading from a compressed stream */
static svn_error_t *
read_handler_gz (void *baton, char *buffer, apr_size_t *len)
{
struct zbaton *btn = baton;
int zerr;
if (btn->in == NULL)
{
btn->in = apr_palloc (btn->pool, sizeof (z_stream));
btn->in->zalloc = zalloc;
btn->in->zfree = zfree;
btn->in->opaque = btn->pool;
btn->read_buffer = apr_palloc(btn->pool, ZBUFFER_SIZE);
btn->in->next_in = btn->read_buffer;
btn->in->avail_in = ZBUFFER_SIZE;
SVN_ERR (read_helper_gz (btn->read, btn->subbaton, btn->read_buffer,
&btn->in->avail_in, &btn->read_flush));
zerr = inflateInit (btn->in);
SVN_ERR (zerr_to_svn_error (zerr, "inflateInit", btn->in));
}
btn->in->next_out = buffer;
btn->in->avail_out = *len;
while (btn->in->avail_out > 0)
{
if (btn->in->avail_in <= 0)
{
btn->in->avail_in = ZBUFFER_SIZE;
btn->in->next_in = btn->read_buffer;
SVN_ERR (read_helper_gz (btn->read, btn->subbaton, btn->read_buffer,
&btn->in->avail_in, &btn->read_flush));
}
zerr = inflate (btn->in, btn->read_flush);
if (zerr == Z_STREAM_END)
break;
else if (zerr != Z_OK)
return zerr_to_svn_error(zerr, "inflate", btn->in);
}
*len -= btn->in->avail_out;
return SVN_NO_ERROR;
}
/* Compress data and write it to the substream */
static svn_error_t *
write_handler_gz (void *baton, const char *buffer, apr_size_t *len)
{
struct zbaton *btn = baton;
apr_pool_t *subpool;
void *write_buf;
apr_size_t buf_size, write_len;
int zerr;
if (btn->out == NULL)
{
btn->out = apr_palloc (btn->pool, sizeof (z_stream));
btn->out->zalloc = zalloc;
btn->out->zfree = zfree;
btn->out->opaque = btn->pool;
zerr = deflateInit (btn->out, Z_DEFAULT_COMPRESSION);
SVN_ERR (zerr_to_svn_error (zerr, "deflateInit", btn->out));
}
/* The largest buffer we should need is 0.1% larger than the
compressed data, + 12 bytes. This info comes from zlib.h. */
buf_size = *len + (*len / 1000) + 13;
subpool = svn_pool_create (btn->pool);
write_buf = apr_palloc (subpool, buf_size);
btn->out->next_in = (char *) buffer;
btn->out->avail_in = *len;
while (btn->out->avail_in > 0)
{
btn->out->next_out = write_buf;
btn->out->avail_out = buf_size;
zerr = deflate (btn->out, Z_NO_FLUSH);
SVN_ERR (zerr_to_svn_error (zerr, "deflate", btn->out));
write_len = buf_size - btn->out->avail_out;
if (write_len > 0)
SVN_ERR (btn->write (btn->subbaton, write_buf, &write_len));
}
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
/* Handle flushing and closing the stream */
static svn_error_t *
close_handler_gz (void *baton)
{
struct zbaton *btn = baton;
int zerr;
if (btn->in != NULL)
{
zerr = inflateEnd(btn->in);
SVN_ERR (zerr_to_svn_error (zerr, "inflateEnd", btn->in));
}
if (btn->out != NULL)
{
void *buf;
apr_size_t write_len;
buf = apr_palloc (btn->pool, ZBUFFER_SIZE);
while (TRUE)
{
btn->out->next_out = buf;
btn->out->avail_out = ZBUFFER_SIZE;
zerr = deflate (btn->out, Z_FINISH);
if (zerr != Z_STREAM_END && zerr != Z_OK)
return zerr_to_svn_error (zerr, "deflate", btn->out);
write_len = ZBUFFER_SIZE - btn->out->avail_out;
if (write_len > 0)
SVN_ERR (btn->write (btn->subbaton, buf, &write_len));
if (zerr == Z_STREAM_END)
break;
}
zerr = deflateEnd(btn->out);
SVN_ERR (zerr_to_svn_error (zerr, "deflateEnd", btn->out));
}
if (btn->close != NULL)
return btn->close (btn->subbaton);
else
return SVN_NO_ERROR;
}
#endif /* SVN_HAVE_ZLIB */
svn_stream_t *
svn_stream_compressed (svn_stream_t *stream, apr_pool_t *pool)
{
#ifdef SVN_HAVE_ZLIB
struct svn_stream_t *zstream;
struct zbaton *baton;
assert(stream != NULL);
baton = apr_palloc (pool, sizeof (*baton));
baton->in = baton->out = NULL;
baton->read = stream->read_fn;
baton->write = stream->write_fn;
baton->close = stream->close_fn;
baton->subbaton = stream->baton;
baton->pool = pool;
baton->read_buffer = NULL;
baton->read_flush = Z_SYNC_FLUSH;
zstream = svn_stream_create(baton, pool);
svn_stream_set_read(zstream, read_handler_gz);
svn_stream_set_write(zstream, write_handler_gz);
svn_stream_set_close(zstream, close_handler_gz);
return zstream;
#else
return stream;
#endif /* SVN_HAVE_ZLIB */
}
/* Miscellaneous stream functions. */
struct string_stream_baton
{
svn_stringbuf_t *str;
apr_size_t amt_read;
};
static svn_error_t *
read_handler_string (void *baton, char *buffer, apr_size_t *len)
{
struct string_stream_baton *btn = baton;
apr_size_t left_to_read = btn->str->len - btn->amt_read;
*len = (*len > left_to_read) ? left_to_read : *len;
memcpy (buffer, btn->str->data + btn->amt_read, *len);
btn->amt_read += *len;
return SVN_NO_ERROR;
}
static svn_error_t *
write_handler_string (void *baton, const char *data, apr_size_t *len)
{
struct string_stream_baton *btn = baton;
svn_stringbuf_appendbytes (btn->str, data, *len);
return SVN_NO_ERROR;
}
svn_stream_t *
svn_stream_from_stringbuf (svn_stringbuf_t *str,
apr_pool_t *pool)
{
svn_stream_t *stream;
struct string_stream_baton *baton;
if (! str)
return svn_stream_empty (pool);
baton = apr_palloc (pool, sizeof (*baton));
baton->str = str;
baton->amt_read = 0;
stream = svn_stream_create (baton, pool);
svn_stream_set_read (stream, read_handler_string);
svn_stream_set_write (stream, write_handler_string);
return stream;
}
svn_error_t *
svn_stream_for_stdout (svn_stream_t **out, apr_pool_t *pool)
{
apr_file_t *stdout_file;
apr_status_t apr_err;
apr_err = apr_file_open_stdout (&stdout_file, pool);
if (apr_err)
return svn_error_wrap_apr (apr_err, "Can't open stdout");
*out = svn_stream_from_aprfile (stdout_file, pool);
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -