1251881Speter/* 2251881Speter * diff.c : routines for doing diffs 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter#include <apr.h> 26251881Speter#include <apr_pools.h> 27251881Speter#include <apr_general.h> 28251881Speter 29251881Speter#include "svn_pools.h" 30251881Speter#include "svn_error.h" 31251881Speter#include "svn_diff.h" 32251881Speter#include "svn_types.h" 33251881Speter 34251881Speter#include "diff.h" 35251881Speter 36251881Speter 37251881Spetersvn_diff__token_index_t* 38251881Spetersvn_diff__get_token_counts(svn_diff__position_t *loop_start, 39251881Speter svn_diff__token_index_t num_tokens, 40251881Speter apr_pool_t *pool) 41251881Speter{ 42251881Speter svn_diff__token_index_t *token_counts; 43251881Speter svn_diff__token_index_t token_index; 44251881Speter svn_diff__position_t *current; 45251881Speter 46251881Speter token_counts = apr_palloc(pool, num_tokens * sizeof(*token_counts)); 47251881Speter for (token_index = 0; token_index < num_tokens; token_index++) 48251881Speter token_counts[token_index] = 0; 49251881Speter 50251881Speter current = loop_start; 51251881Speter if (current != NULL) 52251881Speter { 53251881Speter do 54251881Speter { 55251881Speter token_counts[current->token_index]++; 56251881Speter current = current->next; 57251881Speter } 58251881Speter while (current != loop_start); 59251881Speter } 60251881Speter 61251881Speter return token_counts; 62251881Speter} 63251881Speter 64251881Speter 65251881Spetersvn_diff_t * 66251881Spetersvn_diff__diff(svn_diff__lcs_t *lcs, 67251881Speter apr_off_t original_start, apr_off_t modified_start, 68251881Speter svn_boolean_t want_common, 69251881Speter apr_pool_t *pool) 70251881Speter{ 71251881Speter svn_diff_t *diff; 72251881Speter svn_diff_t **diff_ref = &diff; 73251881Speter 74251881Speter while (1) 75251881Speter { 76251881Speter if (original_start < lcs->position[0]->offset 77251881Speter || modified_start < lcs->position[1]->offset) 78251881Speter { 79251881Speter (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); 80251881Speter 81251881Speter (*diff_ref)->type = svn_diff__type_diff_modified; 82251881Speter (*diff_ref)->original_start = original_start - 1; 83251881Speter (*diff_ref)->original_length = 84251881Speter lcs->position[0]->offset - original_start; 85251881Speter (*diff_ref)->modified_start = modified_start - 1; 86251881Speter (*diff_ref)->modified_length = 87251881Speter lcs->position[1]->offset - modified_start; 88251881Speter (*diff_ref)->latest_start = 0; 89251881Speter (*diff_ref)->latest_length = 0; 90251881Speter 91251881Speter diff_ref = &(*diff_ref)->next; 92251881Speter } 93251881Speter 94251881Speter /* Detect the EOF */ 95251881Speter if (lcs->length == 0) 96251881Speter break; 97251881Speter 98251881Speter original_start = lcs->position[0]->offset; 99251881Speter modified_start = lcs->position[1]->offset; 100251881Speter 101251881Speter if (want_common) 102251881Speter { 103251881Speter (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); 104251881Speter 105251881Speter (*diff_ref)->type = svn_diff__type_common; 106251881Speter (*diff_ref)->original_start = original_start - 1; 107251881Speter (*diff_ref)->original_length = lcs->length; 108251881Speter (*diff_ref)->modified_start = modified_start - 1; 109251881Speter (*diff_ref)->modified_length = lcs->length; 110251881Speter (*diff_ref)->latest_start = 0; 111251881Speter (*diff_ref)->latest_length = 0; 112251881Speter 113251881Speter diff_ref = &(*diff_ref)->next; 114251881Speter } 115251881Speter 116251881Speter original_start += lcs->length; 117251881Speter modified_start += lcs->length; 118251881Speter 119251881Speter lcs = lcs->next; 120251881Speter } 121251881Speter 122251881Speter *diff_ref = NULL; 123251881Speter 124251881Speter return diff; 125251881Speter} 126251881Speter 127251881Speter 128251881Spetersvn_error_t * 129251881Spetersvn_diff_diff_2(svn_diff_t **diff, 130251881Speter void *diff_baton, 131251881Speter const svn_diff_fns2_t *vtable, 132251881Speter apr_pool_t *pool) 133251881Speter{ 134251881Speter svn_diff__tree_t *tree; 135251881Speter svn_diff__position_t *position_list[2]; 136251881Speter svn_diff__token_index_t num_tokens; 137251881Speter svn_diff__token_index_t *token_counts[2]; 138251881Speter svn_diff_datasource_e datasource[] = {svn_diff_datasource_original, 139251881Speter svn_diff_datasource_modified}; 140251881Speter svn_diff__lcs_t *lcs; 141251881Speter apr_pool_t *subpool; 142251881Speter apr_pool_t *treepool; 143251881Speter apr_off_t prefix_lines = 0; 144251881Speter apr_off_t suffix_lines = 0; 145251881Speter 146251881Speter *diff = NULL; 147251881Speter 148251881Speter subpool = svn_pool_create(pool); 149251881Speter treepool = svn_pool_create(pool); 150251881Speter 151251881Speter svn_diff__tree_create(&tree, treepool); 152251881Speter 153251881Speter SVN_ERR(vtable->datasources_open(diff_baton, &prefix_lines, &suffix_lines, 154251881Speter datasource, 2)); 155251881Speter 156251881Speter /* Insert the data into the tree */ 157251881Speter SVN_ERR(svn_diff__get_tokens(&position_list[0], 158251881Speter tree, 159251881Speter diff_baton, vtable, 160251881Speter svn_diff_datasource_original, 161251881Speter prefix_lines, 162251881Speter subpool)); 163251881Speter 164251881Speter SVN_ERR(svn_diff__get_tokens(&position_list[1], 165251881Speter tree, 166251881Speter diff_baton, vtable, 167251881Speter svn_diff_datasource_modified, 168251881Speter prefix_lines, 169251881Speter subpool)); 170251881Speter 171251881Speter num_tokens = svn_diff__get_node_count(tree); 172251881Speter 173251881Speter /* The cool part is that we don't need the tokens anymore. 174251881Speter * Allow the app to clean them up if it wants to. 175251881Speter */ 176251881Speter if (vtable->token_discard_all != NULL) 177251881Speter vtable->token_discard_all(diff_baton); 178251881Speter 179251881Speter /* We don't need the nodes in the tree either anymore, nor the tree itself */ 180251881Speter svn_pool_destroy(treepool); 181251881Speter 182251881Speter token_counts[0] = svn_diff__get_token_counts(position_list[0], num_tokens, 183251881Speter subpool); 184251881Speter token_counts[1] = svn_diff__get_token_counts(position_list[1], num_tokens, 185251881Speter subpool); 186251881Speter 187251881Speter /* Get the lcs */ 188251881Speter lcs = svn_diff__lcs(position_list[0], position_list[1], token_counts[0], 189251881Speter token_counts[1], num_tokens, prefix_lines, 190251881Speter suffix_lines, subpool); 191251881Speter 192251881Speter /* Produce the diff */ 193251881Speter *diff = svn_diff__diff(lcs, 1, 1, TRUE, pool); 194251881Speter 195251881Speter /* Get rid of all the data we don't have a use for anymore */ 196251881Speter svn_pool_destroy(subpool); 197251881Speter 198251881Speter return SVN_NO_ERROR; 199251881Speter} 200