@@ -233,54 +233,31 @@ static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr,
233233 return b_next ;
234234}
235235
236- static int find_lcs (struct histindex * index , struct region * lcs ,
237- int line1 , int count1 , int line2 , int count2 ) {
238- int b_ptr ;
239-
240- if (scanA (index , line1 , count1 ))
241- return -1 ;
242-
243- index -> cnt = index -> max_chain_length + 1 ;
244-
245- for (b_ptr = line2 ; b_ptr <= LINE_END (2 ); )
246- b_ptr = try_lcs (index , lcs , b_ptr , line1 , count1 , line2 , count2 );
247-
248- return index -> has_common && index -> max_chain_length < index -> cnt ;
249- }
250-
251- static int fall_back_to_classic_diff (struct histindex * index ,
236+ static int fall_back_to_classic_diff (xpparam_t const * xpp , xdfenv_t * env ,
252237 int line1 , int count1 , int line2 , int count2 )
253238{
254- xpparam_t xpp ;
255- xpp .flags = index -> xpp -> flags & ~XDF_DIFF_ALGORITHM_MASK ;
239+ xpparam_t xpparam ;
240+ xpparam .flags = xpp -> flags & ~XDF_DIFF_ALGORITHM_MASK ;
256241
257- return xdl_fall_back_diff (index -> env , & xpp ,
242+ return xdl_fall_back_diff (env , & xpparam ,
258243 line1 , count1 , line2 , count2 );
259244}
260245
261- static int histogram_diff (xpparam_t const * xpp , xdfenv_t * env ,
262- int line1 , int count1 , int line2 , int count2 )
246+ static inline void free_index (struct histindex * index )
263247{
264- struct histindex index ;
265- struct region lcs ;
266- int sz ;
267- int result = -1 ;
268-
269- if (count1 <= 0 && count2 <= 0 )
270- return 0 ;
271-
272- if (LINE_END (1 ) >= MAX_PTR )
273- return -1 ;
248+ xdl_free (index -> records );
249+ xdl_free (index -> line_map );
250+ xdl_free (index -> next_ptrs );
251+ xdl_cha_free (& index -> rcha );
252+ }
274253
275- if (!count1 ) {
276- while (count2 -- )
277- env -> xdf2 .rchg [line2 ++ - 1 ] = 1 ;
278- return 0 ;
279- } else if (!count2 ) {
280- while (count1 -- )
281- env -> xdf1 .rchg [line1 ++ - 1 ] = 1 ;
282- return 0 ;
283- }
254+ static int find_lcs (xpparam_t const * xpp , xdfenv_t * env ,
255+ struct region * lcs ,
256+ int line1 , int count1 , int line2 , int count2 )
257+ {
258+ int b_ptr ;
259+ int sz , ret = -1 ;
260+ struct histindex index ;
284261
285262 memset (& index , 0 , sizeof (index ));
286263
@@ -318,9 +295,55 @@ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
318295 index .ptr_shift = line1 ;
319296 index .max_chain_length = 64 ;
320297
298+ if (scanA (& index , line1 , count1 ))
299+ goto cleanup ;
300+
301+ index .cnt = index .max_chain_length + 1 ;
302+
303+ for (b_ptr = line2 ; b_ptr <= LINE_END (2 ); )
304+ b_ptr = try_lcs (& index , lcs , b_ptr , line1 , count1 , line2 , count2 );
305+
306+ if (index .has_common && index .max_chain_length < index .cnt )
307+ ret = 1 ;
308+ else
309+ ret = 0 ;
310+
311+ cleanup :
312+ free_index (& index );
313+ return ret ;
314+ }
315+
316+ static int histogram_diff (xpparam_t const * xpp , xdfenv_t * env ,
317+ int line1 , int count1 , int line2 , int count2 )
318+ {
319+ struct region lcs ;
320+ int lcs_found ;
321+ int result ;
322+ redo :
323+ result = -1 ;
324+
325+ if (count1 <= 0 && count2 <= 0 )
326+ return 0 ;
327+
328+ if (LINE_END (1 ) >= MAX_PTR )
329+ return -1 ;
330+
331+ if (!count1 ) {
332+ while (count2 -- )
333+ env -> xdf2 .rchg [line2 ++ - 1 ] = 1 ;
334+ return 0 ;
335+ } else if (!count2 ) {
336+ while (count1 -- )
337+ env -> xdf1 .rchg [line1 ++ - 1 ] = 1 ;
338+ return 0 ;
339+ }
340+
321341 memset (& lcs , 0 , sizeof (lcs ));
322- if (find_lcs (& index , & lcs , line1 , count1 , line2 , count2 ))
323- result = fall_back_to_classic_diff (& index , line1 , count1 , line2 , count2 );
342+ lcs_found = find_lcs (xpp , env , & lcs , line1 , count1 , line2 , count2 );
343+ if (lcs_found < 0 )
344+ goto out ;
345+ else if (lcs_found )
346+ result = fall_back_to_classic_diff (xpp , env , line1 , count1 , line2 , count2 );
324347 else {
325348 if (lcs .begin1 == 0 && lcs .begin2 == 0 ) {
326349 while (count1 -- )
@@ -333,21 +356,21 @@ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
333356 line1 , lcs .begin1 - line1 ,
334357 line2 , lcs .begin2 - line2 );
335358 if (result )
336- goto cleanup ;
337- result = histogram_diff (xpp , env ,
338- lcs .end1 + 1 , LINE_END (1 ) - lcs .end1 ,
339- lcs .end2 + 1 , LINE_END (2 ) - lcs .end2 );
340- if (result )
341- goto cleanup ;
359+ goto out ;
360+ /*
361+ * result = histogram_diff(xpp, env,
362+ * lcs.end1 + 1, LINE_END(1) - lcs.end1,
363+ * lcs.end2 + 1, LINE_END(2) - lcs.end2);
364+ * but let's optimize tail recursion ourself:
365+ */
366+ count1 = LINE_END (1 ) - lcs .end1 ;
367+ line1 = lcs .end1 + 1 ;
368+ count2 = LINE_END (2 ) - lcs .end2 ;
369+ line2 = lcs .end2 + 1 ;
370+ goto redo ;
342371 }
343372 }
344-
345- cleanup :
346- xdl_free (index .records );
347- xdl_free (index .line_map );
348- xdl_free (index .next_ptrs );
349- xdl_cha_free (& index .rcha );
350-
373+ out :
351374 return result ;
352375}
353376
0 commit comments