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
->readBytes
= ByteArray_readBytes
;
27 self
->writeInt
= ByteArray_writeInt
;
28 self
->writeUnsignedInt
= ByteArray_writeUnsignedInt
;
29 self
->writeShort
= ByteArray_writeShort
;
30 self
->writeUnsignedShort
= ByteArray_writeUnsignedShort
;
31 self
->writeByte
= ByteArray_writeByte
;
32 self
->writeUnsignedByte
= ByteArray_writeUnsignedByte
;;
33 self
->writeMem
= ByteArray_writeMem
;
34 self
->writeUTFBytes
= ByteArray_writeUTFBytes
;
35 self
->writeBytes
= ByteArray_writeBytes
;
36 self
->writeFloat
= ByteArray_writeFloat
;
38 self
->set_position
= ByteArray_set_position
;
39 self
->set_position_rel
= ByteArray_set_position_rel
;
40 self
->get_position
= ByteArray_get_position
;
42 self
->bytesAvailable
= ByteArray_bytesAvailable
;
44 #ifdef IS_LITTLE_ENDIAN
45 self
->sys_endian
= BAE_LITTLE
;
47 self
->sys_endian
= BAE_BIG
;
51 struct ByteArray
* ByteArray_new(void) {
52 struct ByteArray
* self
= (struct ByteArray
*) malloc(sizeof(*self
));
53 if(self
) ByteArray_ctor(self
);
57 void ByteArray_set_endian(struct ByteArray
* self
, enum ByteArray_Endianess endian
) {
58 self
->endian
= endian
;
61 void ByteArray_set_flags(struct ByteArray
*self
, int flags
) {
65 enum ByteArray_Endianess
ByteArray_get_endian(struct ByteArray
* self
) {
69 // a real byte array clears the mem and resets
71 // where len is equivalent to the bytes written into it
72 //void* mem_getptr(MG* mem, size_t offset, size_t byteswanted);
73 void ByteArray_clear(struct ByteArray
* self
) {
74 fprintf(stderr
, "clear called\n");
75 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
76 void *p
= mem_getptr(&self
->source
.mem
, 0, self
->size
);
77 if(p
) memset(p
, 0, self
->size
);
80 void ByteArray_close(struct ByteArray
* self
) {
81 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
82 mem_free(&self
->source
.mem
);
85 off_t
ByteArray_get_position(struct ByteArray
* self
) {
89 static void seek_error() {
90 perror("seek error!\n");
94 static void neg_off() {
95 fprintf(stderr
, "negative seek attempted\n");
100 fprintf(stderr
, "oob access attempted\n");
104 void ByteArray_set_length(struct ByteArray
* self
, off_t len
) {
105 if(len
> self
->size
) {
112 off_t
ByteArray_get_length(struct ByteArray
* self
) {
116 int ByteArray_set_position_rel(struct ByteArray
* self
, int rel
) {
117 if((int) self
->pos
+ rel
< 0) {
121 return ByteArray_set_position(self
, self
->pos
+ rel
);
124 int ByteArray_set_position(struct ByteArray
* self
, off_t pos
) {
125 if(pos
== self
->pos
) return 1;
126 if(pos
> self
->size
) {
131 if(self
->type
== BAT_FILESTREAM
) {
132 off_t ret
= lseek(self
->source
.fd
, pos
, SEEK_SET
);
133 if(ret
== (off_t
) -1) {
142 static void read_error() {
143 perror("read error!\n");
147 static void read_error_short() {
148 perror("read error (short)!\n");
152 int ByteArray_open_file(struct ByteArray
* self
, const char* filename
) {
154 self
->type
= BAT_FILESTREAM
;
157 if(stat(filename
, &st
) == -1) return 0;
158 self
->size
= st
.st_size
;
159 self
->source
.fd
= open(filename
, O_RDONLY
);
160 if (self
->source
.fd
== -1) return 0;
161 void *addr
= mmap(NULL
, self
->size
, PROT_READ
, MAP_PRIVATE
, self
->source
.fd
, 0);
162 if(addr
== MAP_FAILED
) {
166 return ByteArray_open_mem(self
, addr
, self
->size
);
169 void ByteArray_close_file(struct ByteArray
*self
) {
170 close(self
->source
.fd
);
171 self
->source
.fd
= -1;
174 int ByteArray_open_mem(struct ByteArray
* self
, char* data
, size_t size
) {
176 self
->type
= BAT_MEMSTREAM
;
177 mem_set(&self
->source
.mem
, data
, size
, size
);
181 ssize_t
ByteArray_readMultiByte(struct ByteArray
* self
, char* buffer
, size_t len
) {
182 if(self
->type
== BAT_MEMSTREAM
) {
183 assert_op((size_t) self
->pos
+ len
, <=, (size_t) self
->size
);
184 void *p
= mem_getptr(&self
->source
.mem
, self
->pos
, len
);
185 if(p
) memcpy(buffer
, p
, len
);
188 ssize_t ret
= read(self
->source
.fd
, buffer
, len
);
192 } else if((size_t) ret
!= len
) {
202 // write contents of self into dest
203 // if len == 0 all available bytes are used.
204 // self->pos is considered the start offset to use for self.
205 // the position in dest will not be advanced.
206 // the position in source will be advanced len bytes.
207 // returns the number of bytes written
208 off_t
ByteArray_readBytes(struct ByteArray
* self
, struct ByteArray
*dest
, off_t start
, off_t len
) {
209 off_t left
= self
->size
- self
->pos
;
210 if(len
== 0) len
= left
;
211 else if(len
> left
) {
215 if(len
== 0) return 0;
216 else if (len
> start
+ dest
->size
) {
218 len
= start
+ dest
->size
;
219 if(len
== 0) return 0;
221 if(dest
->type
!= BAT_MEMSTREAM
) {
224 void *p
= mem_getptr(&dest
->source
.mem
, start
, len
);
225 if(p
) self
->readMultiByte(self
, p
, len
);
230 off_t
ByteArray_bytesAvailable(struct ByteArray
* self
) {
231 if(self
->pos
< self
->size
) return self
->size
- self
->pos
;
235 unsigned int ByteArray_readUnsignedInt(struct ByteArray
* self
) {
238 unsigned char charval
[sizeof(unsigned int)];
240 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
241 if(self
->endian
!= self
->sys_endian
) {
242 buf
.intval
= byteswap32(buf
.intval
);
247 int ByteArray_readInt(struct ByteArray
* self
) {
250 unsigned char charval
[sizeof(unsigned int)];
252 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
253 if(self
->endian
!= self
->sys_endian
) {
254 buf
.intval
= byteswap32(buf
.intval
);
259 unsigned short ByteArray_readUnsignedShort(struct ByteArray
* self
) {
261 unsigned short intval
;
262 unsigned char charval
[sizeof(unsigned short)];
264 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
265 if(self
->endian
!= self
->sys_endian
) {
266 buf
.intval
= byteswap16(buf
.intval
);
271 short ByteArray_readShort(struct ByteArray
* self
) {
273 unsigned short intval
;
274 unsigned char charval
[sizeof(unsigned short)];
276 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
277 if(self
->endian
!= self
->sys_endian
) {
278 buf
.intval
= byteswap16(buf
.intval
);
283 unsigned char ByteArray_readUnsignedByte(struct ByteArray
* self
) {
285 unsigned char intval
;
287 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
291 signed char ByteArray_readByte(struct ByteArray
* self
) {
295 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
299 /* equivalent to foo = self[x]; (pos stays unchanged) */
300 unsigned char ByteArray_getUnsignedByte(struct ByteArray
* self
, off_t index
) {
301 //assert_op(self->type, ==, BAT_MEMSTREAM);
302 assert_op(index
, <, self
->size
);
303 off_t save
= self
->pos
;
305 ByteArray_set_position(self
, index
);
306 res
= ByteArray_readUnsignedByte(self
);
307 ByteArray_set_position(self
, save
);
311 /* equivalent to self[x] = what (pos stays unchanged) */
312 void ByteArray_setUnsignedByte(struct ByteArray
* self
, off_t index
, unsigned char what
) {
313 off_t save
= self
->pos
;
314 if(ByteArray_set_position(self
, index
)) {
315 ByteArray_writeUnsignedByte(self
, what
);
320 off_t
ByteArray_writeByte(struct ByteArray
* self
, signed char what
) {
321 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
324 off_t
ByteArray_writeUnsignedByte(struct ByteArray
* self
, unsigned char what
) {
325 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
328 off_t
ByteArray_writeShort(struct ByteArray
* self
, signed short what
) {
331 unsigned char charval
[sizeof(what
)];
334 if(self
->sys_endian
!= self
->endian
) {
335 u
.intval
= byteswap16(u
.intval
);
337 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
340 off_t
ByteArray_writeUnsignedShort(struct ByteArray
* self
, unsigned short what
) {
342 unsigned short intval
;
343 unsigned char charval
[sizeof(what
)];
346 if(self
->sys_endian
!= self
->endian
) {
347 u
.intval
= byteswap16(u
.intval
);
349 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
352 off_t
ByteArray_writeInt(struct ByteArray
* self
, signed int what
) {
355 unsigned char charval
[sizeof(what
)];
358 if(self
->sys_endian
!= self
->endian
) {
359 u
.intval
= byteswap32(u
.intval
);
361 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
364 off_t
ByteArray_writeUnsignedInt(struct ByteArray
* self
, unsigned int what
) {
367 unsigned char charval
[sizeof(what
)];
370 if(self
->sys_endian
!= self
->endian
) {
371 u
.intval
= byteswap32(u
.intval
);
373 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
376 off_t
ByteArray_writeMem(struct ByteArray
* self
, unsigned char* what
, size_t len
) {
377 if(self
->type
== BAT_FILESTREAM
) {
378 fprintf(stderr
, "tried to write to file!\n");
382 if(!(self
->flags
& BAF_CANGROW
) && (size_t) self
->pos
+ len
> (size_t) self
->size
) {
383 fprintf(stderr
, "oob write attempted");
388 if(mem_write(&self
->source
.mem
, self
->pos
, what
, len
)) {
390 if(self
->pos
> self
->size
) self
->size
= self
->pos
; /* apparently CANGROW was used */
395 off_t
ByteArray_writeUTFBytes(struct ByteArray
* self
, char* what
) {
396 return ByteArray_writeMem(self
, (unsigned char*) what
, strlen(what
));
399 // write contents of what into self
400 off_t
ByteArray_writeBytes(struct ByteArray
* self
, struct ByteArray
* what
) {
401 if(what
->type
== BAT_FILESTREAM
) {
402 fprintf(stderr
, "tried to write from non-memory stream\n");
406 unsigned char* p
= mem_getptr(&what
->source
.mem
, what
->pos
, what
->size
- what
->pos
);
408 return ByteArray_writeMem(self
, p
, what
->size
- what
->pos
);
413 off_t
ByteArray_writeFloat(struct ByteArray
* self
, float what
) {
417 unsigned char charval
[sizeof(what
)];
420 if(self
->sys_endian
!= self
->endian
) {
421 u
.intval
= byteswap32(u
.intval
);
423 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
426 void ByteArray_dump_to_stream(struct ByteArray
* self
, FILE *out
) {
427 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
428 mem_write_stream(&self
->source
.mem
, out
);
431 void ByteArray_dump_to_file(struct ByteArray
* self
, char* filename
) {
432 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
433 mem_write_file(&self
->source
.mem
, filename
);