Author: stsp
Date: Sun Jan 3 21:27:00 2010
New Revision: 895482
URL: http://svn.apache.org/viewvc?rev=895482&view=rev
Log:
Add support for reading lines with arbitrary EOL markers from a stream.
* subversion/include/svn_io.h
(svn_stream_readline_detect_eol): Declare.
* subversion/libsvn_subr/stream.c
(scan_eol): New helper function.
(stream_readline): Move all of svn_stream_readline() into this new helper
function, which can optionally detect line-endings automatically.
(svn_stream_readline, svn_stream_readline_detect_eol): Implement using
the new stream_readline() helper.
Modified:
subversion/trunk/subversion/include/svn_io.h
subversion/trunk/subversion/libsvn_subr/stream.c
Modified: subversion/trunk/subversion/include/svn_io.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=895482&r1=895481&r2=895482&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_io.h (original)
+++ subversion/trunk/subversion/include/svn_io.h Sun Jan 3 21:27:00 2010
@@ -1135,6 +1135,20 @@
svn_boolean_t *eof,
apr_pool_t *pool);
+/**
+ * Similar to svn_stream_readline(). The line-terminator is detected
+ * automatically. If @a eol is not NULL, the detected line-terminator
+ * is returned in @a *eol. If EOF is reached and the stream does not
+ * end with a newline character, @a *eol will be NULL.
+ *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_stream_readline_detect_eol(svn_stream_t *stream,
+ svn_stringbuf_t **stringbuf,
+ const char **eol,
+ svn_boolean_t *eof,
+ apr_pool_t *pool);
/**
* Read the contents of the readable stream @a from and write them to the
Modified: subversion/trunk/subversion/libsvn_subr/stream.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=895482&r1=895481&r2=895482&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/stream.c (original)
+++ subversion/trunk/subversion/libsvn_subr/stream.c Sun Jan 3 21:27:00 2010
@@ -42,6 +42,7 @@
#include "svn_utf.h"
#include "svn_checksum.h"
#include "svn_path.h"
+#include "private/svn_eol_private.h"
struct svn_stream_t {
@@ -254,16 +255,55 @@
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_stream_readline(svn_stream_t *stream,
- svn_stringbuf_t **stringbuf,
- const char *eol,
- svn_boolean_t *eof,
- apr_pool_t *pool)
+/* Scan STREAM for an end-of-line indicatior, and return it in *EOL.
+ * Set *EOL to NULL if the stream runs out before an end-of-line indicator
+ * is found. */
+static svn_error_t *
+scan_eol(const char **eol, svn_stream_t *stream)
+{
+ const char *eol_str;
+
+ SVN_ERR(svn_stream_mark(stream, TRUE));
+
+ eol_str = NULL;
+ while (! eol_str)
+ {
+ char buf[512];
+ apr_size_t len;
+
+ len = sizeof(buf);
+ SVN_ERR(svn_stream_read(stream, buf, &len));
+ if (len == 0)
+ break; /* EOF */
+ eol_str = svn_eol__detect_eol(buf, buf + len);
+ }
+
+ SVN_ERR(svn_stream_reset(stream));
+ SVN_ERR(svn_stream_mark(stream, FALSE));
+
+ *eol = eol_str;
+
+ return SVN_NO_ERROR;
+}
+
+/* Guts of svn_stream_readline() and svn_stream_readline_detect_eol().
+ * Returns the line read from STREAM in *STRINGBUF, and indicates
+ * end-of-file in *EOF. If DETECT_EOL is TRUE, the end-of-line indicator
+ * is detected automatically and returned in *EOL.
+ * If DETECT_EOL is FALSE, *EOL must point to the desired end-of-line
+ * indicator. STRINGBUF is allocated in POOL. */
+static svn_error_t *
+stream_readline(svn_stringbuf_t **stringbuf,
+ svn_boolean_t *eof,
+ const char **eol,
+ svn_stream_t *stream,
+ svn_boolean_t detect_eol,
+ apr_pool_t *pool)
{
svn_stringbuf_t *str;
apr_pool_t *iterpool;
svn_boolean_t filtered;
+ const char *eol_str;
*eof = FALSE;
@@ -282,8 +322,22 @@
80 chars. */
str = svn_stringbuf_create_ensure(80, iterpool);
+ if (detect_eol)
+ {
+ SVN_ERR(scan_eol(&eol_str, stream));
+ if (eol)
+ *eol = eol_str;
+ if (! eol_str)
+ {
+ /* No newline until EOF, EOL_STR can be anything. */
+ eol_str = APR_EOL_STR;
+ }
+ }
+ else
+ eol_str = *eol;
+
/* Read into STR up to and including the next EOL sequence. */
- match = eol;
+ match = eol_str;
while (*match)
{
numbytes = 1;
@@ -294,7 +348,7 @@
*eof = TRUE;
/* We know we don't have a whole EOL sequence, but ensure we
* don't chop off any partial EOL sequence that we may have. */
- match = eol;
+ match = eol_str;
/* Process this short (or empty) line just like any other
* except with *EOF set. */
break;
@@ -303,12 +357,12 @@
if (c == *match)
match++;
else
- match = eol;
+ match = eol_str;
svn_stringbuf_appendbytes(str, &c, 1);
}
- svn_stringbuf_chop(str, match - eol);
+ svn_stringbuf_chop(str, match - eol_str);
SVN_ERR(line_filter(stream, &filtered, str->data, iterpool));
}
@@ -329,6 +383,28 @@
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_stream_readline(svn_stream_t *stream,
+ svn_stringbuf_t **stringbuf,
+ const char *eol,
+ svn_boolean_t *eof,
+ apr_pool_t *pool)
+{
+ return svn_error_return(stream_readline(stringbuf, eof, &eol, stream,
+ FALSE, pool));
+}
+
+svn_error_t *
+svn_stream_readline_detect_eol(svn_stream_t *stream,
+ svn_stringbuf_t **stringbuf,
+ const char **eol,
+ svn_boolean_t *eof,
+ apr_pool_t *pool)
+{
+ return svn_error_return(stream_readline(stringbuf, eof, eol, stream,
+ TRUE, pool));
+}
+
svn_error_t *svn_stream_copy3(svn_stream_t *from, svn_stream_t *to,
svn_cancel_func_t cancel_func,