/src/ndpi/src/lib/ndpi_bitmap64.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * ndpi_bitmap64.c |
3 | | * |
4 | | * Copyright (C) 2011-23 - ntop.org and contributors |
5 | | * |
6 | | * nDPI is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * nDPI is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with nDPI. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | */ |
20 | | |
21 | | |
22 | | #include <stdlib.h> |
23 | | #include <errno.h> |
24 | | #include <math.h> |
25 | | #include <sys/types.h> |
26 | | |
27 | | #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_UNKNOWN |
28 | | |
29 | | #include "ndpi_config.h" |
30 | | #include "ndpi_api.h" |
31 | | #include "third_party/include/binaryfusefilter.h" |
32 | | |
33 | 48.2k | #define NDPI_BITMAP64_REALLOC_SIZE 4096 |
34 | | |
35 | | // #define PRINT_DUPLICATED_HASHS |
36 | | |
37 | | typedef struct { |
38 | | u_int32_t num_allocated_entries, num_used_entries; |
39 | | u_int64_t *entries; |
40 | | bool is_compressed; |
41 | | binary_fuse16_t bitmap; |
42 | | } ndpi_bitmap64_t; |
43 | | |
44 | | /* ********************************************************** */ |
45 | | |
46 | 51.3k | ndpi_bitmap64* ndpi_bitmap64_alloc() { |
47 | 51.3k | ndpi_bitmap64_t *rc = (ndpi_bitmap64_t*)ndpi_malloc(sizeof(ndpi_bitmap64_t)); |
48 | | |
49 | 51.3k | if(!rc) return(rc); |
50 | | |
51 | 48.2k | rc->num_allocated_entries = NDPI_BITMAP64_REALLOC_SIZE, rc->num_used_entries = 0; |
52 | 48.2k | if((rc->entries = (u_int64_t*)ndpi_calloc(rc->num_allocated_entries, sizeof(u_int64_t))) == NULL) { |
53 | 3.02k | ndpi_free(rc); |
54 | 3.02k | return(NULL); |
55 | 3.02k | } |
56 | | |
57 | 45.2k | rc->is_compressed = false; |
58 | | |
59 | 45.2k | return((ndpi_bitmap64*)rc); |
60 | 48.2k | } |
61 | | |
62 | | /* ********************************************************** */ |
63 | | |
64 | 363k | static int ndpi_bitmap64_entry_compare(const void *_a, const void *_b) { |
65 | 363k | u_int64_t *a = (u_int64_t*)_a, *b = (u_int64_t*)_b; |
66 | | |
67 | 363k | if(*a < *b) return -1; |
68 | 168k | else if(*a > *b) return 1; |
69 | 0 | else return 0; |
70 | 363k | } |
71 | | |
72 | | /* ********************************************************** */ |
73 | | |
74 | | /* Sort and compact memory before searching */ |
75 | 44.1k | bool ndpi_bitmap64_compress(ndpi_bitmap64 *_b) { |
76 | 44.1k | ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b; |
77 | 44.1k | u_int32_t i; |
78 | | |
79 | 44.1k | if(!b) |
80 | 0 | return(false); |
81 | | |
82 | 44.1k | if(b->is_compressed) |
83 | 0 | return(true); |
84 | | |
85 | 44.1k | if(b->num_used_entries > 0) { |
86 | 44.1k | if(b->num_used_entries > 1) |
87 | 23.4k | qsort(b->entries, b->num_used_entries, |
88 | 23.4k | sizeof(u_int64_t), |
89 | 23.4k | ndpi_bitmap64_entry_compare); |
90 | | |
91 | | /* Now remove duplicates */ |
92 | 44.1k | u_int64_t old_value = b->entries[0], new_len = 1; |
93 | | |
94 | 197k | for(i=1; i<b->num_used_entries; i++) { |
95 | 153k | if(b->entries[i] != old_value) { |
96 | 153k | if(new_len != i) |
97 | 0 | memcpy(&b->entries[new_len], &b->entries[i], sizeof(u_int64_t)); |
98 | | |
99 | 153k | old_value = b->entries[i]; |
100 | 153k | new_len++; |
101 | 153k | } else { |
102 | | #ifdef PRINT_DUPLICATED_HASHS |
103 | | printf("Skipping duplicate hash %lluu [id: %u/%u]\n", |
104 | | b->entries[i].value, i, b->num_used_entries); |
105 | | #endif |
106 | 0 | } |
107 | 153k | } |
108 | | |
109 | 44.1k | b->num_used_entries = b->num_allocated_entries = new_len; |
110 | 44.1k | } |
111 | | |
112 | 44.1k | if(binary_fuse16_allocate(b->num_used_entries, &b->bitmap)) { |
113 | 41.4k | if(binary_fuse16_populate(b->entries, b->num_used_entries, &b->bitmap)) { |
114 | 28.3k | ndpi_free(b->entries), b->num_used_entries = b->num_allocated_entries = 0; |
115 | 28.3k | b->entries = NULL; |
116 | 28.3k | } else { |
117 | 13.1k | binary_fuse16_free(&b->bitmap); |
118 | 13.1k | return(false); |
119 | 13.1k | } |
120 | 41.4k | } else { |
121 | 2.63k | return(false); |
122 | 2.63k | } |
123 | | |
124 | 28.3k | b->is_compressed = true; |
125 | | |
126 | 28.3k | return(true); |
127 | 44.1k | } |
128 | | |
129 | | /* ********************************************************** */ |
130 | | |
131 | 201k | bool ndpi_bitmap64_set(ndpi_bitmap64 *_b, u_int64_t value) { |
132 | 201k | ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b; |
133 | | |
134 | 201k | if(!b) |
135 | 6.11k | return(false); |
136 | | |
137 | 195k | if(b->is_compressed) { |
138 | | /* |
139 | | We need to discard the filter and start over as this |
140 | | datastructure is immutable |
141 | | */ |
142 | |
|
143 | 0 | binary_fuse16_free(&b->bitmap); |
144 | | /* No need to call b->is_compressed = false; as it will be set below */ |
145 | 0 | } |
146 | | |
147 | 195k | if(b->num_used_entries >= b->num_allocated_entries) { |
148 | 0 | u_int64_t *rc; |
149 | 0 | u_int32_t new_len = b->num_allocated_entries + NDPI_BITMAP64_REALLOC_SIZE; |
150 | |
|
151 | 0 | rc = (u_int64_t*)ndpi_realloc(b->entries, |
152 | 0 | sizeof(u_int64_t)*b->num_allocated_entries, |
153 | 0 | sizeof(u_int64_t)*new_len); |
154 | 0 | if(rc == NULL) { |
155 | 0 | b->is_compressed = false; |
156 | 0 | return(false); |
157 | 0 | } |
158 | | |
159 | 0 | b->entries = rc, b->num_allocated_entries = new_len; |
160 | 0 | } |
161 | | |
162 | 195k | b->entries[b->num_used_entries] = value; |
163 | 195k | b->num_used_entries++, b->is_compressed = false; |
164 | | |
165 | 195k | return(true); |
166 | 195k | } |
167 | | |
168 | | /* ********************************************************** */ |
169 | | |
170 | 8.76k | bool ndpi_bitmap64_isset(ndpi_bitmap64 *_b, u_int64_t value) { |
171 | 8.76k | ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b; |
172 | | |
173 | 8.76k | if(!b) |
174 | 0 | return(false); |
175 | | |
176 | 8.76k | if(!b->is_compressed) ndpi_bitmap64_compress(b); |
177 | 8.76k | if(!b->is_compressed) |
178 | 327 | return(false); |
179 | | |
180 | 8.43k | return(binary_fuse16_contain(value, &b->bitmap)); |
181 | 8.76k | } |
182 | | |
183 | | /* ********************************************************** */ |
184 | | |
185 | 45.2k | void ndpi_bitmap64_free(ndpi_bitmap64 *_b) { |
186 | 45.2k | ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b; |
187 | | |
188 | 45.2k | if(!b) |
189 | 0 | return; |
190 | | |
191 | 45.2k | if(b->entries) ndpi_free(b->entries); |
192 | | |
193 | 45.2k | if(b->is_compressed) |
194 | 28.3k | binary_fuse16_free(&b->bitmap); |
195 | | |
196 | 45.2k | ndpi_free(b); |
197 | 45.2k | } |
198 | | |
199 | | /* ********************************************************** */ |
200 | | |
201 | 0 | u_int32_t ndpi_bitmap64_size(ndpi_bitmap64 *_b) { |
202 | 0 | ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b; |
203 | |
|
204 | 0 | if(!b) |
205 | 0 | return(0); |
206 | | |
207 | 0 | return(sizeof(ndpi_bitmap64) + binary_fuse16_size_in_bytes(&b->bitmap)); |
208 | 0 | } |