You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by jc...@apache.org on 2010/12/22 09:32:13 UTC

svn commit: r1051789 - /subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c

Author: jcorvel
Date: Wed Dec 22 08:32:12 2010
New Revision: 1051789

URL: http://svn.apache.org/viewvc?rev=1051789&view=rev
Log:
On the diff-optimizations-bytes branch:

Make diff3 (three-way diff) work with prefix/suffix scanning.

* subversion/libsvn_diff/diff3.c
  (svn_diff_diff3): Call datasources_open to open the three datasources
   together, and let it scan for identical prefix and suffix. Use the number
   of prefix_lines to adjust the starting offsets of the existing algorithm,
   and to insert a diff chunk of type "common" for the prefix.

Modified:
    subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c?rev=1051789&r1=1051788&r2=1051789&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_diff/diff_file.c Wed Dec 22 08:32:12 2010
@@ -252,76 +252,99 @@ datasource_open(void *baton, svn_diff_da
  * If the end of the current chunk is reached, read the next chunk in the
  * buffer and point curp to the start of the chunk.  If EOF is reached, set
  * curp equal to endp to indicate EOF. */
-static svn_error_t *
-increment_pointers(struct file_info *file[], int file_len, apr_pool_t *pool)
-{
-  int i;
-
-  for (i = 0; i < file_len; i++)
-    if (file[i]->chunk == -1) /* indicates before beginning of file */
-      {
-        file[i]->chunk = 0; /* point to beginning of file again */
-      }
-    else if (file[i]->curp == file[i]->endp - 1)
-      {
-        apr_off_t last_chunk = offset_to_chunk(file[i]->size);
-        if (file[i]->chunk == last_chunk)
-          {
-            file[i]->curp++; /* curp == endp signals end of file */
-          }
-        else
-          {
-            apr_off_t length;
-            file[i]->chunk++;
-            length = file[i]->chunk == last_chunk ? 
-              offset_in_chunk(file[i]->size) : CHUNK_SIZE;
-            SVN_ERR(read_chunk(file[i]->file, file[i]->path, file[i]->buffer,
-                               length, chunk_to_offset(file[i]->chunk),
-                               pool));
-            file[i]->endp = file[i]->buffer + length;
-            file[i]->curp = file[i]->buffer;
-          }
-      }
-    else
-      {
-        file[i]->curp++;
-      }
+#define INCREMENT_POINTERS(all_files, files_len, pool)                       \
+  do {                                                                       \
+    int i;                                                                   \
+                                                                             \
+    for (i = 0; i < files_len; i++)                                          \
+    {                                                                        \
+      if (all_files[i]->curp < all_files[i]->endp - 1)                       \
+        all_files[i]->curp++;                                                \
+      else                                                                   \
+        SVN_ERR(increment_chunk(all_files[i], pool));                        \
+    }                                                                        \
+  } while (0)
 
-  return SVN_NO_ERROR;
-}
 
 /* For all files in the FILE array, decrement the curp pointer.  If the
  * start of a chunk is reached, read the previous chunk in the buffer and
  * point curp to the last byte of the chunk.  If the beginning of a FILE is
  * reached, set chunk to -1 to indicate BOF. */
+#define DECREMENT_POINTERS(all_files, files_len, pool)                       \
+  do {                                                                       \
+    int i;                                                                   \
+                                                                             \
+    for (i = 0; i < files_len; i++)                                          \
+    {                                                                        \
+      if (all_files[i]->curp > all_files[i]->buffer)                         \
+        all_files[i]->curp--;                                                \
+      else                                                                   \
+        SVN_ERR(decrement_chunk(all_files[i], pool));                        \
+    }                                                                        \
+  } while (0)
+
+
 static svn_error_t *
-decrement_pointers(struct file_info *file[], int file_len, apr_pool_t *pool)
+increment_chunk(struct file_info *file, apr_pool_t *pool)
 {
-  int i;
+  apr_off_t length;
+  apr_off_t last_chunk = offset_to_chunk(file->size);
+
+  if (file->chunk == -1)
+    {
+      /* We are at BOF (Beginning Of File). Point to first chunk/byte again. */
+      file->chunk = 0;
+      file->curp = file->buffer;
+    }
+  else if (file->chunk == last_chunk)
+    {
+      /* We are at the last chunk. Indicate EOF by setting curp == endp. */
+      file->curp = file->endp;
+    }
+  else
+    {
+      /* There are still chunks left. Read next chunk and reset pointers. */
+      file->chunk++;
+      length = file->chunk == last_chunk ? 
+        offset_in_chunk(file->size) : CHUNK_SIZE;
+      SVN_ERR(read_chunk(file->file, file->path, file->buffer,
+                         length, chunk_to_offset(file->chunk),
+                         pool));
+      file->endp = file->buffer + length;
+      file->curp = file->buffer;
+    }
+  
+  return SVN_NO_ERROR;
+}
 
-  for (i = 0; i < file_len; i++)
-    if (file[i]->curp == file[i]->buffer)
-      {
-        if (file[i]->chunk == 0)
-          file[i]->chunk--; /* chunk == -1 signals beginning of file */
-        else
-          {
-            file[i]->chunk--;
-            SVN_ERR(read_chunk(file[i]->file, file[i]->path, file[i]->buffer,
-                               CHUNK_SIZE, chunk_to_offset(file[i]->chunk),
-                               pool));
-            file[i]->endp = file[i]->buffer + CHUNK_SIZE;
-            file[i]->curp = file[i]->endp - 1;
-          }
-      }
-    else
-      {
-        file[i]->curp--;
-      }
 
+static svn_error_t *
+decrement_chunk(struct file_info *file, apr_pool_t *pool)
+{
+  if (file->chunk == 0)
+    {
+      /* We are already at the first chunk. Indicate BOF (Beginning Of File)
+         by setting chunk = -1 and curp = endp - 1. Both conditions are
+         important. They help the increment step to catch the BOF situation
+         in an efficient way. */
+      file->chunk--; 
+      file->curp = file->endp - 1;
+    }
+  else
+    {
+      /* Read previous chunk and reset pointers. */
+      file->chunk--;
+      SVN_ERR(read_chunk(file->file, file->path, file->buffer,
+                         CHUNK_SIZE, chunk_to_offset(file->chunk),
+                         pool));
+      file->endp = file->buffer + CHUNK_SIZE;
+      file->curp = file->endp - 1;
+    }
+  
   return SVN_NO_ERROR;
 }
 
+
 /* Check whether one of the FILEs has its pointers 'before' the beginning of
  * the file (this can happen while scanning backwards). This is the case if
  * one of them has chunk == -1. */
@@ -391,7 +414,7 @@ find_identical_prefix(svn_boolean_t *rea
           had_cr = FALSE;
         }
 
-      increment_pointers(file, file_len, pool);
+      INCREMENT_POINTERS(file, file_len, pool);
 
       /* curp == endp indicates EOF (this can only happen with last chunk) */
       *reached_one_eof = is_one_at_eof(file, file_len);
@@ -421,20 +444,20 @@ find_identical_prefix(svn_boolean_t *rea
       if (ended_at_nonmatching_newline)
         {
           (*prefix_lines)--;
-          decrement_pointers(file, file_len, pool);
+          DECREMENT_POINTERS(file, file_len, pool);
         }
     }
 
   /* Back up one byte, so we point at the last identical byte */
-  decrement_pointers(file, file_len, pool);
+  DECREMENT_POINTERS(file, file_len, pool);
 
   /* Back up to the last eol sequence (\n, \r\n or \r) */
   while (!is_one_at_bof(file, file_len) && 
          *file[0]->curp != '\n' && *file[0]->curp != '\r')
-    decrement_pointers(file, file_len, pool);
+    DECREMENT_POINTERS(file, file_len, pool);
 
   /* Slide one byte forward, to point past the eol sequence */
-  increment_pointers(file, file_len, pool);
+  INCREMENT_POINTERS(file, file_len, pool);
 
   return SVN_NO_ERROR;
 }
@@ -518,7 +541,7 @@ find_identical_suffix(struct file_info *
       is_match && *file_for_suffix[0].curp == *file_for_suffix[i].curp;
   while (is_match)
     {
-      decrement_pointers(file_for_suffix_ptr, file_len, pool);
+      DECREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
       
       reached_prefix = file_for_suffix[0].chunk == suffix_min_chunk0 
                        && (file_for_suffix[0].curp - file_for_suffix[0].buffer)
@@ -533,7 +556,7 @@ find_identical_suffix(struct file_info *
     }
 
   /* Slide one byte forward, to point at the first byte of identical suffix */
-  increment_pointers(file_for_suffix_ptr, file_len, pool);
+  INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
 
   /* Slide forward until we find an eol sequence to add the rest of the line
      we're in. Then add SUFFIX_LINES_TO_KEEP more lines. Stop if at least 
@@ -543,15 +566,15 @@ find_identical_suffix(struct file_info *
       while (!is_one_at_eof(file_for_suffix_ptr, file_len)
              && *file_for_suffix[0].curp != '\n'
              && *file_for_suffix[0].curp != '\r')
-        increment_pointers(file_for_suffix_ptr, file_len, pool);
+        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
 
       /* Slide one or two more bytes, to point past the eol. */
       if (!is_one_at_eof(file_for_suffix_ptr, file_len)
           && *file_for_suffix[0].curp == '\r')
-        increment_pointers(file_for_suffix_ptr, file_len, pool);
+        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
       if (!is_one_at_eof(file_for_suffix_ptr, file_len)
           && *file_for_suffix[0].curp == '\n')
-        increment_pointers(file_for_suffix_ptr, file_len, pool);
+        INCREMENT_POINTERS(file_for_suffix_ptr, file_len, pool);
     }
   while (!is_one_at_eof(file_for_suffix_ptr, file_len) 
          && suffix_lines_to_keep--);