-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinsimkanal.c
100 lines (85 loc) · 2.63 KB
/
binsimkanal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*****************************************************
* binsimkanal -- program to flip bits in input file *
* *
* Author: Filip Hrenić *
* *
* Purpose: TINF lab 2015/2016 *
* *
* Usage: *
* binsimkanal input error output *
* - input: input file *
* - error: number [0,1] *
* - output: output file *
*****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct BinStream {
FILE* file;
int idx;
char buffer;
} BinStream;
BinStream* newBinStream(FILE* file){
BinStream* b = (BinStream*) malloc(sizeof(BinStream));
b->file = file;
b->idx = 0;
b->buffer = 0;
return b;
}
int readBit(BinStream* in, int* bit){
int s = sizeof(in->buffer);
if (in->idx == 0)
if (!fread(&(in->buffer), s, 1, in->file)) return 0;
*bit = ((1<<(8*s-1 - in->idx)) & in->buffer) != 0;
in->idx = (in->idx + 1) % (8*s);
return 1;
}
void writeBit(BinStream* out, int bit){
int s = sizeof(out->buffer);
out->buffer *= 2;
out->buffer += bit;
if (++out->idx == 8 * s){
out->idx = 0;
fwrite(&(out->buffer), s, 1, out->file);
out->buffer = 0;
}
}
void flush(BinStream* out){
if (!out->idx) return;
int s = sizeof(out->buffer);
while(out->idx){
out->buffer *= 2;
out->idx = (out->idx + 1) % (8*s);
}
fwrite(&(out->buffer), s, 1, out->file);
out->buffer = 0;
}
int main(int argc, char *argv[]){
if (argc != 4){
fprintf(stderr, "Have to provide input and output file with error rate.\nExample: %s input_file error_rate output_file\n", argv[0]);
return -1;
}
time_t t;
srand((unsigned) time(&t));
FILE* input = fopen(argv[1], "rb");
FILE* output = fopen(argv[3], "wb");
double e = atof(argv[2]);
if (e<0 || e>1){
fprintf(stderr, "Error rate must be in range [0,1]\n");
return -1;
}
fprintf(stderr, "Channeling...\n");
BinStream* in = newBinStream(input);
BinStream* out = newBinStream(output);
int bound = e * RAND_MAX;
int bit;
while(readBit(in, &bit)){
if (rand() < bound) bit ^= 1; // change bit
writeBit(out, bit);
}
flush(out);
fprintf(stderr, "Done!\n");
fclose(input);
fclose(output);
return 0;
}