bitmapper 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|