subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1129947 - in /subversion/trunk/subversion: include/private/svn_eol_private.h libsvn_diff/diff_file.c libsvn_diff/parse-diff.c libsvn_subr/eol.c libsvn_subr/stream.c
Date Tue, 31 May 2011 22:36:13 GMT
Author: stsp
Date: Tue May 31 22:36:13 2011
New Revision: 1129947

URL: http://svn.apache.org/viewvc?rev=1129947&view=rev
Log:
Make it easier for callers of svn_eol__detect_eol() to reliably detect
two-byte newline sequences that overlap buffer boundaries. Update a few
callers to take advantage of this.

* subversion/libsvn_diff/diff_file.c
  (svn_diff_file_output_merge2): Update caller. Pass NULL for EOLP for now.

* subversion/libsvn_diff/parse-diff.c
  (scan_eol): Update caller. Properly detect "\r\n" sequences that overlap
   buffer boundaries. Previous code added in r1129804 wasn't correct for
   the case where the buffer contains more than one newline sequence.

* subversion/include/private/svn_eol_private.h
  (svn_eol__detect_eol): Update signature and docstring.

* subversion/libsvn_subr/eol.c
  (svn_eol__detect_eol): Remove ENDP parameter, replaced by LEN parameter
   indicating length of the buffer (suggested by Julian). Add EOLP output
   paramater which contains the address of the first byte of the eol sequence,
   if any. This allows callers to tell where in the buffer the newline was
   found, and take appropriate action if the very last byte in the buffer
   was '\r' (which might be the start of an "\r\n" sequence).
  (svn_eol__detect_file_eol): Update caller. Pass NULL for EOLP for now.

* subversion/libsvn_subr/stream.c
  (scan_eol): Update caller. Detect "\r\n" sequences that overlap buffer
   boundaries.

Modified:
    subversion/trunk/subversion/include/private/svn_eol_private.h
    subversion/trunk/subversion/libsvn_diff/diff_file.c
    subversion/trunk/subversion/libsvn_diff/parse-diff.c
    subversion/trunk/subversion/libsvn_subr/eol.c
    subversion/trunk/subversion/libsvn_subr/stream.c

Modified: subversion/trunk/subversion/include/private/svn_eol_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_eol_private.h?rev=1129947&r1=1129946&r2=1129947&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_eol_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_eol_private.h Tue May 31 22:36:13 2011
@@ -48,25 +48,29 @@ extern "C" {
 char *
 svn_eol__find_eol_start(char *buf, apr_size_t len);
 
-/* Return the first eol marker found in [@a buf, @a endp) as a
- * NUL-terminated string, or NULL if no eol marker is found.
+/* Return the first eol marker found in buffer @a buf as a NUL-terminated
+ * string, or NULL if no eol marker is found. Do not examine more than
+ * @a len bytes in @a buf.
  *
  * If the last valid character of @a buf is the first byte of a
  * potentially two-byte eol sequence, just return that single-character
  * sequence, that is, assume @a buf represents a CR-only or LF-only file.
  * This is correct for callers that pass an entire file at once, and is
- * no more likely to be incorrect than correct for any caller that
- * doesn't.
+ * no more likely to be incorrect than correct for any caller that doesn't.
  *
- * The returned string is statically allocated.
+ * The returned string is statically allocated, i.e. it is NOT a pointer
+ * to an address within @a buf.
  *
- * ### [JAF] Does it make sense for this to use "[buf, end)" while
- *     svn_eol__find_eol_start() uses "buf, len"?
+ * If an eol marker is found and @a eolp is not NULL, store in @a *eolp
+ * the address within @a buf of the first byte of the eol marker.
+ * This allows callers to tell whether there might be more than one eol
+ * sequence in @a buf, as well as detect two-byte eol sequences that
+ * span buffer boundaries.
  *
  * @since New in 1.7
  */
 const char *
-svn_eol__detect_eol(char *buf, char *endp);
+svn_eol__detect_eol(char *buf, apr_size_t len, char **eolp);
 
 /* Set @a *eol to the EOL marker used in @a file.
  * If it cannot be detected, set @a *eol to NULL.

Modified: subversion/trunk/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/diff_file.c?rev=1129947&r1=1129946&r2=1129947&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/trunk/subversion/libsvn_diff/diff_file.c Tue May 31 22:36:13 2011
@@ -2305,7 +2305,8 @@ svn_diff_file_output_merge2(svn_stream_t
   /* Check what eol marker we should use for conflict markers.
      We use the eol marker of the modified file and fall back on the
      platform's eol marker if that file doesn't contain any newlines. */
-  eol = svn_eol__detect_eol(baton.buffer[1], baton.endp[1]);
+  eol = svn_eol__detect_eol(baton.buffer[1], baton.endp[1] - baton.buffer[1],
+                            NULL);
   if (! eol)
     eol = APR_EOL_STR;
   baton.marker_eol = eol;

Modified: subversion/trunk/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_diff/parse-diff.c?rev=1129947&r1=1129946&r2=1129947&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/trunk/subversion/libsvn_diff/parse-diff.c Tue May 31 22:36:13 2011
@@ -300,15 +300,17 @@ scan_eol(const char **eol, apr_file_t *f
 
       if (len > 0)
         {
+          char *eolp;
+
           buf[len] = '\0';
           total_len += len;
 
-          eol_str = svn_eol__detect_eol(buf, buf + len);
+          eol_str = svn_eol__detect_eol(buf, len, &eolp);
 
           /* Detect the case where '\r' is the last character in the buffer
            * and '\n' would be the first character in the next buffer. */
           if (eol_str && eol_str[0] == '\r' && eol_str[1] == '\0' &&
-              buf[len - 1] == '\r')
+              eolp == buf + len)
             {
               len = 1;
               SVN_ERR(svn_io_file_read_full2(file, buf, 1, &len, &eof, pool));

Modified: subversion/trunk/subversion/libsvn_subr/eol.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/eol.c?rev=1129947&r1=1129946&r2=1129947&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/eol.c (original)
+++ subversion/trunk/subversion/libsvn_subr/eol.c Tue May 31 22:36:13 2011
@@ -96,20 +96,22 @@ svn_eol__find_eol_start(char *buf, apr_s
 }
 
 const char *
-svn_eol__detect_eol(char *buf, char *endp)
+svn_eol__detect_eol(char *buf, apr_size_t len, char **eolp)
 {
-  const char *eol;
+  char *eol;
 
-  SVN_ERR_ASSERT_NO_RETURN(buf <= endp);
-  eol = svn_eol__find_eol_start(buf, endp - buf);
+  eol = svn_eol__find_eol_start(buf, len);
   if (eol)
     {
+      if (eolp)
+        *eolp = eol;
+
       if (*eol == '\n')
         return "\n";
 
       /* We found a CR. */
       ++eol;
-      if (eol == endp || *eol != '\n')
+      if (eol == buf + len || *eol != '\n')
         return "\r";
       return "\r\n";
     }
@@ -163,7 +165,7 @@ svn_eol__detect_file_eol(const char **eo
       /* Try to detect the EOL style of the file by searching the
        * current chunk. */
       SVN_ERR_ASSERT(nbytes <= sizeof(buf));
-      *eol = svn_eol__detect_eol(buf, buf + nbytes);
+      *eol = svn_eol__detect_eol(buf, nbytes, NULL);
     }
   while (*eol == NULL);
 

Modified: subversion/trunk/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1129947&r1=1129946&r2=1129947&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/stream.c (original)
+++ subversion/trunk/subversion/libsvn_subr/stream.c Tue May 31 22:36:13 2011
@@ -258,13 +258,27 @@ scan_eol(const char **eol, svn_stream_t 
   while (! eol_str)
     {
       char buf[512];
+      char *eolp;
       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);
+      eol_str = svn_eol__detect_eol(buf, len, &eolp);
+
+      /* Detect the case where '\r' is the last character in the buffer
+       * and '\n' would be the first character in the next buffer. */
+      if (eol_str && eol_str[0] == '\r' && eol_str[1] == '\0' &&
+          eolp == buf + len)
+        {
+          len = 1;
+          SVN_ERR(svn_stream_read(stream, buf, &len));
+          if (len == 0)
+            break; /* EOF */
+          else if (*buf == '\n')
+            eol_str = "\r\n";
+        }
     }
 
   SVN_ERR(svn_stream_seek(stream, mark));



Mime
View raw message