2 * token.c : routines for doing diffs
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include <apr_pools.h>
22 #include <apr_general.h>
24 #include "svn_version.h"
27 #include "svn_error.h"
29 #include "svn_types.h"
35 * Prime number to use as the size of the hash table. This number was
36 * not selected by testing of any kind and may need tweaking.
38 #define SVN_DIFF__HASH_SIZE 127
40 struct svn_diff__node_t
42 svn_diff__node_t
*parent
;
43 svn_diff__node_t
*left
;
44 svn_diff__node_t
*right
;
50 struct svn_diff__tree_t
52 svn_diff__node_t
*root
[SVN_DIFF__HASH_SIZE
];
58 * Support functions to build a tree of token positions
62 svn_diff__tree_create(svn_diff__tree_t
**tree
, apr_pool_t
*pool
)
64 *tree
= apr_pcalloc(pool
, sizeof(**tree
));
70 svn_diff__tree_insert_token(svn_diff__node_t
**node
, svn_diff__tree_t
*tree
,
72 const svn_diff_fns_t
*vtable
,
73 apr_uint32_t hash
, void *token
)
75 svn_diff__node_t
*new_node
;
76 svn_diff__node_t
**node_ref
;
77 svn_diff__node_t
*parent
;
80 SVN_ERR_ASSERT(token
);
83 node_ref
= &tree
->root
[hash
% SVN_DIFF__HASH_SIZE
];
85 while (*node_ref
!= NULL
)
89 rv
= hash
- parent
->hash
;
91 SVN_ERR(vtable
->token_compare(diff_baton
, parent
->token
, token
, &rv
));
95 /* Discard the previous token. This helps in cases where
96 * only recently read tokens are still in memory.
98 if (vtable
->token_discard
!= NULL
)
99 vtable
->token_discard(diff_baton
, parent
->token
);
101 parent
->token
= token
;
108 node_ref
= &parent
->left
;
112 node_ref
= &parent
->right
;
116 /* Create a new node */
117 new_node
= apr_palloc(tree
->pool
, sizeof(*new_node
));
118 new_node
->parent
= parent
;
119 new_node
->left
= NULL
;
120 new_node
->right
= NULL
;
121 new_node
->hash
= hash
;
122 new_node
->token
= token
;
124 *node
= *node_ref
= new_node
;
131 * Get all tokens from a datasource. Return the
132 * last item in the (circular) list.
135 svn_diff__get_tokens(svn_diff__position_t
**position_list
,
136 svn_diff__tree_t
*tree
,
138 const svn_diff_fns_t
*vtable
,
139 svn_diff_datasource_e datasource
,
142 svn_diff__position_t
*start_position
;
143 svn_diff__position_t
*position
= NULL
;
144 svn_diff__position_t
**position_ref
;
145 svn_diff__node_t
*node
;
150 *position_list
= NULL
;
153 SVN_ERR(vtable
->datasource_open(diff_baton
, datasource
));
155 position_ref
= &start_position
;
157 hash
= 0; /* The callback fn doesn't need to touch it per se */
160 SVN_ERR(vtable
->datasource_get_next_token(&hash
, &token
,
161 diff_baton
, datasource
));
166 SVN_ERR(svn_diff__tree_insert_token(&node
, tree
,
170 /* Create a new position */
171 position
= apr_palloc(pool
, sizeof(*position
));
172 position
->next
= NULL
;
173 position
->node
= node
;
174 position
->offset
= offset
;
176 *position_ref
= position
;
177 position_ref
= &position
->next
;
180 *position_ref
= start_position
;
182 SVN_ERR(vtable
->datasource_close(diff_baton
, datasource
));
184 *position_list
= position
;