You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/12/10 21:02:33 UTC

svn commit: r1719188 - in /subversion/trunk/subversion: include/svn_io.h libsvn_subr/io.c tests/libsvn_subr/io-test.c

Author: ivan
Date: Thu Dec 10 20:02:33 2015
New Revision: 1719188

URL: http://svn.apache.org/viewvc?rev=1719188&view=rev
Log:
Use existing APR function in implementation of svn_io_file_readline() for
peeking char after we found '\r' instead of save position and seek back.

* subversion/include/svn_io.h
  (svn_io_file_ungetc): New.

* subversion/libsvn_subr/io.c
  (svn_io_file_ungetc): New. Wrapper around apr_file_ungetc().
  (svn_io_file_readline): Use svn_io_file_ungetc() for peeking char after we
   found '\r' instead of save position and seek back.

* subversion/tests/libsvn_subr/io-test.c
  (test_file_readline): New test for svn_io_file_readline().
  (test_file_ungetc): New test for svn_io_file_ungetc().
  (svn_test_descriptor_t): Add test_file_readline and test_file_ungetc.

Modified:
    subversion/trunk/subversion/include/svn_io.h
    subversion/trunk/subversion/libsvn_subr/io.c
    subversion/trunk/subversion/tests/libsvn_subr/io-test.c

Modified: subversion/trunk/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1719188&r1=1719187&r2=1719188&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_io.h (original)
+++ subversion/trunk/subversion/include/svn_io.h Thu Dec 10 20:02:33 2015
@@ -2206,6 +2206,14 @@ svn_io_file_getc(char *ch,
                  apr_pool_t *pool);
 
 
+/** Wrapper for apr_file_ungetc().
+  * @since New in 1.10
+  */
+svn_error_t *
+svn_io_file_ungetc(char ch,
+                   apr_file_t *file,
+                   apr_pool_t *pool);
+
 /** Wrapper for apr_file_putc().
   * @since New in 1.7
   */
@@ -2222,7 +2230,6 @@ svn_io_file_info_get(apr_finfo_t *finfo,
                      apr_file_t *file,
                      apr_pool_t *pool);
 
-
 /** Set @a *filesize_p to the size of @a file. Use @a pool for temporary
   * allocations.
   *

Modified: subversion/trunk/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/io.c?rev=1719188&r1=1719187&r2=1719188&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/io.c (original)
+++ subversion/trunk/subversion/libsvn_subr/io.c Thu Dec 10 20:02:33 2015
@@ -3722,6 +3722,16 @@ svn_io_file_getc(char *ch, apr_file_t *f
 
 
 svn_error_t *
+svn_io_file_ungetc(char ch, apr_file_t *file, apr_pool_t *pool)
+{
+  return do_io_file_wrapper_cleanup(file, apr_file_ungetc(ch, file),
+                                    N_("Can't unget char to file '%s'"),
+                                    N_("Can't unget char to stream"),
+                                    pool);
+}
+
+
+svn_error_t *
 svn_io_file_putc(char ch, apr_file_t *file, apr_pool_t *pool)
 {
   return do_io_file_wrapper_cleanup(file, apr_file_putc(ch, file),
@@ -5364,11 +5374,7 @@ svn_io_file_readline(apr_file_t *file,
 
           if (!found_eof && len < max_len)
             {
-              apr_off_t pos;
-
               /* Check for "\r\n" by peeking at the next byte. */
-              pos = 0;
-              SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
               SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
                                              &found_eof, scratch_pool));
               if (numbytes == 1 && c == '\n')
@@ -5379,7 +5385,7 @@ svn_io_file_readline(apr_file_t *file,
               else
                 {
                   /* Pretend we never peeked. */
-                  SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
+                  SVN_ERR(svn_io_file_ungetc(c, file, scratch_pool));
                   found_eof = FALSE;
                   numbytes = 1;
                 }

Modified: subversion/trunk/subversion/tests/libsvn_subr/io-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/io-test.c?rev=1719188&r1=1719187&r2=1719188&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/io-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/io-test.c Thu Dec 10 20:02:33 2015
@@ -592,6 +592,114 @@ test_read_length_line(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_file_readline(apr_pool_t *pool)
+{
+  const char *tmp_dir;
+  const char *tmp_file;
+  svn_stringbuf_t *buf;
+  apr_file_t *f;
+  svn_error_t *err;
+  const char *eol;
+  svn_boolean_t eof;
+
+  SVN_ERR(svn_test_make_sandbox_dir(&tmp_dir, "test_file_readline",
+                                    pool));
+
+  tmp_file = svn_dirent_join(tmp_dir, "foo", pool);
+
+  SVN_ERR(svn_io_file_create(tmp_file, "CR\rLF\nCRLF\r\nno-eol", pool));
+
+  SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ | APR_BUFFERED,
+                           APR_OS_DEFAULT, pool));
+  err = svn_io_file_readline(f, &buf, &eol, &eof, APR_SIZE_MAX, pool, pool);
+  SVN_ERR(err);
+  SVN_TEST_STRING_ASSERT(buf->data, "CR");
+  SVN_TEST_STRING_ASSERT(eol, "\r");
+  SVN_TEST_ASSERT(!eof);
+
+  err = svn_io_file_readline(f, &buf, &eol, &eof, APR_SIZE_MAX, pool, pool);
+  SVN_ERR(err);
+  SVN_TEST_STRING_ASSERT(buf->data, "LF");
+  SVN_TEST_STRING_ASSERT(eol, "\n");
+  SVN_TEST_ASSERT(!eof);
+
+  err = svn_io_file_readline(f, &buf, &eol, &eof, APR_SIZE_MAX, pool, pool);
+  SVN_ERR(err);
+  SVN_TEST_STRING_ASSERT(buf->data, "CRLF");
+  SVN_TEST_STRING_ASSERT(eol, "\r\n");
+  SVN_TEST_ASSERT(!eof);
+
+  err = svn_io_file_readline(f, &buf, &eol, &eof, APR_SIZE_MAX, pool, pool);
+  SVN_ERR(err);
+  SVN_TEST_STRING_ASSERT(buf->data, "no-eol");
+  SVN_TEST_STRING_ASSERT(eol, NULL);
+  SVN_TEST_ASSERT(eof);
+
+  /* Further reads still returns EOF. */
+  err = svn_io_file_readline(f, &buf, &eol, &eof, APR_SIZE_MAX, pool, pool);
+  SVN_ERR(err);
+  SVN_TEST_STRING_ASSERT(buf->data, "");
+  SVN_TEST_STRING_ASSERT(eol, NULL);
+  SVN_TEST_ASSERT(eof);
+
+  SVN_ERR(svn_io_file_close(f, pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_file_ungetc(apr_pool_t *pool)
+{
+  const char *tmp_dir;
+  const char *tmp_file;
+  apr_file_t *f;
+  char c;
+
+  SVN_ERR(svn_test_make_sandbox_dir(&tmp_dir, "test_file_ungetc",
+                                    pool));
+
+  tmp_file = svn_dirent_join(tmp_dir, "foo", pool);
+  SVN_ERR(svn_io_file_create(tmp_file, "12", pool));
+
+  /* Test using buffered I/O. */
+  SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ | APR_BUFFERED,
+                           APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '1');
+
+  SVN_ERR(svn_io_file_ungetc(c, f, pool));
+
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '1');
+
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '2');
+
+  SVN_TEST_ASSERT_ERROR(svn_io_file_getc(&c, f, pool), APR_EOF);
+
+  SVN_ERR(svn_io_file_close(f, pool));
+
+  /* Also make sure that ungetc works fine unbuffered I/O. */
+  SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ, APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '1');
+
+  SVN_ERR(svn_io_file_ungetc(c, f, pool));
+
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '1');
+
+  SVN_ERR(svn_io_file_getc(&c, f, pool));
+  SVN_TEST_ASSERT(c == '2');
+
+  SVN_TEST_ASSERT_ERROR(svn_io_file_getc(&c, f, pool), APR_EOF);
+
+  SVN_ERR(svn_io_file_close(f, pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Move the read pointer in FILE to absolute position OFFSET and align
  * the read buffer to multiples of BLOCK_SIZE.  BUFFERED is set only if
  * FILE actually uses a read buffer.  Use POOL for allocations.
@@ -990,6 +1098,10 @@ static struct svn_test_descriptor_t test
                    "test svn_io_file_rename2"),
     SVN_TEST_PASS2(test_read_length_line,
                    "test svn_io_read_length_line()"),
+    SVN_TEST_PASS2(test_file_readline,
+                   "test svn_io_file_readline()"),
+    SVN_TEST_PASS2(test_file_ungetc,
+                   "test svn_io_file_ungetc()"),
     SVN_TEST_NULL
   };