Fossil

Check-in [8017c358]
Login

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

Overview
Comment:Another adjustment to handle some corner cases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | binDiffFix
Files: files | file ages | folders
SHA1:8017c358ba77159dcdb836c0fa305e94cf701c20
User & Date: mistachkin 2016-10-03 23:10:23
Context
2016-10-03
23:18
Further improve clarity. check-in: 11e2c6e6 user: mistachkin tags: binDiffFix
23:10
Another adjustment to handle some corner cases. check-in: 8017c358 user: mistachkin tags: binDiffFix
21:59
Initial tests for the diff-binary-detection fixes. check-in: 5db0eb52 user: mistachkin tags: binDiffFix
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/blob.c.

85
86
87
88
89
90
91
























92
93
94
95
96
97
98
#if 0  /* Enable for debugging only */
#define assert_blob_is_reset(x) assert(blob_is_reset(x))
#else
#define assert_blob_is_reset(x)
#endif



























/*
** We find that the built-in isspace() function does not work for
** some international character sets.  So here is a substitute.
*/
int fossil_isspace(char c){
  return c==' ' || (c<='\r' && c>='\t');







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#if 0  /* Enable for debugging only */
#define assert_blob_is_reset(x) assert(blob_is_reset(x))
#else
#define assert_blob_is_reset(x)
#endif


/*
** The built-in strchr() function cannot deal with NUL characters.
** So here is a substitute.  If the character being sought after
** is not NUL, this function will call the built-in strchr().  In
** that case, the "n" argument is ignored.  If the value of "n"
** is less than zero, the length of the "str" value will be used;
** however, that is unlikely to produce a useful result.
*/
char *fossil_strchr(
  const char *str, /* Null-terminated string being searched. */
  int n,           /* Length of the string being searched. */
  int c            /* Character being sought. */
){
  if( c=='\0' ){
    int i = 0;
    if( n<0 ) n = strlen(str); /* pedantic */
    for(; i<n; i++){
      if( str[i]==c ) return str+i;
    }
    return 0;
  }else{
    return strchr(str, c);
  }
}

/*
** We find that the built-in isspace() function does not work for
** some international character sets.  So here is a substitute.
*/
int fossil_isspace(char c){
  return c==' ' || (c<='\r' && c>='\t');

Changes to src/diff.c.

113
114
115
116
117
118
119
















120
121
122
123
124
125
126
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155




156
157
158
159
160
161
162
163
164
165
166
167
168
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  int nEditAlloc;    /* Space allocated for aEdit[] */
  DLine *aFrom;      /* File on left side of the diff */
  int nFrom;         /* Number of lines in aFrom[] */
  DLine *aTo;        /* File on right side of the diff */
  int nTo;           /* Number of lines in aTo[] */
  int (*same_fn)(const DLine*,const DLine*); /* comparison function */
};

















/*
** Return an array of DLine objects containing a pointer to the
** start of each line and a hash of that line.  The lower
** bits of the hash store the length of each line.
**
** Trailing whitespace is removed from each line.  2010-08-20:  Not any
................................................................................
  int n,
  int *pnLine,
  u64 diffFlags
){
  int nLine, i, k, nn, s, x;
  unsigned int h, h2;
  DLine *a;
  const char *zNL, *z2;

  /* Count the number of lines in the input file.  Include the last line
  ** in the count even if it lacks the \n terminator
  */
  for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
  if( z2[0]!=0 ) nLine++;

  a = fossil_malloc( sizeof(a[0])*nLine );
  memset(a, 0, sizeof(a[0])*nLine);
  if( nLine==0 ){




    *pnLine = 0;
    return a;
  }
  i = 0;
  do{
    zNL = strchr(z,'\n');
    if( zNL==0 ) zNL = z+n;
    nn = (int)(zNL - z);
    if( nn>LENGTH_MASK ){
      fossil_free(a);
      return 0;
    }
    a[i].z = z;
................................................................................
      }
    }
    a[i].indent = s;
    a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
    h2 = h % nLine;
    a[i].iNext = a[h2].iHash;
    a[h2].iHash = i+1;
    z += nn+1;
    i++;
  }while( zNL[0] && zNL[1] );
  assert( i==nLine );

  /* Return results */
  *pnLine = nLine;
  return a;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|

|
|
<
<
<
<



>
>
>
>





|







 







|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
154
155
156
157
158
159
160
161
162
163
164




165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  int nEditAlloc;    /* Space allocated for aEdit[] */
  DLine *aFrom;      /* File on left side of the diff */
  int nFrom;         /* Number of lines in aFrom[] */
  DLine *aTo;        /* File on right side of the diff */
  int nTo;           /* Number of lines in aTo[] */
  int (*same_fn)(const DLine*,const DLine*); /* comparison function */
};

/*
** Count the number of lines in the input string.  Include the last line
** in the count even if it lacks the \n terminator.  If an empty string
** is specified, the number of lines is zero.
*/
static int count_lines(
  const char *z,
  int n
){
  int nLine;
  const char *zNL, *z2;
  for(nLine=0, z2=z; (zNL = fossil_strchr(z2,-1,'\n'))!=0; z2=zNL+1, nLine++){}
  if( z2[0]!=0 ) nLine++;
  return nLine;
}

/*
** Return an array of DLine objects containing a pointer to the
** start of each line and a hash of that line.  The lower
** bits of the hash store the length of each line.
**
** Trailing whitespace is removed from each line.  2010-08-20:  Not any
................................................................................
  int n,
  int *pnLine,
  u64 diffFlags
){
  int nLine, i, k, nn, s, x;
  unsigned int h, h2;
  DLine *a;
  const char *zNL;

  nLine = count_lines(z, n);
  assert( nLine>0 || z[0]==0 );




  a = fossil_malloc( sizeof(a[0])*nLine );
  memset(a, 0, sizeof(a[0])*nLine);
  if( nLine==0 ){
    if( fossil_strchr(z,n,'\0')!=0 ){
      fossil_free(a);
      return 0;
    }
    *pnLine = 0;
    return a;
  }
  i = 0;
  do{
    zNL = fossil_strchr(z,n,'\n');
    if( zNL==0 ) zNL = z+n;
    nn = (int)(zNL - z);
    if( nn>LENGTH_MASK ){
      fossil_free(a);
      return 0;
    }
    a[i].z = z;
................................................................................
      }
    }
    a[i].indent = s;
    a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
    h2 = h % nLine;
    a[i].iNext = a[h2].iHash;
    a[h2].iHash = i+1;
    z += nn+1; n -= nn+1;
    i++;
  }while( zNL[0] && zNL[1] );
  assert( i==nLine );

  /* Return results */
  *pnLine = nLine;
  return a;

Changes to test/diff.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

test_setup; set rootDir [file normalize [pwd]]

###################################
# Tests of binary file detection. #
###################################

file mkdir [file join .fossil-settings]
write_file [file join .fossil-settings binary-glob] "*"

write_file file0.dat ""; # no content.
write_file file1.dat "test file 1 (one line no term)."
write_file file2.dat "test file 2 (NUL character).\0"
write_file file3.dat "test file 3 (long line).[string repeat x 16384]"
write_file file4.dat "test file 4 (long line).[string repeat y 16384]\ntwo"







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

test_setup; set rootDir [file normalize [pwd]]

###################################
# Tests of binary file detection. #
###################################

file mkdir .fossil-settings
write_file [file join .fossil-settings binary-glob] "*"

write_file file0.dat ""; # no content.
write_file file1.dat "test file 1 (one line no term)."
write_file file2.dat "test file 2 (NUL character).\0"
write_file file3.dat "test file 3 (long line).[string repeat x 16384]"
write_file file4.dat "test file 4 (long line).[string repeat y 16384]\ntwo"