2 #include "../include/debug.h"
3 #include "../include/endianness.h"
6 void ByteArray_defaults(struct ByteArray
* self
) {
7 memset(self
, 0, sizeof(*self
));
10 void ByteArray_ctor(struct ByteArray
* self
) {
11 ByteArray_defaults(self
);
12 // original constructor code goes here
13 self
->readMultiByte
= ByteArray_readMultiByte
;
14 self
->readByte
= ByteArray_readByte
;
15 self
->readUnsignedByte
= ByteArray_readUnsignedByte
;
16 self
->readShort
= ByteArray_readShort
;
17 self
->readUnsignedShort
= ByteArray_readUnsignedShort
;
18 self
->readInt
= ByteArray_readInt
;
19 self
->readUnsignedInt
= ByteArray_readUnsignedInt
;
20 self
->readBytes
= ByteArray_readBytes
;
22 self
->writeInt
= ByteArray_writeInt
;
23 self
->writeUnsignedInt
= ByteArray_writeUnsignedInt
;
24 self
->writeShort
= ByteArray_writeShort
;
25 self
->writeUnsignedShort
= ByteArray_writeUnsignedShort
;
26 self
->writeByte
= ByteArray_writeByte
;
27 self
->writeUnsignedByte
= ByteArray_writeUnsignedByte
;;
28 self
->writeMem
= ByteArray_writeMem
;
29 self
->writeUTFBytes
= ByteArray_writeUTFBytes
;
30 self
->writeBytes
= ByteArray_writeBytes
;
31 self
->writeFloat
= ByteArray_writeFloat
;
33 self
->set_position
= ByteArray_set_position
;
34 self
->set_position_rel
= ByteArray_set_position_rel
;
35 self
->get_position
= ByteArray_get_position
;
37 self
->bytesAvailable
= ByteArray_bytesAvailable
;
39 #ifdef IS_LITTLE_ENDIAN
40 self
->sys_endian
= BAE_LITTLE
;
42 self
->sys_endian
= BAE_BIG
;
46 struct ByteArray
* ByteArray_new(void) {
47 struct ByteArray
* self
= (struct ByteArray
*) malloc(sizeof(*self
));
48 if(self
) ByteArray_ctor(self
);
52 void ByteArray_set_endian(struct ByteArray
* self
, enum ByteArray_Endianess endian
) {
53 self
->endian
= endian
;
56 enum ByteArray_Endianess
ByteArray_get_endian(struct ByteArray
* self
) {
60 // a real byte array clears the mem and resets
62 // where len is equivalent to the bytes written into it
63 void ByteArray_clear(struct ByteArray
* self
) {
64 fprintf(stderr
, "clear called\n");
65 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
66 assert_op(self
->start_addr
, !=, 0);
67 memset(self
->start_addr
, 0, self
->size
);
70 off_t
ByteArray_get_position(struct ByteArray
* self
) {
74 static void seek_error() {
75 perror("seek error!\n");
79 static void neg_off() {
80 fprintf(stderr
, "negative seek attempted\n");
85 fprintf(stderr
, "oob access attempted\n");
89 void ByteArray_set_length(struct ByteArray
* self
, off_t len
) {
90 if(len
> self
->size
) {
97 off_t
ByteArray_get_length(struct ByteArray
* self
) {
101 int ByteArray_set_position_rel(struct ByteArray
* self
, int rel
) {
102 if((int) self
->pos
+ rel
< 0) {
106 return ByteArray_set_position(self
, self
->pos
+ rel
);
109 int ByteArray_set_position(struct ByteArray
* self
, off_t pos
) {
110 if(pos
== self
->pos
) return 1;
111 if(pos
> self
->size
) {
116 if(self
->type
== BAT_FILESTREAM
) {
117 off_t ret
= lseek(self
->fd
, pos
, SEEK_SET
);
118 if(ret
== (off_t
) -1) {
127 static void read_error() {
128 perror("read error!\n");
132 static void read_error_short() {
133 perror("read error (short)!\n");
137 int ByteArray_open_file(struct ByteArray
* self
, const char* filename
) {
139 self
->type
= BAT_FILESTREAM
;
142 if(stat(filename
, &st
) == -1) return 0;
143 self
->size
= st
.st_size
;
144 self
->fd
= open(filename
, O_RDONLY
);
145 return (self
->fd
!= -1);
148 void ByteArray_close_file(struct ByteArray
*self
) {
153 int ByteArray_open_mem(struct ByteArray
* self
, char* data
, size_t size
) {
156 self
->type
= BAT_MEMSTREAM
;
157 self
->start_addr
= data
;
161 void ByteArray_readMultiByte(struct ByteArray
* self
, char* buffer
, size_t len
) {
162 if(self
->type
== BAT_MEMSTREAM
) {
163 assert_op(self
->start_addr
, !=, 0);
164 assert_op((off_t
) (self
->pos
+ len
), <=, self
->size
);
165 memcpy(buffer
, &self
->start_addr
[self
->pos
], len
);
167 ssize_t ret
= read(self
->fd
, buffer
, len
);
171 } else if(ret
!= (ssize_t
) len
) {
180 // write contents of self into what
181 // if len == 0 all available bytes are used.
182 // self->pos is considered the start offset to use for self.
183 // the position in dest will not be advanced.
184 // the position in source will be advanced len bytes.
185 // returns the number of bytes written
186 off_t
ByteArray_readBytes(struct ByteArray
* self
, struct ByteArray
*dest
, off_t start
, off_t len
) {
187 off_t left
= self
->size
- self
->pos
;
188 if(len
== 0) len
= left
;
189 else if(len
> left
) {
193 if(len
== 0) return 0;
194 else if (len
> start
+ dest
->size
) {
196 len
= start
+ dest
->size
;
197 if(len
== 0) return 0;
199 if(dest
->type
!= BAT_MEMSTREAM
) {
202 self
->readMultiByte(self
, &dest
->start_addr
[start
], len
);
206 off_t
ByteArray_bytesAvailable(struct ByteArray
* self
) {
207 if(self
->pos
< self
->size
) return self
->size
- self
->pos
;
211 unsigned int ByteArray_readUnsignedInt(struct ByteArray
* self
) {
214 unsigned char charval
[sizeof(unsigned int)];
216 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
217 if(self
->endian
!= self
->sys_endian
) {
218 buf
.intval
= byteswap32(buf
.intval
);
223 int ByteArray_readInt(struct ByteArray
* self
) {
226 unsigned char charval
[sizeof(unsigned int)];
228 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
229 if(self
->endian
!= self
->sys_endian
) {
230 buf
.intval
= byteswap32(buf
.intval
);
235 unsigned short ByteArray_readUnsignedShort(struct ByteArray
* self
) {
237 unsigned short intval
;
238 unsigned char charval
[sizeof(unsigned short)];
240 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
241 if(self
->endian
!= self
->sys_endian
) {
242 buf
.intval
= byteswap16(buf
.intval
);
247 short ByteArray_readShort(struct ByteArray
* self
) {
249 unsigned short intval
;
250 unsigned char charval
[sizeof(unsigned short)];
252 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
253 if(self
->endian
!= self
->sys_endian
) {
254 buf
.intval
= byteswap16(buf
.intval
);
259 unsigned char ByteArray_readUnsignedByte(struct ByteArray
* self
) {
261 unsigned char intval
;
263 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
267 signed char ByteArray_readByte(struct ByteArray
* self
) {
271 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
275 /* equivalent to foo = self[x]; (pos stays unchanged) */
276 unsigned char ByteArray_getUnsignedByte(struct ByteArray
* self
, off_t index
) {
277 //assert_op(self->type, ==, BAT_MEMSTREAM);
278 assert_op(index
, <, self
->size
);
279 if(self
->type
== BAT_MEMSTREAM
) {
280 assert_op(self
->start_addr
, !=, 0);
281 return (self
->start_addr
[index
]);
283 off_t save
= self
->pos
;
285 ByteArray_set_position(self
, index
);
286 res
= ByteArray_readUnsignedByte(self
);
287 ByteArray_set_position(self
, save
);
292 /* equivalent to self[x] = what (pos stays unchanged) */
293 void ByteArray_setUnsignedByte(struct ByteArray
* self
, off_t index
, unsigned char what
) {
294 off_t save
= self
->pos
;
295 if(ByteArray_set_position(self
, index
)) {
296 ByteArray_writeUnsignedByte(self
, what
);
301 off_t
ByteArray_writeByte(struct ByteArray
* self
, signed char what
) {
302 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
305 off_t
ByteArray_writeUnsignedByte(struct ByteArray
* self
, unsigned char what
) {
306 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
309 off_t
ByteArray_writeShort(struct ByteArray
* self
, signed short what
) {
312 unsigned char charval
[sizeof(what
)];
315 if(self
->sys_endian
!= self
->endian
) {
316 u
.intval
= byteswap16(u
.intval
);
318 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
321 off_t
ByteArray_writeUnsignedShort(struct ByteArray
* self
, unsigned short what
) {
323 unsigned short intval
;
324 unsigned char charval
[sizeof(what
)];
327 if(self
->sys_endian
!= self
->endian
) {
328 u
.intval
= byteswap16(u
.intval
);
330 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
333 off_t
ByteArray_writeInt(struct ByteArray
* self
, signed int what
) {
336 unsigned char charval
[sizeof(what
)];
339 if(self
->sys_endian
!= self
->endian
) {
340 u
.intval
= byteswap32(u
.intval
);
342 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
345 off_t
ByteArray_writeUnsignedInt(struct ByteArray
* self
, unsigned int what
) {
348 unsigned char charval
[sizeof(what
)];
351 if(self
->sys_endian
!= self
->endian
) {
352 u
.intval
= byteswap32(u
.intval
);
354 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
357 off_t
ByteArray_writeMem(struct ByteArray
* self
, unsigned char* what
, size_t len
) {
358 if(self
->type
== BAT_FILESTREAM
) {
359 fprintf(stderr
, "tried to write to file!\n");
363 if((off_t
)(self
->pos
+ len
) > self
->size
) {
364 fprintf(stderr
, "oob write attempted");
368 assert_op(self
->start_addr
, !=, 0);
370 memcpy(&self
->start_addr
[self
->pos
], what
, len
);
375 off_t
ByteArray_writeUTFBytes(struct ByteArray
* self
, char* what
) {
376 return ByteArray_writeMem(self
, (unsigned char*) what
, strlen(what
));
379 // write contents of what into self
380 off_t
ByteArray_writeBytes(struct ByteArray
* self
, struct ByteArray
* what
) {
381 if(what
->type
== BAT_FILESTREAM
) {
382 fprintf(stderr
, "tried to write from non-memory stream\n");
386 return ByteArray_writeMem(self
, (unsigned char*) &what
->start_addr
[what
->pos
], what
->size
- what
->pos
);
390 off_t
ByteArray_writeFloat(struct ByteArray
* self
, float what
) {
394 unsigned char charval
[sizeof(what
)];
397 if(self
->sys_endian
!= self
->endian
) {
398 u
.intval
= byteswap32(u
.intval
);
400 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
403 void ByteArray_dump_to_file(struct ByteArray
* self
, char* filename
) {
404 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
405 int fd
= open(filename
, O_CREAT
| O_TRUNC
| O_WRONLY
, 0666);
406 write(fd
, self
->start_addr
, self
->size
);