2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
27 #include "revobject.h"
29 static const double max_load_factor
= 0.65;
31 static unsigned int git_revpool_table__hash(const git_oid
*id
)
34 memcpy(&r
, id
->id
, sizeof(r
));
38 git_revpool_table
*git_revpool_table_create(unsigned int min_size
)
40 git_revpool_table
*table
;
43 table
= git__malloc(sizeof(*table
));
48 /* round up size to closest power of 2 */
50 min_size
|= min_size
>> 1;
51 min_size
|= min_size
>> 2;
52 min_size
|= min_size
>> 4;
53 min_size
|= min_size
>> 8;
54 min_size
|= min_size
>> 16;
56 table
->size_mask
= min_size
;
58 table
->max_count
= (unsigned int)((min_size
+ 1) * max_load_factor
);
60 table
->nodes
= git__malloc((min_size
+ 1) * sizeof(git_revpool_node
*));
62 if (table
->nodes
== NULL
) {
67 for (i
= 0; i
<= min_size
; ++i
)
68 table
->nodes
[i
] = NULL
;
73 int git_revpool_table_insert(git_revpool_table
*table
, git_revpool_object
*object
)
75 git_revpool_node
*node
;
76 unsigned int index
, hash
;
81 if (table
->count
+ 1 > table
->max_count
)
82 git_revpool_table_resize(table
);
84 node
= git__malloc(sizeof(git_revpool_node
));
88 hash
= git_revpool_table__hash(&object
->id
);
89 index
= (hash
& table
->size_mask
);
91 node
->object
= object
;
93 node
->next
= table
->nodes
[index
];
95 table
->nodes
[index
] = node
;
101 git_revpool_object
*git_revpool_table_lookup(git_revpool_table
*table
, const git_oid
*id
)
103 git_revpool_node
*node
;
104 unsigned int index
, hash
;
109 hash
= git_revpool_table__hash(id
);
110 index
= (hash
& table
->size_mask
);
111 node
= table
->nodes
[index
];
113 while (node
!= NULL
) {
114 if (node
->hash
== hash
&& git_oid_cmp(id
, &node
->object
->id
) == 0)
123 void git_revpool_table_resize(git_revpool_table
*table
)
125 git_revpool_node
**new_nodes
;
126 unsigned int new_size
, i
;
128 new_size
= (table
->size_mask
+ 1) * 2;
130 new_nodes
= git__malloc(new_size
* sizeof(git_revpool_node
*));
131 if (new_nodes
== NULL
)
134 memset(new_nodes
, 0x0, new_size
* sizeof(git_revpool_node
*));
136 for (i
= 0; i
<= table
->size_mask
; ++i
) {
140 while ((n
= table
->nodes
[i
]) != NULL
) {
141 table
->nodes
[i
] = n
->next
;
142 index
= n
->hash
& (new_size
- 1);
143 n
->next
= new_nodes
[index
];
144 new_nodes
[index
] = n
;
149 table
->nodes
= new_nodes
;
150 table
->size_mask
= (new_size
- 1);
151 table
->max_count
= (unsigned int)(new_size
* max_load_factor
);
155 void git_revpool_table_free(git_revpool_table
*table
)
159 for (index
= 0; index
<= table
->size_mask
; ++index
) {
160 git_revpool_node
*node
, *next_node
;
162 node
= table
->nodes
[index
];
163 while (node
!= NULL
) {
164 next_node
= node
->next
;
174 void git_revpool_tableit_init(git_revpool_table
*table
, git_revpool_tableit
*it
)
176 memset(it
, 0x0, sizeof(git_revpool_tableit
));
178 it
->nodes
= table
->nodes
;
179 it
->current_node
= NULL
;
181 it
->size
= table
->size_mask
+ 1;
184 git_revpool_object
*git_revpool_tableit_next(git_revpool_tableit
*it
)
186 git_revpool_node
*next
= NULL
;
188 while (it
->current_node
== NULL
) {
189 if (it
->current_pos
>= it
->size
)
192 it
->current_node
= it
->nodes
[it
->current_pos
++];
195 next
= it
->current_node
;
196 it
->current_node
= it
->current_node
->next
;