1 /* ByteArray (C) 2012 rofl0r
3 * licensed under the LGPL 2.1+ */
7 #include "endianness.h"
11 void ByteArray_defaults(struct ByteArray
* self
) {
12 memset(self
, 0, sizeof(*self
));
15 void ByteArray_ctor(struct ByteArray
* self
) {
16 ByteArray_defaults(self
);
17 // original constructor code goes here
18 self
->readMultiByte
= ByteArray_readMultiByte
;
19 self
->readByte
= ByteArray_readByte
;
20 self
->readUnsignedByte
= ByteArray_readUnsignedByte
;
21 self
->readShort
= ByteArray_readShort
;
22 self
->readUnsignedShort
= ByteArray_readUnsignedShort
;
23 self
->readInt
= ByteArray_readInt
;
24 self
->readUnsignedInt
= ByteArray_readUnsignedInt
;
25 self
->readUnsignedLongLong
= ByteArray_readUnsignedLongLong
;
26 self
->readBytes
= ByteArray_readBytes
;
28 self
->writeInt
= ByteArray_writeInt
;
29 self
->writeUnsignedInt
= ByteArray_writeUnsignedInt
;
30 self
->writeShort
= ByteArray_writeShort
;
31 self
->writeUnsignedShort
= ByteArray_writeUnsignedShort
;
32 self
->writeByte
= ByteArray_writeByte
;
33 self
->writeUnsignedByte
= ByteArray_writeUnsignedByte
;;
34 self
->writeMem
= ByteArray_writeMem
;
35 self
->writeUTFBytes
= ByteArray_writeUTFBytes
;
36 self
->writeBytes
= ByteArray_writeBytes
;
37 self
->writeFloat
= ByteArray_writeFloat
;
39 self
->set_position
= ByteArray_set_position
;
40 self
->set_position_rel
= ByteArray_set_position_rel
;
41 self
->get_position
= ByteArray_get_position
;
43 self
->bytesAvailable
= ByteArray_bytesAvailable
;
45 #ifdef IS_LITTLE_ENDIAN
46 self
->sys_endian
= BAE_LITTLE
;
48 self
->sys_endian
= BAE_BIG
;
52 struct ByteArray
* ByteArray_new(void) {
53 struct ByteArray
* self
= (struct ByteArray
*) malloc(sizeof(*self
));
54 if(self
) ByteArray_ctor(self
);
58 void ByteArray_set_endian(struct ByteArray
* self
, enum ByteArray_Endianess endian
) {
59 self
->endian
= endian
;
62 void ByteArray_set_flags(struct ByteArray
*self
, int flags
) {
66 enum ByteArray_Endianess
ByteArray_get_endian(struct ByteArray
* self
) {
70 // a real byte array clears the mem and resets
72 // where len is equivalent to the bytes written into it
73 //void* mem_getptr(MG* mem, size_t offset, size_t byteswanted);
74 void ByteArray_clear(struct ByteArray
* self
) {
75 fprintf(stderr
, "clear called\n");
76 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
77 void *p
= mem_getptr(&self
->source
.mem
, 0, self
->size
);
78 if(p
) memset(p
, 0, self
->size
);
81 void ByteArray_close(struct ByteArray
* self
) {
82 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
83 mem_free(&self
->source
.mem
);
86 off_t
ByteArray_get_position(struct ByteArray
* self
) {
90 static void seek_error() {
91 perror("seek error!\n");
95 static void neg_off() {
96 fprintf(stderr
, "negative seek attempted\n");
101 fprintf(stderr
, "oob access attempted\n");
105 void ByteArray_set_length(struct ByteArray
* self
, off_t len
) {
106 if(len
> self
->size
) {
113 off_t
ByteArray_get_length(struct ByteArray
* self
) {
117 int ByteArray_set_position_rel(struct ByteArray
* self
, int rel
) {
118 if((int) self
->pos
+ rel
< 0) {
122 return ByteArray_set_position(self
, self
->pos
+ rel
);
125 int ByteArray_set_position(struct ByteArray
* self
, off_t pos
) {
126 if(pos
== self
->pos
) return 1;
127 if(pos
> self
->size
) {
132 if(self
->type
== BAT_FILESTREAM
) {
133 off_t ret
= lseek(self
->source
.fd
, pos
, SEEK_SET
);
134 if(ret
== (off_t
) -1) {
143 static void read_error() {
144 perror("read error!\n");
148 static void read_error_short() {
149 perror("read error (short)!\n");
153 int ByteArray_open_file(struct ByteArray
* self
, const char* filename
) {
155 self
->type
= BAT_FILESTREAM
;
158 if(stat(filename
, &st
) == -1) return 0;
159 self
->size
= st
.st_size
;
160 self
->source
.fd
= open(filename
, O_RDONLY
);
161 if (self
->source
.fd
== -1) return 0;
162 void *addr
= mmap(NULL
, self
->size
, PROT_READ
, MAP_PRIVATE
, self
->source
.fd
, 0);
163 if(addr
== MAP_FAILED
) {
167 return ByteArray_open_mem(self
, addr
, self
->size
);
170 void ByteArray_close_file(struct ByteArray
*self
) {
171 close(self
->source
.fd
);
172 self
->source
.fd
= -1;
175 int ByteArray_open_mem(struct ByteArray
* self
, char* data
, size_t size
) {
177 self
->type
= BAT_MEMSTREAM
;
178 mem_set(&self
->source
.mem
, data
, size
, size
);
182 ssize_t
ByteArray_readMultiByte(struct ByteArray
* self
, char* buffer
, size_t len
) {
183 if(self
->type
== BAT_MEMSTREAM
) {
184 assert_op((size_t) self
->pos
+ len
, <=, (size_t) self
->size
);
185 void *p
= mem_getptr(&self
->source
.mem
, self
->pos
, len
);
186 if(p
) memcpy(buffer
, p
, len
);
189 ssize_t ret
= read(self
->source
.fd
, buffer
, len
);
193 } else if((size_t) ret
!= len
) {
203 // write contents of self into dest
204 // if len == 0 all available bytes are used.
205 // self->pos is considered the start offset to use for self.
206 // the position in dest will not be advanced.
207 // the position in source will be advanced len bytes.
208 // returns the number of bytes written
209 off_t
ByteArray_readBytes(struct ByteArray
* self
, struct ByteArray
*dest
, off_t start
, off_t len
) {
210 off_t left
= self
->size
- self
->pos
;
211 if(len
== 0) len
= left
;
212 else if(len
> left
) {
216 if(len
== 0) return 0;
217 else if (len
> start
+ dest
->size
) {
219 len
= start
+ dest
->size
;
220 if(len
== 0) return 0;
222 if(dest
->type
!= BAT_MEMSTREAM
) {
225 void *p
= mem_getptr(&dest
->source
.mem
, start
, len
);
226 if(p
) self
->readMultiByte(self
, p
, len
);
231 off_t
ByteArray_bytesAvailable(struct ByteArray
* self
) {
232 if(self
->pos
< self
->size
) return self
->size
- self
->pos
;
236 unsigned long long ByteArray_readUnsignedLongLong(struct ByteArray
* self
) {
238 unsigned long long intval
;
239 unsigned char charval
[sizeof(unsigned long long)];
241 self
->readMultiByte(self
, (char*) buf
.charval
, 8);
242 if(self
->endian
!= self
->sys_endian
) {
243 buf
.intval
= byteswap64(buf
.intval
);
248 unsigned int ByteArray_readUnsignedInt(struct ByteArray
* self
) {
251 unsigned char charval
[sizeof(unsigned int)];
253 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
254 if(self
->endian
!= self
->sys_endian
) {
255 buf
.intval
= byteswap32(buf
.intval
);
260 int ByteArray_readInt(struct ByteArray
* self
) {
263 unsigned char charval
[sizeof(unsigned int)];
265 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
266 if(self
->endian
!= self
->sys_endian
) {
267 buf
.intval
= byteswap32(buf
.intval
);
272 unsigned short ByteArray_readUnsignedShort(struct ByteArray
* self
) {
274 unsigned short intval
;
275 unsigned char charval
[sizeof(unsigned short)];
277 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
278 if(self
->endian
!= self
->sys_endian
) {
279 buf
.intval
= byteswap16(buf
.intval
);
284 short ByteArray_readShort(struct ByteArray
* self
) {
286 unsigned short intval
;
287 unsigned char charval
[sizeof(unsigned short)];
289 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
290 if(self
->endian
!= self
->sys_endian
) {
291 buf
.intval
= byteswap16(buf
.intval
);
296 unsigned char ByteArray_readUnsignedByte(struct ByteArray
* self
) {
298 unsigned char intval
;
300 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
304 signed char ByteArray_readByte(struct ByteArray
* self
) {
308 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
312 /* equivalent to foo = self[x]; (pos stays unchanged) */
313 unsigned char ByteArray_getUnsignedByte(struct ByteArray
* self
, off_t index
) {
314 //assert_op(self->type, ==, BAT_MEMSTREAM);
315 assert_op(index
, <, self
->size
);
316 off_t save
= self
->pos
;
318 ByteArray_set_position(self
, index
);
319 res
= ByteArray_readUnsignedByte(self
);
320 ByteArray_set_position(self
, save
);
324 /* equivalent to self[x] = what (pos stays unchanged) */
325 void ByteArray_setUnsignedByte(struct ByteArray
* self
, off_t index
, unsigned char what
) {
326 off_t save
= self
->pos
;
327 if(ByteArray_set_position(self
, index
)) {
328 ByteArray_writeUnsignedByte(self
, what
);
333 off_t
ByteArray_writeByte(struct ByteArray
* self
, signed char what
) {
334 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
337 off_t
ByteArray_writeUnsignedByte(struct ByteArray
* self
, unsigned char what
) {
338 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
341 off_t
ByteArray_writeShort(struct ByteArray
* self
, signed short what
) {
344 unsigned char charval
[sizeof(what
)];
347 if(self
->sys_endian
!= self
->endian
) {
348 u
.intval
= byteswap16(u
.intval
);
350 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
353 off_t
ByteArray_writeUnsignedShort(struct ByteArray
* self
, unsigned short what
) {
355 unsigned short intval
;
356 unsigned char charval
[sizeof(what
)];
359 if(self
->sys_endian
!= self
->endian
) {
360 u
.intval
= byteswap16(u
.intval
);
362 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
365 off_t
ByteArray_writeInt(struct ByteArray
* self
, signed int what
) {
368 unsigned char charval
[sizeof(what
)];
371 if(self
->sys_endian
!= self
->endian
) {
372 u
.intval
= byteswap32(u
.intval
);
374 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
377 off_t
ByteArray_writeUnsignedInt(struct ByteArray
* self
, unsigned int what
) {
380 unsigned char charval
[sizeof(what
)];
383 if(self
->sys_endian
!= self
->endian
) {
384 u
.intval
= byteswap32(u
.intval
);
386 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
389 off_t
ByteArray_writeMem(struct ByteArray
* self
, unsigned char* what
, size_t len
) {
390 if(self
->type
== BAT_FILESTREAM
) {
391 fprintf(stderr
, "tried to write to file!\n");
395 if(!(self
->flags
& BAF_CANGROW
) && (size_t) self
->pos
+ len
> (size_t) self
->size
) {
396 fprintf(stderr
, "oob write attempted");
401 if(mem_write(&self
->source
.mem
, self
->pos
, what
, len
)) {
403 if(self
->pos
> self
->size
) self
->size
= self
->pos
; /* apparently CANGROW was used */
408 off_t
ByteArray_writeUTFBytes(struct ByteArray
* self
, char* what
) {
409 return ByteArray_writeMem(self
, (unsigned char*) what
, strlen(what
));
412 // write contents of what into self
413 off_t
ByteArray_writeBytes(struct ByteArray
* self
, struct ByteArray
* what
) {
414 if(what
->type
== BAT_FILESTREAM
) {
415 fprintf(stderr
, "tried to write from non-memory stream\n");
419 unsigned char* p
= mem_getptr(&what
->source
.mem
, what
->pos
, what
->size
- what
->pos
);
421 return ByteArray_writeMem(self
, p
, what
->size
- what
->pos
);
426 off_t
ByteArray_writeFloat(struct ByteArray
* self
, float what
) {
430 unsigned char charval
[sizeof(what
)];
433 if(self
->sys_endian
!= self
->endian
) {
434 u
.intval
= byteswap32(u
.intval
);
436 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
439 void ByteArray_dump_to_stream(struct ByteArray
* self
, FILE *out
) {
440 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
441 mem_write_stream(&self
->source
.mem
, out
);
444 void ByteArray_dump_to_file(struct ByteArray
* self
, char* filename
) {
445 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
446 mem_write_file(&self
->source
.mem
, filename
);