2 * diff.c : routines for doing diffs
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
26 #include <apr_pools.h>
27 #include <apr_general.h>
29 #include "svn_pools.h"
30 #include "svn_error.h"
32 #include "svn_types.h"
37 svn_diff__token_index_t
*
38 svn_diff__get_token_counts(svn_diff__position_t
*loop_start
,
39 svn_diff__token_index_t num_tokens
,
42 svn_diff__token_index_t
*token_counts
;
43 svn_diff__token_index_t token_index
;
44 svn_diff__position_t
*current
;
46 token_counts
= apr_palloc(pool
, num_tokens
* sizeof(*token_counts
));
47 for (token_index
= 0; token_index
< num_tokens
; token_index
++)
48 token_counts
[token_index
] = 0;
55 token_counts
[current
->token_index
]++;
56 current
= current
->next
;
58 while (current
!= loop_start
);
66 svn_diff__diff(svn_diff__lcs_t
*lcs
,
67 apr_off_t original_start
, apr_off_t modified_start
,
68 svn_boolean_t want_common
,
72 svn_diff_t
**diff_ref
= &diff
;
76 if (original_start
< lcs
->position
[0]->offset
77 || modified_start
< lcs
->position
[1]->offset
)
79 (*diff_ref
) = apr_palloc(pool
, sizeof(**diff_ref
));
81 (*diff_ref
)->type
= svn_diff__type_diff_modified
;
82 (*diff_ref
)->original_start
= original_start
- 1;
83 (*diff_ref
)->original_length
=
84 lcs
->position
[0]->offset
- original_start
;
85 (*diff_ref
)->modified_start
= modified_start
- 1;
86 (*diff_ref
)->modified_length
=
87 lcs
->position
[1]->offset
- modified_start
;
88 (*diff_ref
)->latest_start
= 0;
89 (*diff_ref
)->latest_length
= 0;
91 diff_ref
= &(*diff_ref
)->next
;
98 original_start
= lcs
->position
[0]->offset
;
99 modified_start
= lcs
->position
[1]->offset
;
103 (*diff_ref
) = apr_palloc(pool
, sizeof(**diff_ref
));
105 (*diff_ref
)->type
= svn_diff__type_common
;
106 (*diff_ref
)->original_start
= original_start
- 1;
107 (*diff_ref
)->original_length
= lcs
->length
;
108 (*diff_ref
)->modified_start
= modified_start
- 1;
109 (*diff_ref
)->modified_length
= lcs
->length
;
110 (*diff_ref
)->latest_start
= 0;
111 (*diff_ref
)->latest_length
= 0;
113 diff_ref
= &(*diff_ref
)->next
;
116 original_start
+= lcs
->length
;
117 modified_start
+= lcs
->length
;
129 svn_diff_diff_2(svn_diff_t
**diff
,
131 const svn_diff_fns2_t
*vtable
,
134 svn_diff__tree_t
*tree
;
135 svn_diff__position_t
*position_list
[2];
136 svn_diff__token_index_t num_tokens
;
137 svn_diff__token_index_t
*token_counts
[2];
138 svn_diff_datasource_e datasource
[] = {svn_diff_datasource_original
,
139 svn_diff_datasource_modified
};
140 svn_diff__lcs_t
*lcs
;
142 apr_pool_t
*treepool
;
143 apr_off_t prefix_lines
= 0;
144 apr_off_t suffix_lines
= 0;
148 subpool
= svn_pool_create(pool
);
149 treepool
= svn_pool_create(pool
);
151 svn_diff__tree_create(&tree
, treepool
);
153 SVN_ERR(vtable
->datasources_open(diff_baton
, &prefix_lines
, &suffix_lines
,
156 /* Insert the data into the tree */
157 SVN_ERR(svn_diff__get_tokens(&position_list
[0],
160 svn_diff_datasource_original
,
164 SVN_ERR(svn_diff__get_tokens(&position_list
[1],
167 svn_diff_datasource_modified
,
171 num_tokens
= svn_diff__get_node_count(tree
);
173 /* The cool part is that we don't need the tokens anymore.
174 * Allow the app to clean them up if it wants to.
176 if (vtable
->token_discard_all
!= NULL
)
177 vtable
->token_discard_all(diff_baton
);
179 /* We don't need the nodes in the tree either anymore, nor the tree itself */
180 svn_pool_destroy(treepool
);
182 token_counts
[0] = svn_diff__get_token_counts(position_list
[0], num_tokens
,
184 token_counts
[1] = svn_diff__get_token_counts(position_list
[1], num_tokens
,
188 lcs
= svn_diff__lcs(position_list
[0], position_list
[1], token_counts
[0],
189 token_counts
[1], num_tokens
, prefix_lines
,
190 suffix_lines
, subpool
);
192 /* Produce the diff */
193 *diff
= svn_diff__diff(lcs
, 1, 1, TRUE
, pool
);
195 /* Get rid of all the data we don't have a use for anymore */
196 svn_pool_destroy(subpool
);