Fossil SCM

Minor tweaks to the break_into_lines() algorithm. Add tests.

mistachkin 2016-10-26 21:32 trunk merge
Commit 057e4b0a62eff884d1b15e75d5f3b3ca7a532313
2 files changed +36 -17 +31
+36 -17
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115115
int nFrom; /* Number of lines in aFrom[] */
116116
DLine *aTo; /* File on right side of the diff */
117117
int nTo; /* Number of lines in aTo[] */
118118
int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119119
};
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
+}
120144
121145
/*
122146
** Return an array of DLine objects containing a pointer to the
123147
** start of each line and a hash of that line. The lower
124148
** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
140164
u64 diffFlags
141165
){
142166
int nLine, i, k, nn, s, x;
143167
unsigned int h, h2;
144168
DLine *a;
145
- const char *zNL, *z2;
146
-
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] );
154
- }
155
- if( n!=(int)(z2-z) ) return 0;
156
-
169
+ const char *zNL;
170
+
171
+ if( count_lines(z, n, &nLine)==0 ){
172
+ return 0;
173
+ }
174
+ assert( nLine>0 || z[0]=='\0' );
157175
a = fossil_malloc( sizeof(a[0])*nLine );
158176
memset(a, 0, sizeof(a[0])*nLine);
159177
if( nLine==0 ){
160178
*pnLine = 0;
161179
return a;
162180
}
163181
i = 0;
164182
do{
165183
zNL = strchr(z,'\n');
166
- if( zNL==0 ) zNL = z+strlen(z);
184
+ if( zNL==0 ) zNL = z+n;
167185
nn = (int)(zNL - z);
168186
if( nn>LENGTH_MASK ){
169187
fossil_free(a);
170188
return 0;
171189
}
@@ -181,14 +199,15 @@
181199
}
182200
if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
183201
int numws = 0;
184202
while( s<k && fossil_isspace(z[s]) ){ s++; }
185203
for(h=0, x=s; x<k; x++){
186
- if( fossil_isspace(z[x]) ){
204
+ char c = z[x];
205
+ if( fossil_isspace(c) ){
187206
++numws;
188207
}else{
189
- h += z[x];
208
+ h += c;
190209
h *= 0x9e3779b1;
191210
}
192211
}
193212
k -= numws;
194213
}else{
@@ -200,13 +219,13 @@
200219
a[i].indent = s;
201220
a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
202221
h2 = h % nLine;
203222
a[i].iNext = a[h2].iHash;
204223
a[h2].iHash = i+1;
205
- z += nn+1;
224
+ z += nn+1; n -= nn+1;
206225
i++;
207
- }while( zNL[0] && zNL[1] );
226
+ }while( zNL[0]!='\0' && zNL[1]!='\0' );
208227
assert( i==nLine );
209228
210229
/* Return results */
211230
*pnLine = nLine;
212231
return a;
213232
214233
ADDED test/diff.test
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115 int nFrom; /* Number of lines in aFrom[] */
116 DLine *aTo; /* File on right side of the diff */
117 int nTo; /* Number of lines in aTo[] */
118 int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
121 /*
122 ** Return an array of DLine objects containing a pointer to the
123 ** start of each line and a hash of that line. The lower
124 ** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
140 u64 diffFlags
141 ){
142 int nLine, i, k, nn, s, x;
143 unsigned int h, h2;
144 DLine *a;
145 const char *zNL, *z2;
146
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] );
154 }
155 if( n!=(int)(z2-z) ) return 0;
156
157 a = fossil_malloc( sizeof(a[0])*nLine );
158 memset(a, 0, sizeof(a[0])*nLine);
159 if( nLine==0 ){
160 *pnLine = 0;
161 return a;
162 }
163 i = 0;
164 do{
165 zNL = strchr(z,'\n');
166 if( zNL==0 ) zNL = z+strlen(z);
167 nn = (int)(zNL - z);
168 if( nn>LENGTH_MASK ){
169 fossil_free(a);
170 return 0;
171 }
@@ -181,14 +199,15 @@
181 }
182 if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
183 int numws = 0;
184 while( s<k && fossil_isspace(z[s]) ){ s++; }
185 for(h=0, x=s; x<k; x++){
186 if( fossil_isspace(z[x]) ){
 
187 ++numws;
188 }else{
189 h += z[x];
190 h *= 0x9e3779b1;
191 }
192 }
193 k -= numws;
194 }else{
@@ -200,13 +219,13 @@
200 a[i].indent = s;
201 a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
202 h2 = h % nLine;
203 a[i].iNext = a[h2].iHash;
204 a[h2].iHash = i+1;
205 z += nn+1;
206 i++;
207 }while( zNL[0] && zNL[1] );
208 assert( i==nLine );
209
210 /* Return results */
211 *pnLine = nLine;
212 return a;
213
214 DDED test/diff.test
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115 int nFrom; /* Number of lines in aFrom[] */
116 DLine *aTo; /* File on right side of the diff */
117 int nTo; /* Number of lines in aTo[] */
118 int (*same_fn)(const DLine*,const DLine*); /* comparison function */
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 }
144
145 /*
146 ** Return an array of DLine objects containing a pointer to the
147 ** start of each line and a hash of that line. The lower
148 ** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
164 u64 diffFlags
165 ){
166 int nLine, i, k, nn, s, x;
167 unsigned int h, h2;
168 DLine *a;
169 const char *zNL;
170
171 if( count_lines(z, n, &nLine)==0 ){
172 return 0;
173 }
174 assert( nLine>0 || z[0]=='\0' );
 
 
 
 
 
 
175 a = fossil_malloc( sizeof(a[0])*nLine );
176 memset(a, 0, sizeof(a[0])*nLine);
177 if( nLine==0 ){
178 *pnLine = 0;
179 return a;
180 }
181 i = 0;
182 do{
183 zNL = strchr(z,'\n');
184 if( zNL==0 ) zNL = z+n;
185 nn = (int)(zNL - z);
186 if( nn>LENGTH_MASK ){
187 fossil_free(a);
188 return 0;
189 }
@@ -181,14 +199,15 @@
199 }
200 if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
201 int numws = 0;
202 while( s<k && fossil_isspace(z[s]) ){ s++; }
203 for(h=0, x=s; x<k; x++){
204 char c = z[x];
205 if( fossil_isspace(c) ){
206 ++numws;
207 }else{
208 h += c;
209 h *= 0x9e3779b1;
210 }
211 }
212 k -= numws;
213 }else{
@@ -200,13 +219,13 @@
219 a[i].indent = s;
220 a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
221 h2 = h % nLine;
222 a[i].iNext = a[h2].iHash;
223 a[h2].iHash = i+1;
224 z += nn+1; n -= nn+1;
225 i++;
226 }while( zNL[0]!='\0' && zNL[1]!='\0' );
227 assert( i==nLine );
228
229 /* Return results */
230 *pnLine = nLine;
231 return a;
232
233 DDED test/diff.test
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
1
+16384]"
2
+write_file file4_file file4.dat "test file 4 (l16384]\ntwo"
3
+write_file f163842016 D. Richard Hipp
4
+#
5
+# This program is free software; you can redistribute it and/or
6
+# modify it under the terms of the Simplified BSD License (also
7
+# known as the "2-Clause License" or "FreeBSD License".)
8
+#
9
+# This program is distributed in the hope that it will be useful,
10
+# but without any warranty; without even the implied warranty of
11
+# merchantability or fitness for a particular purpose.
12
+#
13
+# Author contact information:
14
+# [email protected]
15
+# http://www.hwaci.com/drh/
16
+#
17
+############################################################################
18
+#
19
+# Tests for the diff command.
20
+#
21
+
22
+require_no_open_checkout
23
+
24
+test_setup; set rootDir [file normalize [pwd]]
25
+
26
+###################################
27
+# Tests of binary file det#
28
+# Coite_file file1.dat z 32768]
29
+fossil diff file1.dat
30
+
31
+test diff-file1-1 {[normalize_restest_cleanup
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
1 16384]"
2 write_file file4_file file4.dat "test file 4 (l16384]\ntwo"
3 write_file f163842016 D. Richard Hipp
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the Simplified BSD License (also
7 # known as the "2-Clause License" or "FreeBSD License".)
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but without any warranty; without even the implied warranty of
11 # merchantability or fitness for a particular purpose.
12 #
13 # Author contact information:
14 # [email protected]
15 # http://www.hwaci.com/drh/
16 #
17 ############################################################################
18 #
19 # Tests for the diff command.
20 #
21
22 require_no_open_checkout
23
24 test_setup; set rootDir [file normalize [pwd]]
25
26 ###################################
27 # Tests of binary file det#
28 # Coite_file file1.dat z 32768]
29 fossil diff file1.dat
30
31 test diff-file1-1 {[normalize_restest_cleanup

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button