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 const float max_load_factor
= 0.65;
31 unsigned int git_revpool_table__hash(const git_oid
*id
)
33 return *((unsigned int *)id
->id
);
36 git_revpool_table
*git_revpool_table_create(unsigned int min_size
)
38 git_revpool_table
*table
;
41 table
= git__malloc(sizeof(table
));
46 // round up size to closest power of 2
48 min_size
|= min_size
>> 1;
49 min_size
|= min_size
>> 2;
50 min_size
|= min_size
>> 4;
51 min_size
|= min_size
>> 8;
52 min_size
|= min_size
>> 16;
54 table
->size_mask
= min_size
;
56 table
->max_count
= (min_size
+ 1) * max_load_factor
;
58 table
->nodes
= git__malloc((min_size
+ 1) * sizeof(git_revpool_node
*));
60 if (table
->nodes
== NULL
) {
65 for (i
= 0; i
<= min_size
; ++i
)
66 table
->nodes
[i
] = NULL
;
71 int git_revpool_table_insert(git_revpool_table
*table
, git_revpool_object
*object
)
73 git_revpool_node
*node
;
74 unsigned int index
, hash
;
79 if (table
->count
+ 1 > table
->max_count
)
80 git_revpool_table_resize(table
);
82 node
= git__malloc(sizeof(git_revpool_node
));
86 hash
= git_revpool_table__hash(&object
->id
);
87 index
= (hash
& table
->size_mask
);
89 node
->object
= object
;
91 node
->next
= table
->nodes
[index
];
93 table
->nodes
[index
] = node
;
99 git_revpool_object
*git_revpool_table_lookup(git_revpool_table
*table
, const git_oid
*id
)
101 git_revpool_node
*node
;
102 unsigned int index
, hash
;
107 hash
= git_revpool_table__hash(id
);
108 index
= (hash
& table
->size_mask
);
109 node
= table
->nodes
[index
];
111 while (node
!= NULL
) {
112 if (node
->hash
== hash
&& git_oid_cmp(id
, &node
->object
->id
) == 0)
121 void git_revpool_table_resize(git_revpool_table
*table
)
123 git_revpool_node
**new_nodes
;
124 unsigned int new_size
, i
;
126 new_size
= (table
->size_mask
+ 1) * 2;
128 new_nodes
= git__malloc(new_size
* sizeof(git_revpool_node
*));
129 if (new_nodes
== NULL
)
132 memset(new_nodes
, 0x0, new_size
* sizeof(git_revpool_node
*));
134 for (i
= 0; i
<= table
->size_mask
; ++i
) {
138 while ((n
= table
->nodes
[i
]) != NULL
) {
139 table
->nodes
[i
] = n
->next
;
140 index
= n
->hash
& (new_size
- 1);
141 n
->next
= new_nodes
[index
];
142 new_nodes
[index
] = n
;
147 table
->nodes
= new_nodes
;
148 table
->size_mask
= (new_size
- 1);
149 table
->max_count
= new_size
* max_load_factor
;
153 void git_revpool_table_free(git_revpool_table
*table
)
157 for (index
= 0; index
<= table
->size_mask
; ++index
) {
158 git_revpool_node
*node
, *next_node
;
160 node
= table
->nodes
[index
];
161 while (node
!= NULL
) {
162 next_node
= node
->next
;
171 void git_revpool_tableit_init(git_revpool_table
*table
, git_revpool_tableit
*it
)
173 memset(it
, 0x0, sizeof(git_revpool_tableit
));
175 it
->nodes
= table
->nodes
;
176 it
->current_node
= NULL
;
178 it
->size
= table
->size_mask
+ 1;
181 git_revpool_object
*git_revpool_tableit_next(git_revpool_tableit
*it
)
183 git_revpool_node
*next
= NULL
;
185 while (it
->current_node
== NULL
) {
186 if (it
->current_pos
>= it
->size
)
189 it
->current_node
= it
->nodes
[it
->current_pos
++];
192 next
= it
->current_node
;
193 it
->current_node
= it
->current_node
->next
;