-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbitio.c
More file actions
203 lines (161 loc) · 4.84 KB
/
bitio.c
File metadata and controls
203 lines (161 loc) · 4.84 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "bitio.h"
#define BIT_IO_BUFFER 4096
struct bitFILE{
FILE *file; /* file to (from) write (read) */
int mode; /* the mode (READ or WRITE) */
int bytepos; /* actual byte's position in the buffer */
int bitpos; /* last bit's position in the byte */
int read; /* # of bytes read from the file and stored in buffer */
unsigned char *buffer; /* bits buffer */
};
int bitof(int n){
return (int)(ceil(log(n)/log(2)));
}
int bitIO_feof(struct bitFILE *bitF)
{
if (feof(bitF->file) && bitF->bytepos == bitF->read)
return 1;
return 0;
}
int bitIO_ferror(struct bitFILE *bitF)
{
return (ferror(bitF->file));
}
void write_buffer(struct bitFILE *bitF){
int ret;
/* write data */
ret = fwrite(bitF->buffer, 1, bitF->bytepos, bitF->file);
/* check for errors on writing */
if(ret != bitF->bytepos)
return;
/* clear the buffer */
bitF->bytepos = 0;
bitF->bitpos = 0;
memset(bitF->buffer, 0, BIT_IO_BUFFER);
}
void read_buffer(struct bitFILE *bitF){
/* read data */
bitF->read = fread(bitF->buffer, 1, BIT_IO_BUFFER, bitF->file);
/* check for errors */
if(bitF->read < BIT_IO_BUFFER && ferror(bitF->file))
return;
/* clear variables */
bitF->bytepos = 0;
bitF->bitpos = 0;
}
struct bitFILE* bitIO_open(const char *path, int mode){
struct bitFILE *bitF;
/* errors handler */
if(mode!=BIT_IO_W && mode!=BIT_IO_R)
{
printf("Invalid mode detected.\n");
return NULL;
}
if(path == NULL)
return NULL;
/* initialize structure */
bitF = (struct bitFILE*)calloc(1, sizeof(struct bitFILE));
bitF->mode = mode;
bitF->bytepos = 0;
bitF->bitpos = 0;
bitF->buffer = (unsigned char*)calloc(BIT_IO_BUFFER, sizeof(unsigned char));
memset(bitF->buffer, 0, BIT_IO_BUFFER);
/* open file */
/*read binary mode */
if(bitF->mode == BIT_IO_R)
{
if((bitF->file = fopen(path, "rb")) == NULL)
return NULL;
/* fill the buffer for the 1st time */
read_buffer(bitF);
}
/* write mode */
else if((bitF->file = fopen(path, "w")) == NULL)
return NULL;
return bitF;
}
int bitIO_close(struct bitFILE *bitF){
/* errors handler */
if(bitF == NULL || bitF->file == NULL)
return -1;
/* write the unwritten bytes into the file */
if(bitF->mode == BIT_IO_W)
{
if(bitF->bitpos > 0)
(bitF->bytepos)++;
write_buffer(bitF);
}
/* close the file */
fclose(bitF->file);
/* free memory */
free(bitF->buffer);
free(bitF);
return 0;
}
int bitIO_write(struct bitFILE *bitF, void *info, int nbit){
int i;
int byte_pos = 0, bit_pos = 0; /* byte's position and bit's position */
unsigned char mask; /* mask of bits */
/* errors handler */
if(bitF == NULL || bitF->file == NULL || bitF->mode != BIT_IO_W|| info == NULL || nbit < 0)
return -1;
for(i=0; i<nbit; i++)
{
/* get bit to write */
mask = 1 << bit_pos;
/* if it is a 1 set it, otherwise do nothing */
if((*(unsigned char *)(info + byte_pos) & mask) != 0)
bitF->buffer[bitF->bytepos] |= (1 << bitF->bitpos);
/* update info to write variables */
byte_pos = (bit_pos < 7)? byte_pos : (byte_pos + 1);
bit_pos = (bit_pos < 7)? (bit_pos + 1) : 0;
/* update bitF structure */
bitF->bytepos = (bitF->bitpos < 7)? bitF->bytepos : (bitF->bytepos + 1);
bitF->bitpos = (bitF->bitpos <7)? (bitF->bitpos + 1) : 0;
/* check if a write_buffer must be done */
if(bitF->bytepos == BIT_IO_BUFFER)
write_buffer(bitF);
/* check for writing errors */
if(bitIO_ferror(bitF) != 0)
break;
}
return i;
}
int bitIO_read(struct bitFILE *bitF, void *info, int info_s, int nbit){
int i;
int byte_pos = 0, bit_pos = 0; /* byte's position and bit's position */
unsigned char mask; /* mask of bits */
/* errors handler */
if(bitF == NULL || bitF->file == NULL || bitF->mode != BIT_IO_R || info == NULL || info_s <= 0 || nbit < 0)
return -1;
/* clear the 'info' buffer */
memset(info, 0, info_s);
/* begin the reading */
for(i=0; i<nbit && (bitIO_feof(bitF) != 1); i++)
{
/* get bit to read */
mask = 1 << bitF->bitpos;
/* if it is a 1 set it, otherwise do nothing */
if((bitF->buffer[bitF->bytepos] & mask) != 0)
*(unsigned char *)(info + byte_pos) |= (1 << bit_pos);
/* update buffers */
/* update info to write variables */
byte_pos = (bit_pos < 7)? byte_pos : (byte_pos + 1);
bit_pos = (bit_pos < 7)? (bit_pos + 1) : 0;
/* update bitF structure */
bitF->bytepos = (bitF->bitpos < 7)? bitF->bytepos : (bitF->bytepos + 1);
bitF->bitpos = (bitF->bitpos <7)? (bitF->bitpos + 1) : 0;
/* check if it read all bits from the file and, if it is the case,
it reads new bytes from the file */
if(bitF->bytepos == BIT_IO_BUFFER)
read_buffer(bitF);
/* check for reading errors */
if(bitIO_ferror(bitF) != 0)
break;
}
return i;
}