bitmapper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/bitmapper/bit_bucket.c +143 -0
- data/ext/bitmapper/bit_bucket.h +37 -0
- data/ext/bitmapper/bit_mapper_wrap.c +349 -0
- data/ext/bitmapper/bit_mapper_wrap.h +39 -0
- data/ext/bitmapper/bitmapper.c +198 -0
- data/ext/bitmapper/extconf.rb +11 -0
- data/lib/bitmapper.rb +5 -0
- metadata +52 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
|
5
|
+
#include "bit_bucket.h"
|
6
|
+
|
7
|
+
void _bit_bucket_set_bit_to(BitBucket* ptr,unsigned long long int byte_part, int bit_part, unsigned val){
|
8
|
+
val = (val == 0) ? 0 : 1;
|
9
|
+
switch(bit_part){
|
10
|
+
case 0: ptr->bucket[byte_part].f0 = val;break;
|
11
|
+
case 1: ptr->bucket[byte_part].f1 = val;break;
|
12
|
+
case 2: ptr->bucket[byte_part].f2 = val;break;
|
13
|
+
case 3: ptr->bucket[byte_part].f3 = val;break;
|
14
|
+
case 4: ptr->bucket[byte_part].f4 = val;break;
|
15
|
+
case 5: ptr->bucket[byte_part].f5 = val;break;
|
16
|
+
case 6: ptr->bucket[byte_part].f6 = val;break;
|
17
|
+
case 7: ptr->bucket[byte_part].f7 = val;break;
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
/*
|
22
|
+
sets the of given bit location to 1
|
23
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
24
|
+
responsablity to ensure pointer is valid
|
25
|
+
@param num the bit location
|
26
|
+
*/
|
27
|
+
int bit_bucket_set_bit(BitBucket* ptr,unsigned long long int num){
|
28
|
+
unsigned long long int byte_part=num/8, bit_part=num%8;
|
29
|
+
if(num > ptr->size) return 1;
|
30
|
+
_bit_bucket_set_bit_to(ptr, byte_part, bit_part, 1);
|
31
|
+
return 0;
|
32
|
+
}
|
33
|
+
|
34
|
+
/*
|
35
|
+
clears the state of given bit location to 0
|
36
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
37
|
+
responsablity to ensure pointer is valid
|
38
|
+
@param num the bit location
|
39
|
+
*/
|
40
|
+
int bit_bucket_clear_bit(BitBucket* ptr,unsigned long long int num){
|
41
|
+
unsigned long long int byte_part=num/8, bit_part=num%8;
|
42
|
+
if(num > ptr->size) return 1;
|
43
|
+
_bit_bucket_set_bit_to(ptr, byte_part, bit_part, 0);
|
44
|
+
return 0;
|
45
|
+
}
|
46
|
+
|
47
|
+
/*
|
48
|
+
returns the current state of given bit location
|
49
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
50
|
+
responsablity to ensure pointer is valid
|
51
|
+
@param num the bit location
|
52
|
+
*/
|
53
|
+
int bit_bucket_get_bit(BitBucket* ptr,unsigned long long int num){
|
54
|
+
unsigned long long int byte_part=num/8, bit_part=num%8;
|
55
|
+
if(num > ptr->size) return 2;
|
56
|
+
switch(bit_part){
|
57
|
+
case 0: return ptr->bucket[byte_part].f0;
|
58
|
+
case 1: return ptr->bucket[byte_part].f1;
|
59
|
+
case 2: return ptr->bucket[byte_part].f2;
|
60
|
+
case 3: return ptr->bucket[byte_part].f3;
|
61
|
+
case 4: return ptr->bucket[byte_part].f4;
|
62
|
+
case 5: return ptr->bucket[byte_part].f5;
|
63
|
+
case 6: return ptr->bucket[byte_part].f6;
|
64
|
+
case 7: return ptr->bucket[byte_part].f7;
|
65
|
+
};
|
66
|
+
}
|
67
|
+
|
68
|
+
/*
|
69
|
+
Resets the given BitBucket*
|
70
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
71
|
+
responsablity to ensure pointer is valid
|
72
|
+
*/
|
73
|
+
void bit_bucket_reset(BitBucket *ptr){
|
74
|
+
unsigned long long int count = ptr->size/8+1, i;
|
75
|
+
for(i=0;i<count;i++){
|
76
|
+
ptr->bucket[i] = (ByteBits){0,0,0,0,0,0,0,0};
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
/*
|
81
|
+
Creates BitBucket with the given size and allocates the requried
|
82
|
+
memory. A reset on all bits is done after creating the memory.
|
83
|
+
@param long long size Number of bits you want to allocate.
|
84
|
+
*/
|
85
|
+
BitBucket* bit_bucket_create(unsigned long long int size){
|
86
|
+
unsigned long long int count = size/8 + 1;
|
87
|
+
BitBucket *ptr = (BitBucket*)malloc(sizeof(BitBucket));
|
88
|
+
ptr->size = size;
|
89
|
+
ptr->bucket = (ByteBits*)malloc(count*sizeof(ByteBits));
|
90
|
+
bit_bucket_reset(ptr);
|
91
|
+
return ptr;
|
92
|
+
}
|
93
|
+
|
94
|
+
/*
|
95
|
+
gives the size of the BitBucket in bytes
|
96
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
97
|
+
responsablity to ensure pointer is valid
|
98
|
+
*/
|
99
|
+
unsigned long long int bit_bucket_size(BitBucket *ptr){
|
100
|
+
return ptr->size/8+1;
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
gives the string representation of BitBucket
|
105
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
106
|
+
responsablity to ensure pointer is valid
|
107
|
+
*/
|
108
|
+
void bit_bucket_string(BitBucket *ptr, unsigned char* raw){
|
109
|
+
unsigned long long int count = ptr->size/8+1, i;
|
110
|
+
if(ptr == NULL){
|
111
|
+
puts("######### ERROR: ptr is returning null");
|
112
|
+
}
|
113
|
+
memcpy(raw,ptr->bucket, count);
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
Copies 1 Byte of given string to BitBucket* memory at given position
|
118
|
+
@param BitBucket* pointer to the bit bucket to use, users
|
119
|
+
responsablity to ensure pointer is valid
|
120
|
+
@param char* pointer to location where the 1 Byte is located
|
121
|
+
@pos unsigned long long int the offset byte location in BitBucket to be modified
|
122
|
+
*/
|
123
|
+
int bit_bucket_load_byte(BitBucket* ptr,char *buf, unsigned long long int pos){
|
124
|
+
unsigned long long int count = ptr->size/8+1, i;
|
125
|
+
if(ptr == NULL){
|
126
|
+
printf("####### ERROR: ptr is returning null");
|
127
|
+
return 2;
|
128
|
+
}
|
129
|
+
if(count < pos) return 2;
|
130
|
+
memcpy(ptr->bucket+pos, buf, 1);
|
131
|
+
return 1;
|
132
|
+
}
|
133
|
+
|
134
|
+
/*
|
135
|
+
Frees all the memory allocated by bit_bucket_create
|
136
|
+
Should be called before dereferencing BitBucket pointer
|
137
|
+
returned by bit_bucket_create
|
138
|
+
@param BitBucket* the pointer to be cleared
|
139
|
+
*/
|
140
|
+
void bit_bucket_free(BitBucket *ptr){
|
141
|
+
free(ptr->bucket);
|
142
|
+
free(ptr);
|
143
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#ifndef BIT_BUCKET
|
2
|
+
#define BIT_BUCKET
|
3
|
+
|
4
|
+
/*
|
5
|
+
this is the bitfield which takes 1 byte(8-bits) of space in memory
|
6
|
+
*/
|
7
|
+
typedef struct ByteBits{
|
8
|
+
unsigned char f0:1;
|
9
|
+
unsigned char f1:1;
|
10
|
+
unsigned char f2:1;
|
11
|
+
unsigned char f3:1;
|
12
|
+
unsigned char f4:1;
|
13
|
+
unsigned char f5:1;
|
14
|
+
unsigned char f6:1;
|
15
|
+
unsigned char f7:1;
|
16
|
+
} ByteBits;
|
17
|
+
|
18
|
+
/*
|
19
|
+
wrapper for sequence of ByteBits number of Bytebits will be
|
20
|
+
given_size(in bits)/8 + 1
|
21
|
+
*/
|
22
|
+
typedef struct BitBucket{
|
23
|
+
ByteBits *bucket;
|
24
|
+
unsigned long long int size; /* size in bits as given */
|
25
|
+
} BitBucket;
|
26
|
+
|
27
|
+
void _bit_bucket_set_bit_to(BitBucket* ptr,unsigned long long int byte_part, int bit_part, unsigned val);
|
28
|
+
int bit_bucket_set_bit(BitBucket* ptr,unsigned long long int num);
|
29
|
+
int bit_bucket_clear_bit(BitBucket* ptr,unsigned long long int num);
|
30
|
+
int bit_bucket_get_bit(BitBucket* ptr,unsigned long long int num);
|
31
|
+
void bit_bucket_reset(BitBucket *ptr);
|
32
|
+
BitBucket* bit_bucket_create(unsigned long long int size);
|
33
|
+
unsigned long long int bit_bucket_size(BitBucket *ptr);
|
34
|
+
void bit_bucket_string(BitBucket *ptr, unsigned char* raw);
|
35
|
+
int bit_bucket_load_byte(BitBucket* ptr,char *buf, unsigned long long int pos);
|
36
|
+
void bit_bucket_free(BitBucket *ptr);
|
37
|
+
#endif /* BIT_BUCKET */
|
@@ -0,0 +1,349 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <math.h>
|
5
|
+
|
6
|
+
#include "bit_mapper_wrap.h"
|
7
|
+
/* #include "bit_bucket.c" */
|
8
|
+
|
9
|
+
/*
|
10
|
+
Creates empty Bitmapper*. Without BitBucket pointers.
|
11
|
+
*/
|
12
|
+
Bitmapper* create_map(){
|
13
|
+
Bitmapper* map;
|
14
|
+
map = (Bitmapper*)malloc(sizeof(Bitmapper));
|
15
|
+
return map;
|
16
|
+
}
|
17
|
+
|
18
|
+
/*
|
19
|
+
Buckets are not allocated space a this point. They will be created
|
20
|
+
on the fly.
|
21
|
+
@param int Number of digits from left(Most Significant Digits) to be used
|
22
|
+
for indexing 10^(10-index) will be the size of the bucket in bits.
|
23
|
+
*/
|
24
|
+
void allocate_map(Bitmapper* map, int index_len){
|
25
|
+
unsigned long long int size = pow(10, index_len),i;
|
26
|
+
map->bkts = (BitBucket**)malloc(size*sizeof(BitBucket*));
|
27
|
+
for(i=0;i<size; i++){
|
28
|
+
map->bkts[i] = NULL;
|
29
|
+
}
|
30
|
+
map->bkt_size = pow(10, 10 - index_len);
|
31
|
+
map->bkt_count = size;
|
32
|
+
map->index_len = index_len;
|
33
|
+
sprintf(map->fill_str, "%%llu%%0%illu\n",10-index_len);
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
Clears the memory allocated by create_map and create_bucket_for(if available)
|
38
|
+
@param Bitmapper* the Bitmapper* object to clear, only the buckets in
|
39
|
+
the bitmap obj and the buckets pointer will be freed
|
40
|
+
*/
|
41
|
+
void free_map(Bitmapper* map){
|
42
|
+
unsigned long long int i;
|
43
|
+
for(i=0;i<map->bkt_count; i++){
|
44
|
+
if((map->bkts[i])!=NULL) bit_bucket_free(map->bkts[i]);
|
45
|
+
}
|
46
|
+
free(map->bkts);
|
47
|
+
free(map);
|
48
|
+
}
|
49
|
+
|
50
|
+
/*
|
51
|
+
Creates a Bitbucket with the given size and returns the pointer
|
52
|
+
@param BitBucket* the pointer to the bucket
|
53
|
+
@param unsigned long long int the size of bucket in bits
|
54
|
+
*/
|
55
|
+
BitBucket* create_bucket_for(BitBucket* bkt, unsigned long long int size){
|
56
|
+
bkt = bit_bucket_create(size);
|
57
|
+
return bkt;
|
58
|
+
}
|
59
|
+
|
60
|
+
/*
|
61
|
+
Adds the given number to the bucket reperesented by the given index
|
62
|
+
@param Bitmapper* the mapepr object to use
|
63
|
+
@param unsigned long long int the offset to be added(if the offset is greater
|
64
|
+
than bucket size it is rejected)
|
65
|
+
@param unsigned long long int the index of the bucket that will hold the number
|
66
|
+
*/
|
67
|
+
int add_num_in_bkt(Bitmapper* map,unsigned long long int offset, unsigned long long int bkt_index){
|
68
|
+
if(bkt_index > map->bkt_count) return 1;
|
69
|
+
if((map->bkts[bkt_index]) == NULL)
|
70
|
+
map->bkts[bkt_index] = (BitBucket*)create_bucket_for(map->bkts[bkt_index], map->bkt_size);
|
71
|
+
if(bit_bucket_set_bit(map->bkts[bkt_index], offset) != 0){
|
72
|
+
puts("out of range");
|
73
|
+
return 1;/* ERROR out of range */
|
74
|
+
}
|
75
|
+
return 0;
|
76
|
+
}
|
77
|
+
|
78
|
+
/*
|
79
|
+
Wrapper for add_num_in_bkt, splits the given number into index and
|
80
|
+
bit location
|
81
|
+
@param Bitmapper* the mapepr object to use
|
82
|
+
@param unsigned long long int the number
|
83
|
+
*/
|
84
|
+
int add_num(Bitmapper* map,unsigned long long int full_num){
|
85
|
+
unsigned long long int offset, bkt_index, div;
|
86
|
+
div = pow(10, 10-map->index_len);
|
87
|
+
bkt_index = full_num / div;
|
88
|
+
offset = full_num % div;
|
89
|
+
return add_num_in_bkt(map, offset, bkt_index);
|
90
|
+
}
|
91
|
+
|
92
|
+
/*
|
93
|
+
Removes the given number from the bucket reperesented by the given index
|
94
|
+
@param Bitmapper* the mapepr object to use
|
95
|
+
@param unsigned long long int the offset to be Removed(if the offset is greater
|
96
|
+
than bucket size it is rejected)
|
97
|
+
@param unsigned long long int the index of the bucket that would be hold the number
|
98
|
+
*/
|
99
|
+
int remove_num_in_bkt(Bitmapper* map,unsigned long long int offset, unsigned long long int bkt_index){
|
100
|
+
if(bkt_index > map->bkt_count) return 1;
|
101
|
+
if(map->bkts[bkt_index] == NULL)
|
102
|
+
return 0;
|
103
|
+
if(bit_bucket_clear_bit(map->bkts[bkt_index], offset) != 0){
|
104
|
+
puts("out of range");
|
105
|
+
return 1;/* ERROR out of range */
|
106
|
+
}
|
107
|
+
return 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
/*
|
111
|
+
Wrapper for remove_num_in_bkt, splits the given number into index and
|
112
|
+
bit location
|
113
|
+
@param Bitmapper* the mapepr object to use
|
114
|
+
@param unsigned long long int the number
|
115
|
+
*/
|
116
|
+
int remove_num(Bitmapper* map,unsigned long long int full_num){
|
117
|
+
unsigned long long int offset, bkt_index, div;
|
118
|
+
div = pow(10, 10-map->index_len);
|
119
|
+
bkt_index = full_num / div;
|
120
|
+
offset = full_num % div;
|
121
|
+
return remove_num_in_bkt(map, offset, bkt_index);
|
122
|
+
}
|
123
|
+
|
124
|
+
/*
|
125
|
+
returns the status of the given bit offset in the bucket reperesented by the given index
|
126
|
+
@param Bitmapper* the mapepr object to use
|
127
|
+
@param unsigned long long int the offset to be checked(if the number is greater
|
128
|
+
than bucket size it is rejected)
|
129
|
+
@param unsigned long long int the index of the bucket that would be hold the number
|
130
|
+
*/
|
131
|
+
int status_num_in_bkt(Bitmapper* map,unsigned long long int offset, unsigned long long int bkt_index){
|
132
|
+
if(bkt_index > map->bkt_count) return 2;
|
133
|
+
if(map->bkts[bkt_index] == NULL)
|
134
|
+
return 0;
|
135
|
+
return bit_bucket_get_bit(map->bkts[bkt_index], offset);
|
136
|
+
}
|
137
|
+
|
138
|
+
/*
|
139
|
+
Wrapper for status_num_in_bkt, splits the given number into index and
|
140
|
+
bit location
|
141
|
+
@param Bitmapper* the mapepr object to use
|
142
|
+
@param unsigned long long int the number
|
143
|
+
*/
|
144
|
+
int status_num(Bitmapper* map,unsigned long long int full_num){
|
145
|
+
unsigned long long int offset, bkt_index, div;
|
146
|
+
div = pow(10, 10-map->index_len);
|
147
|
+
bkt_index = full_num / div;
|
148
|
+
offset = full_num % div;
|
149
|
+
return status_num_in_bkt(map, offset, bkt_index);
|
150
|
+
}
|
151
|
+
|
152
|
+
/*
|
153
|
+
A wrapper method which take a file and loads all the numbers in that
|
154
|
+
file into Bitmapper*. Works with DOS & unix files.
|
155
|
+
@param Bitmapper* the mapepr object to use
|
156
|
+
@param FILE* the file pointer to the opened file
|
157
|
+
|
158
|
+
TODO: check for validity of number
|
159
|
+
*/
|
160
|
+
int add_numbers_in_file(Bitmapper* map,FILE *in){
|
161
|
+
char scan_str[20];
|
162
|
+
char msisdn[15], index[map->index_len], rest_num[10-map->index_len];
|
163
|
+
sprintf(scan_str, "%%%is%%%is\n",map->index_len, 10-map->index_len);
|
164
|
+
while(fgets(msisdn, 15, in)!=NULL){
|
165
|
+
sscanf(msisdn,scan_str, index, rest_num);
|
166
|
+
add_num_in_bkt(map, atoll(rest_num), atoll(index) );
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
A wrapper method which take a file and removes all the numbers in that
|
172
|
+
file from Bitmapper* if the number exist. Works with DOS & unix files.
|
173
|
+
@param Bitmapper* the mapepr object to use
|
174
|
+
@param FILE* the file pointer to the opened file
|
175
|
+
|
176
|
+
TODO: check for validity of number
|
177
|
+
*/
|
178
|
+
int remove_numbers_in_file(Bitmapper* map,FILE *del){
|
179
|
+
char scan_str[20];
|
180
|
+
char msisdn[15], index[map->index_len], rest_num[10-map->index_len];
|
181
|
+
sprintf(scan_str, "%%%is%%%is\n",map->index_len, 10-map->index_len);
|
182
|
+
while(fgets(msisdn, 15, del)!=NULL){
|
183
|
+
sscanf(msisdn,scan_str, index, rest_num);
|
184
|
+
remove_num_in_bkt(map, atoll(rest_num), atoll(index) );
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
Dumps the number in bucket(if available) into the given file
|
190
|
+
@param Bitmapper* the mapepr object to use
|
191
|
+
@param FILE* the file pointer to the opened file
|
192
|
+
@param unsigned long long int index to the bucket to consider
|
193
|
+
*/
|
194
|
+
int dump_bucket_to_file(Bitmapper* map, FILE* fp, unsigned long long int bkt_index){
|
195
|
+
unsigned long long int i;
|
196
|
+
unsigned num;
|
197
|
+
if(map->bkt_count<=bkt_index) return 1;
|
198
|
+
|
199
|
+
if(map->bkts[bkt_index] == NULL)
|
200
|
+
return 2;
|
201
|
+
for(i=0;i<map->bkt_size;i++){
|
202
|
+
num = bit_bucket_get_bit(map->bkts[bkt_index], i);
|
203
|
+
if(num==1){
|
204
|
+
fprintf(fp, map->fill_str, bkt_index, i);
|
205
|
+
}
|
206
|
+
}
|
207
|
+
return 0;
|
208
|
+
}
|
209
|
+
|
210
|
+
/*
|
211
|
+
Dumps all numbers set in Bitmapper* in into the given file
|
212
|
+
@param Bitmapper* the mapepr object to use
|
213
|
+
@param FILE* the file pointer to the opened file
|
214
|
+
@param unsigned long long int the length of index
|
215
|
+
*/
|
216
|
+
int dump_all_to_file(Bitmapper* map, FILE* fp){
|
217
|
+
unsigned long long int i;
|
218
|
+
for(i=0;i<map->bkt_count;i++){
|
219
|
+
dump_bucket_to_file(map, fp, i);
|
220
|
+
}
|
221
|
+
return 0;
|
222
|
+
}
|
223
|
+
|
224
|
+
/*
|
225
|
+
Dumps the bucket's(if available) bit values into the given file
|
226
|
+
@param Bitmapper* the mapepr object to use
|
227
|
+
@param FILE* the file pointer to the opened file
|
228
|
+
@param unsigned long long int index to the bucket to consider
|
229
|
+
|
230
|
+
TODO: If the bucket doesn't exist, dump empty string equal to the
|
231
|
+
size of the bucket
|
232
|
+
*/
|
233
|
+
int dump_bucket_str_to_file(Bitmapper* map, FILE* fp,unsigned long long int bkt_index){
|
234
|
+
unsigned char* raw = (unsigned char*)malloc(map->bkt_size/8+1);
|
235
|
+
BitBucket* tmp;
|
236
|
+
if(map->bkts[bkt_index] == NULL)
|
237
|
+
tmp = bit_bucket_create(map->bkt_size);
|
238
|
+
else
|
239
|
+
tmp = map->bkts[bkt_index];
|
240
|
+
bit_bucket_string(tmp, raw);
|
241
|
+
fwrite(raw, 1, bit_bucket_size(tmp), fp);
|
242
|
+
|
243
|
+
if(map->bkts[bkt_index] == NULL)
|
244
|
+
bit_bucket_free(tmp);
|
245
|
+
free(raw);
|
246
|
+
return 0;
|
247
|
+
}
|
248
|
+
|
249
|
+
/*
|
250
|
+
Dumps all bucket's bit values into the given file
|
251
|
+
@param Bitmapper* the mapepr object to use
|
252
|
+
@param FILE* the file pointer to the opened file
|
253
|
+
@param unsigned long long int the length of index
|
254
|
+
*/
|
255
|
+
int dump_all_str_to_file(Bitmapper* map, FILE* fp){
|
256
|
+
unsigned long long int i;
|
257
|
+
for(i=0;i<map->bkt_count;i++){
|
258
|
+
dump_bucket_str_to_file(map, fp, i);
|
259
|
+
}
|
260
|
+
return 0;
|
261
|
+
}
|
262
|
+
|
263
|
+
/*
|
264
|
+
Loads binary string from file to given bitmap bucket. Creates
|
265
|
+
bucket if it doesn't exist
|
266
|
+
@param Bitmapper* the mapepr object to use
|
267
|
+
@param FILE* the file pointer to the opened file
|
268
|
+
@param unsigned long long int the index of bucket to load
|
269
|
+
*/
|
270
|
+
int load_str_file_to_bucket(Bitmapper* map, FILE* fp,unsigned long long int bkt_index){
|
271
|
+
unsigned long long int size,i;
|
272
|
+
char buf[1];
|
273
|
+
if(map->bkts[bkt_index] == NULL){
|
274
|
+
puts("creating bucket");
|
275
|
+
map->bkts[bkt_index] = (BitBucket*)create_bucket_for(map->bkts[bkt_index], map->bkt_size);
|
276
|
+
}
|
277
|
+
|
278
|
+
size = bit_bucket_size(map->bkts[bkt_index]);
|
279
|
+
for(i=0;i<size;i++){
|
280
|
+
fread(buf, 1, 1, fp);
|
281
|
+
if(buf == NULL) break;
|
282
|
+
bit_bucket_load_byte(map->bkts[bkt_index], buf, i);
|
283
|
+
}
|
284
|
+
return 0;
|
285
|
+
}
|
286
|
+
|
287
|
+
/*
|
288
|
+
Loads binary string from file to given bitmap-> Creates
|
289
|
+
bucket if it doesn't exist.
|
290
|
+
* The load is one-one bit maping.
|
291
|
+
* bits exceding Bitmapper* size(buckets count * size of each bucket
|
292
|
+
in bits) will be ignored
|
293
|
+
* the size of the bucket reperesented in file string must be equal
|
294
|
+
to the size of bucket in Bitmapper*.
|
295
|
+
@param Bitmapper* the mapepr object to use
|
296
|
+
@param FILE* the file pointer to the opened file
|
297
|
+
@param unsigned long long int the index of bucket to load
|
298
|
+
*/
|
299
|
+
int load_str_file(Bitmapper* map, FILE* fp){
|
300
|
+
unsigned long long int size, i, bkt_no;
|
301
|
+
char buf[1];
|
302
|
+
for(bkt_no = 0;bkt_no < map->bkt_count; bkt_no++){
|
303
|
+
if(map->bkts[bkt_no] == NULL){
|
304
|
+
// TODO
|
305
|
+
puts("creating bucket");
|
306
|
+
map->bkts[bkt_no] = (BitBucket*)create_bucket_for(map->bkts[bkt_no], map->bkt_size);
|
307
|
+
}
|
308
|
+
size = bit_bucket_size(map->bkts[bkt_no]);
|
309
|
+
for(i=0;i<size;i++){
|
310
|
+
fread(buf, 1, 1, fp);
|
311
|
+
if(buf == NULL) return 0;
|
312
|
+
bit_bucket_load_byte(map->bkts[bkt_no], buf, i);
|
313
|
+
}
|
314
|
+
return 0;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
void test(){
|
319
|
+
int index_len = 6;
|
320
|
+
FILE *in, *out, *del, *str_out, *str_in;
|
321
|
+
Bitmapper* map = create_map();
|
322
|
+
allocate_map(map, index_len);
|
323
|
+
in = fopen("/tmp/ncpr/out.txt","r");
|
324
|
+
add_numbers_in_file(map, in);
|
325
|
+
/* in = fopen("test/data/1-add.txt","r"); */
|
326
|
+
/* del = fopen("test/data/1-del.txt","r"); */
|
327
|
+
out = fopen("/tmp/ncpr/out2.txt","w");
|
328
|
+
/* str_out = fopen("/tmp/ncpr/str_out.txt","w"); */
|
329
|
+
/* add_numbers_in_file(map, in, index_len); */
|
330
|
+
/* // remove_numbers_in_file(map, del); */
|
331
|
+
/* /\* dump_all_str_to_file( map, str_out); *\/ */
|
332
|
+
/* dump_bucket_str_to_file(map, str_out, 934793); */
|
333
|
+
/* fclose(str_out); */
|
334
|
+
/* str_in = fopen("/tmp/ncpr/str_out.txt","r"); */
|
335
|
+
/* load_str_file_to_bucket(map, str_in, 934793); */
|
336
|
+
/* puts("dumping to file"); */
|
337
|
+
dump_all_to_file(map, out);
|
338
|
+
|
339
|
+
|
340
|
+
fclose(in);
|
341
|
+
/* fclose(del); */
|
342
|
+
fclose(out);
|
343
|
+
/* fclose(str_in); */
|
344
|
+
free_map(map);
|
345
|
+
}
|
346
|
+
|
347
|
+
void main(){
|
348
|
+
test();
|
349
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "bit_bucket.h"
|
2
|
+
|
3
|
+
#ifndef BIT_MAPPER_WRAP
|
4
|
+
#define BIT_MAPPER_WRAP
|
5
|
+
|
6
|
+
/*
|
7
|
+
Bitmapper Object holds the buckets pointer and other info
|
8
|
+
*/
|
9
|
+
typedef struct Bitmapper{
|
10
|
+
BitBucket** bkts; /* pointer to list of pointers(count=bkt_count) */
|
11
|
+
unsigned long long int bkt_count; /* number of buckets in Bitmapper */
|
12
|
+
unsigned long long int bkt_size; /* size of each bucket in bits */
|
13
|
+
/* the format specifier used to dump number to file from buckets */
|
14
|
+
int index_len;
|
15
|
+
char fill_str[20];
|
16
|
+
} Bitmapper;
|
17
|
+
|
18
|
+
Bitmapper* create_map();
|
19
|
+
void allocate_map(Bitmapper*, int);
|
20
|
+
void free_map(Bitmapper*);
|
21
|
+
BitBucket* create_bucket_for(BitBucket*, unsigned long long int);
|
22
|
+
int add_num_in_bkt(Bitmapper* ,unsigned long long int, unsigned long long int);
|
23
|
+
int add_num(Bitmapper* ,unsigned long long int);
|
24
|
+
int remove_num_in_bkt(Bitmapper* ,unsigned long long int, unsigned long long int);
|
25
|
+
int remove_num(Bitmapper* ,unsigned long long int);
|
26
|
+
int status_num_in_bkt(Bitmapper* ,unsigned long long int, unsigned long long int);
|
27
|
+
int status_num(Bitmapper* ,unsigned long long int);
|
28
|
+
|
29
|
+
int add_numbers_in_file(Bitmapper* ,FILE*);
|
30
|
+
int remove_numbers_in_file(Bitmapper* ,FILE* );
|
31
|
+
int dump_bucket_to_file(Bitmapper*, FILE* , unsigned long long int);
|
32
|
+
int dump_all_to_file(Bitmapper* , FILE* );
|
33
|
+
|
34
|
+
int dump_bucket_str_to_file(Bitmapper* , FILE* ,unsigned long long int );
|
35
|
+
int dump_all_str_to_file(Bitmapper* , FILE*);
|
36
|
+
int load_str_file_to_bucket(Bitmapper* , FILE* ,unsigned long long int);
|
37
|
+
int load_str_file(Bitmapper* , FILE*);
|
38
|
+
|
39
|
+
#endif /* BIT_MAPPER_WRAP */
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "bit_mapper_wrap.h"
|
3
|
+
|
4
|
+
static VALUE rb_cBitmapper;
|
5
|
+
static ID index_len;
|
6
|
+
|
7
|
+
VALUE bm_init(VALUE self, VALUE len){
|
8
|
+
Bitmapper* map;
|
9
|
+
Data_Get_Struct(self, Bitmapper, map);
|
10
|
+
allocate_map(map, FIX2INT(len));
|
11
|
+
rb_iv_set(self, "@index_len", len);
|
12
|
+
return self;
|
13
|
+
}
|
14
|
+
|
15
|
+
/*
|
16
|
+
TODO: check if void* to Bitmapper* is a safe cast
|
17
|
+
*/
|
18
|
+
void bm_free(void *p){
|
19
|
+
free_map((Bitmapper*)p);
|
20
|
+
}
|
21
|
+
|
22
|
+
VALUE bm_alloc(VALUE self){
|
23
|
+
Bitmapper* map;
|
24
|
+
map = create_map();
|
25
|
+
return Data_Wrap_Struct(self, 0, bm_free, map);
|
26
|
+
}
|
27
|
+
|
28
|
+
/*
|
29
|
+
Generates current index and assign it to @indexes variable
|
30
|
+
*/
|
31
|
+
VALUE bm_referesh_indexes(VALUE self){
|
32
|
+
Bitmapper* map;
|
33
|
+
ID id_push;
|
34
|
+
VALUE arr;
|
35
|
+
FILE *fp;
|
36
|
+
unsigned long long int i;
|
37
|
+
arr = rb_ary_new();
|
38
|
+
id_push = rb_intern("push");
|
39
|
+
Data_Get_Struct(self, Bitmapper, map);
|
40
|
+
|
41
|
+
rb_funcall(arr, rb_intern("clear"), 0);
|
42
|
+
for(i=0;i<map->bkt_count;i++)
|
43
|
+
if(map->bkts[i] != NULL)
|
44
|
+
rb_funcall(arr, id_push, 1, LL2NUM(i));
|
45
|
+
|
46
|
+
rb_iv_set(self, "@indexes", arr);
|
47
|
+
return self;
|
48
|
+
}
|
49
|
+
|
50
|
+
/*
|
51
|
+
Call to refresh indexs in @indexes
|
52
|
+
and return the value
|
53
|
+
*/
|
54
|
+
VALUE bm_get_indexes(VALUE self){
|
55
|
+
bm_referesh_indexes(self);
|
56
|
+
return rb_iv_get(self, "@indexes");
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE bm_add_from_file(VALUE self, VALUE file_str){
|
60
|
+
Bitmapper* map;
|
61
|
+
FILE *fp;
|
62
|
+
Data_Get_Struct(self, Bitmapper, map);
|
63
|
+
fp = fopen(RSTRING_PTR(StringValue(file_str)), "r");
|
64
|
+
if(fp == NULL) rb_raise(rb_eIOError, "file counld not be opened");
|
65
|
+
add_numbers_in_file(map, fp);
|
66
|
+
fclose(fp);
|
67
|
+
return self;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE bm_remove_from_file(VALUE self, VALUE file_str){
|
71
|
+
Bitmapper* map;
|
72
|
+
FILE *fp;
|
73
|
+
Data_Get_Struct(self, Bitmapper, map);
|
74
|
+
fp = fopen(RSTRING_PTR(StringValue(file_str)), "r");
|
75
|
+
if(fp == NULL) rb_raise(rb_eIOError, "file counld not be opened");
|
76
|
+
remove_numbers_in_file(map, fp);
|
77
|
+
fclose(fp);
|
78
|
+
return self;
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE bm_dump_to_file(VALUE self, VALUE file_str){
|
82
|
+
Bitmapper* map;
|
83
|
+
FILE *fp;
|
84
|
+
Data_Get_Struct(self, Bitmapper, map);
|
85
|
+
fp = fopen(RSTRING_PTR(StringValue(file_str)), "w");
|
86
|
+
if(fp == NULL) rb_raise(rb_eIOError, "file counld not be opened");
|
87
|
+
dump_all_to_file(map, fp);
|
88
|
+
fclose(fp);
|
89
|
+
return self;
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE bm_load_str_to_bkt(VALUE self, VALUE file_str, VALUE index){
|
93
|
+
Bitmapper* map;
|
94
|
+
FILE *fp;
|
95
|
+
Data_Get_Struct(self, Bitmapper, map);
|
96
|
+
fp = fopen(RSTRING_PTR(StringValue(file_str)), "r");
|
97
|
+
if(fp == NULL) rb_raise(rb_eIOError, "file counld not be opened");
|
98
|
+
load_str_file_to_bucket(map, fp, NUM2LL(index));
|
99
|
+
fclose(fp);
|
100
|
+
return self;
|
101
|
+
}
|
102
|
+
|
103
|
+
VALUE bm_dump_bkt_str(VALUE self, VALUE file_str, VALUE index){
|
104
|
+
Bitmapper* map;
|
105
|
+
FILE *fp;
|
106
|
+
Data_Get_Struct(self, Bitmapper, map);
|
107
|
+
fp = fopen(RSTRING_PTR(StringValue(file_str)), "w");
|
108
|
+
if(fp == NULL) rb_raise(rb_eIOError, "file counld not be opened");
|
109
|
+
dump_bucket_str_to_file(map, fp, NUM2LL(index));
|
110
|
+
fclose(fp);
|
111
|
+
return self;
|
112
|
+
}
|
113
|
+
|
114
|
+
/*
|
115
|
+
helper method, works as to_i for various datatypes
|
116
|
+
*/
|
117
|
+
unsigned long long int bm_to_ll(VALUE num){
|
118
|
+
VALUE tmp;
|
119
|
+
switch(TYPE(num)){
|
120
|
+
case T_STRING:
|
121
|
+
tmp = rb_funcall(num, rb_intern("to_i"), 0); /* hack */
|
122
|
+
return NUM2LL(tmp);
|
123
|
+
case T_FIXNUM:
|
124
|
+
case T_BIGNUM:
|
125
|
+
return NUM2LL(num);
|
126
|
+
}
|
127
|
+
return 0;
|
128
|
+
}
|
129
|
+
|
130
|
+
/*
|
131
|
+
adds the given number to bitmapper
|
132
|
+
*/
|
133
|
+
VALUE bm_set(VALUE self, VALUE num){
|
134
|
+
int status;
|
135
|
+
Bitmapper* map;
|
136
|
+
|
137
|
+
Data_Get_Struct(self, Bitmapper, map);
|
138
|
+
status = add_num(map, bm_to_ll(num));
|
139
|
+
if(status==0)
|
140
|
+
return (VALUE)Qtrue;
|
141
|
+
else
|
142
|
+
rb_raise(rb_eTypeError, "not valid number");
|
143
|
+
return (VALUE)Qfalse;
|
144
|
+
}
|
145
|
+
|
146
|
+
/*
|
147
|
+
removes the given number from bitmapper
|
148
|
+
*/
|
149
|
+
VALUE bm_clear(VALUE self, VALUE num){
|
150
|
+
int status;
|
151
|
+
Bitmapper* map;
|
152
|
+
|
153
|
+
Data_Get_Struct(self, Bitmapper, map);
|
154
|
+
status = remove_num(map, bm_to_ll(num));
|
155
|
+
if(status==0)
|
156
|
+
return (VALUE)Qtrue;
|
157
|
+
else
|
158
|
+
rb_raise(rb_eTypeError, "not valid number");
|
159
|
+
return (VALUE)Qfalse;
|
160
|
+
}
|
161
|
+
|
162
|
+
/*
|
163
|
+
returns true if the provided number is present in bitmap or returns
|
164
|
+
false
|
165
|
+
*/
|
166
|
+
VALUE bm_num_status(VALUE self, VALUE num){
|
167
|
+
int status;
|
168
|
+
VALUE return_val;
|
169
|
+
Bitmapper* map;
|
170
|
+
|
171
|
+
Data_Get_Struct(self, Bitmapper, map);
|
172
|
+
status = status_num(map, bm_to_ll(num));
|
173
|
+
if(status==1)
|
174
|
+
return (VALUE)Qtrue;
|
175
|
+
else if(status == 0)
|
176
|
+
return (VALUE)Qfalse;
|
177
|
+
else
|
178
|
+
rb_raise(rb_eTypeError, "not valid number");
|
179
|
+
return (VALUE)Qfalse;
|
180
|
+
|
181
|
+
}
|
182
|
+
|
183
|
+
void Init_bitmapper(){
|
184
|
+
rb_cBitmapper = rb_define_class("Bitmapper", rb_cObject);
|
185
|
+
rb_define_alloc_func(rb_cBitmapper, bm_alloc);
|
186
|
+
rb_define_method(rb_cBitmapper, "initialize", bm_init, 1);
|
187
|
+
rb_define_method(rb_cBitmapper, "get_indexes", bm_get_indexes, 0);
|
188
|
+
rb_define_method(rb_cBitmapper, "add", bm_add_from_file, 1);
|
189
|
+
rb_define_method(rb_cBitmapper, "remove", bm_remove_from_file, 1);
|
190
|
+
rb_define_method(rb_cBitmapper, "dump_to", bm_dump_to_file, 1);
|
191
|
+
rb_define_method(rb_cBitmapper, "load_from_str", bm_load_str_to_bkt, 2);
|
192
|
+
rb_define_method(rb_cBitmapper, "dump_to_str", bm_dump_bkt_str, 2);
|
193
|
+
|
194
|
+
rb_define_method(rb_cBitmapper, "status?", bm_num_status, 1);
|
195
|
+
rb_define_method(rb_cBitmapper, "set", bm_set, 1);
|
196
|
+
rb_define_method(rb_cBitmapper, "clear", bm_clear, 1);
|
197
|
+
|
198
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Loads mkmf which is used to make makefiles for Ruby extensions
|
2
|
+
require 'mkmf'
|
3
|
+
|
4
|
+
# Give it a name
|
5
|
+
extension_name = 'bitmapper'
|
6
|
+
|
7
|
+
# The destination
|
8
|
+
dir_config("bitmapper/#{extension_name}")
|
9
|
+
|
10
|
+
# Do the work
|
11
|
+
create_makefile("bitmapper/#{extension_name}")
|
data/lib/bitmapper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bitmapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Goutham Vel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-11 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: PENDING
|
15
|
+
email: gouthamvel@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions:
|
18
|
+
- ext/bitmapper/extconf.rb
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/bitmapper.rb
|
22
|
+
- ext/bitmapper/bitmapper.c
|
23
|
+
- ext/bitmapper/bit_bucket.c
|
24
|
+
- ext/bitmapper/bit_mapper_wrap.c
|
25
|
+
- ext/bitmapper/bit_bucket.h
|
26
|
+
- ext/bitmapper/bit_mapper_wrap.h
|
27
|
+
- ext/bitmapper/extconf.rb
|
28
|
+
homepage: ''
|
29
|
+
licenses: []
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.23
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: A fast bit map filter!
|
52
|
+
test_files: []
|