1 /* ByteArray (C) 2012 rofl0r
3 * licensed under the LGPL 2.1+ */
7 #include "endianness.h"
14 #ifndef NO_MMAN /* lame OS like winblows */
18 #define mmap(...) (void*)0xffffffff
19 #define MAP_FAILED (void*)0xffffffff
23 void ByteArray_defaults(struct ByteArray
* self
) {
24 memset(self
, 0, sizeof(*self
));
27 void ByteArray_ctor(struct ByteArray
* self
) {
28 ByteArray_defaults(self
);
29 // original constructor code goes here
30 self
->readMultiByte
= ByteArray_readMultiByte
;
31 self
->readByte
= ByteArray_readByte
;
32 self
->readUnsignedByte
= ByteArray_readUnsignedByte
;
33 self
->readShort
= ByteArray_readShort
;
34 self
->readUnsignedShort
= ByteArray_readUnsignedShort
;
35 self
->readInt
= ByteArray_readInt
;
36 self
->readUnsignedInt
= ByteArray_readUnsignedInt
;
37 self
->readUnsignedLongLong
= ByteArray_readUnsignedLongLong
;
38 self
->readBytes
= ByteArray_readBytes
;
40 self
->writeInt
= ByteArray_writeInt
;
41 self
->writeUnsignedInt
= ByteArray_writeUnsignedInt
;
42 self
->writeShort
= ByteArray_writeShort
;
43 self
->writeUnsignedShort
= ByteArray_writeUnsignedShort
;
44 self
->writeByte
= ByteArray_writeByte
;
45 self
->writeUnsignedByte
= ByteArray_writeUnsignedByte
;;
46 self
->writeMem
= ByteArray_writeMem
;
47 self
->writeUTFBytes
= ByteArray_writeUTFBytes
;
48 self
->writeBytes
= ByteArray_writeBytes
;
49 self
->writeFloat
= ByteArray_writeFloat
;
51 self
->set_position
= ByteArray_set_position
;
52 self
->set_position_rel
= ByteArray_set_position_rel
;
53 self
->get_position
= ByteArray_get_position
;
55 self
->bytesAvailable
= ByteArray_bytesAvailable
;
57 self
->sys_endian
= ENDIANNESS_BE
? BAE_BIG
: BAE_LITTLE
;
60 struct ByteArray
* ByteArray_new(void) {
61 struct ByteArray
* self
= (struct ByteArray
*) malloc(sizeof(*self
));
62 if(self
) ByteArray_ctor(self
);
66 void ByteArray_set_endian(struct ByteArray
* self
, enum ByteArray_Endianess endian
) {
67 self
->endian
= endian
;
70 void ByteArray_set_flags(struct ByteArray
*self
, int flags
) {
74 enum ByteArray_Endianess
ByteArray_get_endian(struct ByteArray
* self
) {
78 // a real byte array clears the mem and resets
80 // where len is equivalent to the bytes written into it
81 //void* mem_getptr(MG* mem, size_t offset, size_t byteswanted);
82 void ByteArray_clear(struct ByteArray
* self
) {
83 fprintf(stderr
, "clear called\n");
84 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
85 void *p
= mem_getptr(&self
->source
.mem
, 0, self
->size
);
86 if(p
) memset(p
, 0, self
->size
);
89 void ByteArray_close(struct ByteArray
* self
) {
90 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
91 mem_free(&self
->source
.mem
);
94 off_t
ByteArray_get_position(struct ByteArray
* self
) {
98 static void seek_error() {
99 perror("seek error!\n");
103 static void neg_off() {
104 fprintf(stderr
, "negative seek attempted\n");
108 static void oob(const char *fn
, off_t want
, off_t have
) {
109 fprintf(stderr
, "%s: oob access attempted (want: %jd, have %jd)\n", fn
? fn
: "<unknown>", (intmax_t) want
, (intmax_t) have
);
114 void ByteArray_set_length(struct ByteArray
* self
, off_t len
) {
115 if(len
> self
->size
) {
116 oob(self
->filename
, len
, self
->size
);
122 off_t
ByteArray_get_length(struct ByteArray
* self
) {
126 int ByteArray_set_position_rel(struct ByteArray
* self
, int rel
) {
127 if((int) self
->pos
+ rel
< 0) {
131 return ByteArray_set_position(self
, self
->pos
+ rel
);
134 int ByteArray_set_position(struct ByteArray
* self
, off_t pos
) {
135 if(pos
== self
->pos
) return 1;
136 if(pos
> self
->size
) {
137 oob(self
->filename
, pos
, self
->size
);
141 if(self
->type
== BAT_FILESTREAM
) {
142 off_t ret
= lseek(self
->source
.fd
, pos
, SEEK_SET
);
143 if(ret
== (off_t
) -1) {
152 static void read_error() {
153 perror("read error!\n");
157 static void read_error_short() {
158 perror("read error (short)!\n");
162 int ByteArray_open_file(struct ByteArray
* self
, const char* filename
) {
164 self
->type
= BAT_FILESTREAM
;
167 if(stat(filename
, &st
) == -1) return 0;
168 self
->size
= st
.st_size
;
169 self
->filename
= filename
;
170 self
->source
.fd
= open(filename
, O_RDONLY
|O_BINARY
);
171 if (self
->source
.fd
== -1) return 0;
172 void *addr
= mmap(NULL
, self
->size
, PROT_READ
, MAP_PRIVATE
, self
->source
.fd
, 0);
173 if(addr
== MAP_FAILED
) {
174 if(!BLOWS
) perror("mmap");
177 return ByteArray_open_mem(self
, addr
, self
->size
);
180 void ByteArray_close_file(struct ByteArray
*self
) {
181 close(self
->source
.fd
);
182 self
->source
.fd
= -1;
185 int ByteArray_open_mem(struct ByteArray
* self
, char* data
, size_t size
) {
187 self
->type
= BAT_MEMSTREAM
;
188 mem_set(&self
->source
.mem
, data
, size
, size
);
192 ssize_t
ByteArray_readMultiByte(struct ByteArray
* self
, char* buffer
, size_t len
) {
193 if(self
->type
== BAT_MEMSTREAM
) {
194 assert_op((size_t) self
->pos
+ len
, <=, (size_t) self
->size
);
195 void *p
= mem_getptr(&self
->source
.mem
, self
->pos
, len
);
196 if(p
) memcpy(buffer
, p
, len
);
199 ssize_t ret
= read(self
->source
.fd
, buffer
, len
);
203 } else if((size_t) ret
!= len
) {
213 // write contents of self into dest
214 // if len == 0 all available bytes are used.
215 // self->pos is considered the start offset to use for self.
216 // the position in dest will not be advanced.
217 // the position in source will be advanced len bytes.
218 // returns the number of bytes written
219 off_t
ByteArray_readBytes(struct ByteArray
* self
, struct ByteArray
*dest
, off_t start
, off_t len
) {
220 off_t left
= self
->size
- self
->pos
;
221 if(len
== 0) len
= left
;
222 else if(len
> left
) {
223 oob(self
->filename
, len
, left
);
226 if(len
== 0) return 0;
227 else if (len
> start
+ dest
->size
) {
228 oob(self
->filename
, len
, start
+ dest
->size
);
229 len
= start
+ dest
->size
;
230 if(len
== 0) return 0;
232 if(dest
->type
!= BAT_MEMSTREAM
) {
235 void *p
= mem_getptr(&dest
->source
.mem
, start
, len
);
236 if(p
) self
->readMultiByte(self
, p
, len
);
241 off_t
ByteArray_bytesAvailable(struct ByteArray
* self
) {
242 if(self
->pos
< self
->size
) return self
->size
- self
->pos
;
246 unsigned long long ByteArray_readUnsignedLongLong(struct ByteArray
* self
) {
248 unsigned long long intval
;
249 unsigned char charval
[sizeof(unsigned long long)];
251 self
->readMultiByte(self
, (char*) buf
.charval
, 8);
252 if(self
->endian
!= self
->sys_endian
) {
253 buf
.intval
= end_bswap64(buf
.intval
);
258 unsigned int ByteArray_readUnsignedInt(struct ByteArray
* self
) {
261 unsigned char charval
[sizeof(unsigned int)];
263 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
264 if(self
->endian
!= self
->sys_endian
) {
265 buf
.intval
= end_bswap32(buf
.intval
);
270 int ByteArray_readInt(struct ByteArray
* self
) {
273 unsigned char charval
[sizeof(unsigned int)];
275 self
->readMultiByte(self
, (char*) buf
.charval
, 4);
276 if(self
->endian
!= self
->sys_endian
) {
277 buf
.intval
= end_bswap32(buf
.intval
);
282 unsigned short ByteArray_readUnsignedShort(struct ByteArray
* self
) {
284 unsigned short intval
;
285 unsigned char charval
[sizeof(unsigned short)];
287 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
288 if(self
->endian
!= self
->sys_endian
) {
289 buf
.intval
= end_bswap16(buf
.intval
);
294 short ByteArray_readShort(struct ByteArray
* self
) {
296 unsigned short intval
;
297 unsigned char charval
[sizeof(unsigned short)];
299 self
->readMultiByte(self
, (char*) buf
.charval
, 2);
300 if(self
->endian
!= self
->sys_endian
) {
301 buf
.intval
= end_bswap16(buf
.intval
);
306 unsigned char ByteArray_readUnsignedByte(struct ByteArray
* self
) {
308 unsigned char intval
;
310 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
314 signed char ByteArray_readByte(struct ByteArray
* self
) {
318 self
->readMultiByte(self
, (char*) &buf
.intval
, 1);
322 /* equivalent to foo = self[x]; (pos stays unchanged) */
323 unsigned char ByteArray_getUnsignedByte(struct ByteArray
* self
, off_t index
) {
324 //assert_op(self->type, ==, BAT_MEMSTREAM);
325 assert_op(index
, <, self
->size
);
326 off_t save
= self
->pos
;
328 ByteArray_set_position(self
, index
);
329 res
= ByteArray_readUnsignedByte(self
);
330 ByteArray_set_position(self
, save
);
334 /* equivalent to self[x] = what (pos stays unchanged) */
335 void ByteArray_setUnsignedByte(struct ByteArray
* self
, off_t index
, unsigned char what
) {
336 off_t save
= self
->pos
;
337 if(ByteArray_set_position(self
, index
)) {
338 ByteArray_writeUnsignedByte(self
, what
);
343 off_t
ByteArray_writeByte(struct ByteArray
* self
, signed char what
) {
344 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
347 off_t
ByteArray_writeUnsignedByte(struct ByteArray
* self
, unsigned char what
) {
348 return ByteArray_writeMem(self
, (unsigned char*) &what
, 1);
351 off_t
ByteArray_writeShort(struct ByteArray
* self
, signed short what
) {
354 unsigned char charval
[sizeof(what
)];
357 if(self
->sys_endian
!= self
->endian
) {
358 u
.intval
= end_bswap16(u
.intval
);
360 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
363 off_t
ByteArray_writeUnsignedShort(struct ByteArray
* self
, unsigned short what
) {
365 unsigned short intval
;
366 unsigned char charval
[sizeof(what
)];
369 if(self
->sys_endian
!= self
->endian
) {
370 u
.intval
= end_bswap16(u
.intval
);
372 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
375 off_t
ByteArray_writeInt(struct ByteArray
* self
, signed int what
) {
378 unsigned char charval
[sizeof(what
)];
381 if(self
->sys_endian
!= self
->endian
) {
382 u
.intval
= end_bswap32(u
.intval
);
384 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
387 off_t
ByteArray_writeUnsignedInt(struct ByteArray
* self
, unsigned int what
) {
390 unsigned char charval
[sizeof(what
)];
393 if(self
->sys_endian
!= self
->endian
) {
394 u
.intval
= end_bswap32(u
.intval
);
396 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
399 off_t
ByteArray_writeMem(struct ByteArray
* self
, unsigned char* what
, size_t len
) {
400 if(self
->type
== BAT_FILESTREAM
) {
401 fprintf(stderr
, "tried to write to file!\n");
405 if(!(self
->flags
& BAF_CANGROW
) && (size_t) self
->pos
+ len
> (size_t) self
->size
) {
406 fprintf(stderr
, "oob write attempted");
411 if(mem_write(&self
->source
.mem
, self
->pos
, what
, len
)) {
413 if(self
->pos
> self
->size
) self
->size
= self
->pos
; /* apparently CANGROW was used */
418 off_t
ByteArray_writeUTFBytes(struct ByteArray
* self
, char* what
) {
419 return ByteArray_writeMem(self
, (unsigned char*) what
, strlen(what
));
422 // write contents of what into self
423 off_t
ByteArray_writeBytes(struct ByteArray
* self
, struct ByteArray
* what
) {
424 if(what
->type
== BAT_FILESTREAM
) {
425 fprintf(stderr
, "tried to write from non-memory stream\n");
429 unsigned char* p
= mem_getptr(&what
->source
.mem
, what
->pos
, what
->size
- what
->pos
);
431 return ByteArray_writeMem(self
, p
, what
->size
- what
->pos
);
436 off_t
ByteArray_writeFloat(struct ByteArray
* self
, float what
) {
440 unsigned char charval
[sizeof(what
)];
443 if(self
->sys_endian
!= self
->endian
) {
444 u
.intval
= end_bswap32(u
.intval
);
446 return ByteArray_writeMem(self
, u
.charval
, sizeof(what
));
449 void ByteArray_dump_to_stream(struct ByteArray
* self
, FILE *out
) {
450 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
451 mem_write_stream(&self
->source
.mem
, out
);
454 void ByteArray_dump_to_file(struct ByteArray
* self
, char* filename
) {
455 assert_op(self
->type
, ==, BAT_MEMSTREAM
);
456 mem_write_file(&self
->source
.mem
, filename
);