Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_subr/subst.c view on Meta::CPAN
SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,
b->src_format,
&b->src_format_len,
b->newline_buf,
b->newline_off, dst,
b->translated_eol, b->repair));
b->newline_off = 0;
break;
}
}
}
}
else
{
if (b->newline_off)
{
SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,
b->src_format, &b->src_format_len,
b->newline_buf, b->newline_off,
dst, b->translated_eol, b->repair));
b->newline_off = 0;
}
if (b->keyword_off)
{
SVN_ERR(translate_write(dst, b->keyword_buf, b->keyword_off));
b->keyword_off = 0;
}
}
return SVN_NO_ERROR;
}
/* Baton for use with translated stream callbacks. */
struct translated_stream_baton
{
/* Stream to take input from (before translation) on read
/write output to (after translation) on write. */
svn_stream_t *stream;
/* Input/Output translation batons to make them separate chunk streams. */
struct translation_baton *in_baton, *out_baton;
/* Remembers whether any write operations have taken place;
if so, we need to flush the output chunk stream. */
svn_boolean_t written;
/* Buffer to hold translated read data. */
svn_stringbuf_t *readbuf;
/* Offset of the first non-read character in readbuf. */
apr_size_t readbuf_off;
/* Buffer to hold read data
between svn_stream_read() and translate_chunk(). */
char *buf;
#define SVN__TRANSLATION_BUF_SIZE (SVN__STREAM_CHUNK_SIZE + 1)
/* Pool for callback iterations */
apr_pool_t *iterpool;
};
/* Implements svn_read_fn_t. */
static svn_error_t *
translated_stream_read(void *baton,
char *buffer,
apr_size_t *len)
{
struct translated_stream_baton *b = baton;
apr_size_t readlen = SVN__STREAM_CHUNK_SIZE;
apr_size_t unsatisfied = *len;
apr_size_t off = 0;
/* Optimization for a frequent special case. The configuration parser (and
a few others) reads the stream one byte at a time. All the memcpy, pool
clearing etc. imposes a huge overhead in that case. In most cases, we
can just take that single byte directly from the read buffer.
Since *len > 1 requires lots of code to be run anyways, we can afford
the extra overhead of checking for *len == 1.
See <http://mail-archives.apache.org/mod_mbox/subversion-dev/201003.mbox/%3C4B94011E.1070207@alice-dsl.de%3E>.
*/
if (unsatisfied == 1 && b->readbuf_off < b->readbuf->len)
{
/* Just take it from the read buffer */
*buffer = b->readbuf->data[b->readbuf_off++];
return SVN_NO_ERROR;
}
/* Standard code path. */
while (readlen == SVN__STREAM_CHUNK_SIZE && unsatisfied > 0)
{
apr_size_t to_copy;
apr_size_t buffer_remainder;
svn_pool_clear(b->iterpool);
/* fill read buffer, if necessary */
if (! (b->readbuf_off < b->readbuf->len))
{
svn_stream_t *buf_stream;
svn_stringbuf_setempty(b->readbuf);
b->readbuf_off = 0;
SVN_ERR(svn_stream_read(b->stream, b->buf, &readlen));
buf_stream = svn_stream_from_stringbuf(b->readbuf, b->iterpool);
SVN_ERR(translate_chunk(buf_stream, b->in_baton, b->buf,
readlen, b->iterpool));
if (readlen != SVN__STREAM_CHUNK_SIZE)
SVN_ERR(translate_chunk(buf_stream, b->in_baton, NULL, 0,
b->iterpool));
SVN_ERR(svn_stream_close(buf_stream));
}
( run in 1.975 second using v1.01-cache-2.11-cpan-71847e10f99 )