diff.c revision 251881
1196994Sphk/* 2196994Sphk * diff.c : routines for doing diffs 3196994Sphk * 4196994Sphk * ==================================================================== 5196994Sphk * Licensed to the Apache Software Foundation (ASF) under one 6196994Sphk * or more contributor license agreements. See the NOTICE file 7196994Sphk * distributed with this work for additional information 8196994Sphk * regarding copyright ownership. The ASF licenses this file 9196994Sphk * to you under the Apache License, Version 2.0 (the 10196994Sphk * "License"); you may not use this file except in compliance 11196994Sphk * with the License. You may obtain a copy of the License at 12196994Sphk * 13196994Sphk * http://www.apache.org/licenses/LICENSE-2.0 14196994Sphk * 15196994Sphk * Unless required by applicable law or agreed to in writing, 16196994Sphk * software distributed under the License is distributed on an 17196994Sphk * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18196994Sphk * KIND, either express or implied. See the License for the 19196994Sphk * specific language governing permissions and limitations 20196994Sphk * under the License. 21196994Sphk * ==================================================================== 22196994Sphk */ 23196994Sphk 24196994Sphk 25196994Sphk#include <apr.h> 26196994Sphk#include <apr_pools.h> 27196994Sphk#include <apr_general.h> 28196994Sphk 29196994Sphk#include "svn_pools.h" 30196994Sphk#include "svn_error.h" 31196994Sphk#include "svn_diff.h" 32196994Sphk#include "svn_types.h" 33196994Sphk 34196994Sphk#include "diff.h" 35196994Sphk 36196994Sphk 37196994Sphksvn_diff__token_index_t* 38196994Sphksvn_diff__get_token_counts(svn_diff__position_t *loop_start, 39196994Sphk svn_diff__token_index_t num_tokens, 40196994Sphk apr_pool_t *pool) 41196994Sphk{ 42196994Sphk svn_diff__token_index_t *token_counts; 43196994Sphk svn_diff__token_index_t token_index; 44196994Sphk svn_diff__position_t *current; 45196994Sphk 46196994Sphk token_counts = apr_palloc(pool, num_tokens * sizeof(*token_counts)); 47196994Sphk for (token_index = 0; token_index < num_tokens; token_index++) 48196994Sphk token_counts[token_index] = 0; 49209975Snwhitehorn 50209975Snwhitehorn current = loop_start; 51196994Sphk if (current != NULL) 52196994Sphk { 53 do 54 { 55 token_counts[current->token_index]++; 56 current = current->next; 57 } 58 while (current != loop_start); 59 } 60 61 return token_counts; 62} 63 64 65svn_diff_t * 66svn_diff__diff(svn_diff__lcs_t *lcs, 67 apr_off_t original_start, apr_off_t modified_start, 68 svn_boolean_t want_common, 69 apr_pool_t *pool) 70{ 71 svn_diff_t *diff; 72 svn_diff_t **diff_ref = &diff; 73 74 while (1) 75 { 76 if (original_start < lcs->position[0]->offset 77 || modified_start < lcs->position[1]->offset) 78 { 79 (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); 80 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; 90 91 diff_ref = &(*diff_ref)->next; 92 } 93 94 /* Detect the EOF */ 95 if (lcs->length == 0) 96 break; 97 98 original_start = lcs->position[0]->offset; 99 modified_start = lcs->position[1]->offset; 100 101 if (want_common) 102 { 103 (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); 104 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; 112 113 diff_ref = &(*diff_ref)->next; 114 } 115 116 original_start += lcs->length; 117 modified_start += lcs->length; 118 119 lcs = lcs->next; 120 } 121 122 *diff_ref = NULL; 123 124 return diff; 125} 126 127 128svn_error_t * 129svn_diff_diff_2(svn_diff_t **diff, 130 void *diff_baton, 131 const svn_diff_fns2_t *vtable, 132 apr_pool_t *pool) 133{ 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; 141 apr_pool_t *subpool; 142 apr_pool_t *treepool; 143 apr_off_t prefix_lines = 0; 144 apr_off_t suffix_lines = 0; 145 146 *diff = NULL; 147 148 subpool = svn_pool_create(pool); 149 treepool = svn_pool_create(pool); 150 151 svn_diff__tree_create(&tree, treepool); 152 153 SVN_ERR(vtable->datasources_open(diff_baton, &prefix_lines, &suffix_lines, 154 datasource, 2)); 155 156 /* Insert the data into the tree */ 157 SVN_ERR(svn_diff__get_tokens(&position_list[0], 158 tree, 159 diff_baton, vtable, 160 svn_diff_datasource_original, 161 prefix_lines, 162 subpool)); 163 164 SVN_ERR(svn_diff__get_tokens(&position_list[1], 165 tree, 166 diff_baton, vtable, 167 svn_diff_datasource_modified, 168 prefix_lines, 169 subpool)); 170 171 num_tokens = svn_diff__get_node_count(tree); 172 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. 175 */ 176 if (vtable->token_discard_all != NULL) 177 vtable->token_discard_all(diff_baton); 178 179 /* We don't need the nodes in the tree either anymore, nor the tree itself */ 180 svn_pool_destroy(treepool); 181 182 token_counts[0] = svn_diff__get_token_counts(position_list[0], num_tokens, 183 subpool); 184 token_counts[1] = svn_diff__get_token_counts(position_list[1], num_tokens, 185 subpool); 186 187 /* Get the lcs */ 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); 191 192 /* Produce the diff */ 193 *diff = svn_diff__diff(lcs, 1, 1, TRUE, pool); 194 195 /* Get rid of all the data we don't have a use for anymore */ 196 svn_pool_destroy(subpool); 197 198 return SVN_NO_ERROR; 199} 200