Fossil

Check-in [057e4b0a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Minor tweaks to the break_into_lines() algorithm. Add tests.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 057e4b0a62eff884d1b15e75d5f3b3ca7a532313
User & Date: mistachkin 2016-10-26 21:32:50
Context
2016-10-26
21:45
Create a temporary index to speed up incremental Git import. check-in: 0fa60142 user: mistachkin tags: trunk
21:32
Minor tweaks to the break_into_lines() algorithm. Add tests. check-in: 057e4b0a user: mistachkin tags: trunk
21:31
Minor security enhancements to the optional SEE integration. check-in: a8484dc3 user: mistachkin tags: trunk
2016-10-04
02:55
Coding style tweak. Closed-Leaf check-in: b47e4cc4 user: mistachkin tags: binDiffFix
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/diff.c.

   113    113     int nEditAlloc;    /* Space allocated for aEdit[] */
   114    114     DLine *aFrom;      /* File on left side of the diff */
   115    115     int nFrom;         /* Number of lines in aFrom[] */
   116    116     DLine *aTo;        /* File on right side of the diff */
   117    117     int nTo;           /* Number of lines in aTo[] */
   118    118     int (*same_fn)(const DLine*,const DLine*); /* comparison function */
   119    119   };
          120  +
          121  +/*
          122  +** Count the number of lines in the input string.  Include the last line
          123  +** in the count even if it lacks the \n terminator.  If an empty string
          124  +** is specified, the number of lines is zero.  For the purposes of this
          125  +** function, a string is considered empty if it contains no characters
          126  +** -OR- it contains only NUL characters.
          127  +*/
          128  +static int count_lines(
          129  +  const char *z,
          130  +  int n,
          131  +  int *pnLine
          132  +){
          133  +  int nLine;
          134  +  const char *zNL, *z2;
          135  +  for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
          136  +  if( z2[0]!='\0' ){
          137  +    nLine++;
          138  +    do{ z2++; }while( z2[0]!='\0' );
          139  +  }
          140  +  if( n!=(int)(z2-z) ) return 0;
          141  +  if( pnLine ) *pnLine = nLine;
          142  +  return 1;
          143  +}
   120    144   
   121    145   /*
   122    146   ** Return an array of DLine objects containing a pointer to the
   123    147   ** start of each line and a hash of that line.  The lower
   124    148   ** bits of the hash store the length of each line.
   125    149   **
   126    150   ** Trailing whitespace is removed from each line.  2010-08-20:  Not any
................................................................................
   138    162     int n,
   139    163     int *pnLine,
   140    164     u64 diffFlags
   141    165   ){
   142    166     int nLine, i, k, nn, s, x;
   143    167     unsigned int h, h2;
   144    168     DLine *a;
   145         -  const char *zNL, *z2;
          169  +  const char *zNL;
   146    170   
   147         -  /* Count the number of lines in the input file.  Include the last line
   148         -  ** in the count even if it lacks the \n terminator
   149         -  */
   150         -  for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
   151         -  if( z2[0]!=0 ){
   152         -    nLine++;
   153         -    do{ z2++; }while( z2[0] );
          171  +  if( count_lines(z, n, &nLine)==0 ){
          172  +    return 0;
   154    173     }
   155         -  if( n!=(int)(z2-z) ) return 0;
   156         -
          174  +  assert( nLine>0 || z[0]=='\0' );
   157    175     a = fossil_malloc( sizeof(a[0])*nLine );
   158    176     memset(a, 0, sizeof(a[0])*nLine);
   159    177     if( nLine==0 ){
   160    178       *pnLine = 0;
   161    179       return a;
   162    180     }
   163    181     i = 0;
   164    182     do{
   165    183       zNL = strchr(z,'\n');
   166         -    if( zNL==0 ) zNL = z+strlen(z);
          184  +    if( zNL==0 ) zNL = z+n;
   167    185       nn = (int)(zNL - z);
   168    186       if( nn>LENGTH_MASK ){
   169    187         fossil_free(a);
   170    188         return 0;
   171    189       }
   172    190       a[i].z = z;
   173    191       k = nn;
................................................................................
   179    197       if( diffFlags & DIFF_IGNORE_EOLWS ){
   180    198         while( k>0 && fossil_isspace(z[k-1]) ){ k--; }
   181    199       }
   182    200       if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
   183    201         int numws = 0;
   184    202         while( s<k && fossil_isspace(z[s]) ){ s++; }
   185    203         for(h=0, x=s; x<k; x++){
   186         -        if( fossil_isspace(z[x]) ){
          204  +        char c = z[x];
          205  +        if( fossil_isspace(c) ){
   187    206             ++numws;
   188    207           }else{
   189         -          h += z[x];
          208  +          h += c;
   190    209             h *= 0x9e3779b1;
   191    210           }
   192    211         }
   193    212         k -= numws;
   194    213       }else{
   195    214         for(h=0, x=s; x<k; x++){
   196    215           h += z[x];
................................................................................
   198    217         }
   199    218       }
   200    219       a[i].indent = s;
   201    220       a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
   202    221       h2 = h % nLine;
   203    222       a[i].iNext = a[h2].iHash;
   204    223       a[h2].iHash = i+1;
   205         -    z += nn+1;
          224  +    z += nn+1; n -= nn+1;
   206    225       i++;
   207         -  }while( zNL[0] && zNL[1] );
          226  +  }while( zNL[0]!='\0' && zNL[1]!='\0' );
   208    227     assert( i==nLine );
   209    228   
   210    229     /* Return results */
   211    230     *pnLine = nLine;
   212    231     return a;
   213    232   }
   214    233   

Added test/diff.test.

            1  +#
            2  +# Copyright (c) 2016 D. Richard Hipp
            3  +#
            4  +# This program is free software; you can redistribute it and/or
            5  +# modify it under the terms of the Simplified BSD License (also
            6  +# known as the "2-Clause License" or "FreeBSD License".)
            7  +#
            8  +# This program is distributed in the hope that it will be useful,
            9  +# but without any warranty; without even the implied warranty of
           10  +# merchantability or fitness for a particular purpose.
           11  +#
           12  +# Author contact information:
           13  +#   drh@hwaci.com
           14  +#   http://www.hwaci.com/drh/
           15  +#
           16  +############################################################################
           17  +#
           18  +# Tests for the diff command.
           19  +#
           20  +
           21  +require_no_open_checkout
           22  +
           23  +test_setup; set rootDir [file normalize [pwd]]
           24  +
           25  +###################################
           26  +# Tests of binary file detection. #
           27  +###################################
           28  +
           29  +file mkdir .fossil-settings
           30  +write_file [file join .fossil-settings binary-glob] "*"
           31  +
           32  +write_file file0.dat ""; # no content.
           33  +write_file file1.dat "test file 1 (one line no term)."
           34  +write_file file2.dat "test file 2 (NUL character).\0"
           35  +write_file file3.dat "test file 3 (long line).[string repeat x 16384]"
           36  +write_file file4.dat "test file 4 (long line).[string repeat y 16384]\ntwo"
           37  +write_file file5.dat "[string repeat z 16384]\ntest file 5 (long line)."
           38  +
           39  +fossil add $rootDir
           40  +fossil commit -m "c1"
           41  +
           42  +###############################################################################
           43  +
           44  +fossil ls
           45  +test diff-ls-1 {[normalize_result] eq \
           46  +"file0.dat\nfile1.dat\nfile2.dat\nfile3.dat\nfile4.dat\nfile5.dat"}
           47  +
           48  +###############################################################################
           49  +
           50  +write_file file0.dat "\0"
           51  +fossil diff file0.dat
           52  +
           53  +test diff-file0-1 {[normalize_result] eq {Index: file0.dat
           54  +==================================================================
           55  +--- file0.dat
           56  ++++ file0.dat
           57  +cannot compute difference between binary files}}
           58  +
           59  +###############################################################################
           60  +
           61  +write_file file1.dat [string repeat z 16384]
           62  +fossil diff file1.dat
           63  +
           64  +test diff-file1-1 {[normalize_result] eq {Index: file1.dat
           65  +==================================================================
           66  +--- file1.dat
           67  ++++ file1.dat
           68  +cannot compute difference between binary files}}
           69  +
           70  +###############################################################################
           71  +
           72  +write_file file2.dat "test file 2 (no NUL character)."
           73  +fossil diff file2.dat
           74  +
           75  +test diff-file2-1 {[normalize_result] eq {Index: file2.dat
           76  +==================================================================
           77  +--- file2.dat
           78  ++++ file2.dat
           79  +cannot compute difference between binary files}}
           80  +
           81  +###############################################################################
           82  +
           83  +write_file file3.dat "test file 3 (not a long line)."
           84  +fossil diff file3.dat
           85  +
           86  +test diff-file3-1 {[normalize_result] eq {Index: file3.dat
           87  +==================================================================
           88  +--- file3.dat
           89  ++++ file3.dat
           90  +cannot compute difference between binary files}}
           91  +
           92  +###############################################################################
           93  +
           94  +write_file file4.dat "test file 4 (not a long line).\ntwo"
           95  +fossil diff file4.dat
           96  +
           97  +test diff-file4-1 {[normalize_result] eq {Index: file4.dat
           98  +==================================================================
           99  +--- file4.dat
          100  ++++ file4.dat
          101  +cannot compute difference between binary files}}
          102  +
          103  +###############################################################################
          104  +
          105  +write_file file5.dat "[string repeat 0 16]\ntest file 5 (not a long line)."
          106  +fossil diff file5.dat
          107  +
          108  +test diff-file5-1 {[normalize_result] eq {Index: file5.dat
          109  +==================================================================
          110  +--- file5.dat
          111  ++++ file5.dat
          112  +cannot compute difference between binary files}}
          113  +
          114  +###############################################################################
          115  +
          116  +test_cleanup