add support for RcB2 build sys
[rofl0r-c-flod.git] / flashlib / ByteArray.c
blob242216d57a62d77a346ce1a7119dabf00dd24e94
1 #include "ByteArray.h"
2 #include "../include/debug.h"
3 #include "../include/endianness.h"
4 #include <stdlib.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;
41 #else
42 self->sys_endian = BAE_BIG;
43 #endif
46 struct ByteArray* ByteArray_new(void) {
47 struct ByteArray* self = (struct ByteArray*) malloc(sizeof(*self));
48 if(self) ByteArray_ctor(self);
49 return 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) {
57 return self->endian;
60 // a real byte array clears the mem and resets
61 // "len" and pos to 0
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) {
71 return self->pos;
74 static void seek_error() {
75 perror("seek error!\n");
76 assert_dbg(0);
79 static void neg_off() {
80 fprintf(stderr, "negative seek attempted\n");
81 assert_dbg(0);
84 static void oob() {
85 fprintf(stderr, "oob access attempted\n");
86 assert_dbg(0);
89 void ByteArray_set_length(struct ByteArray* self, off_t len) {
90 if(len > self->size) {
91 oob();
92 return;
94 self->size = len;
97 off_t ByteArray_get_length(struct ByteArray* self) {
98 return self->size;
101 int ByteArray_set_position_rel(struct ByteArray* self, int rel) {
102 if((int) self->pos + rel < 0) {
103 neg_off();
104 rel = -self->pos;
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) {
112 oob();
113 return 0;
116 if(self->type == BAT_FILESTREAM) {
117 off_t ret = lseek(self->fd, pos, SEEK_SET);
118 if(ret == (off_t) -1) {
119 seek_error();
120 return 0;
123 self->pos = pos;
124 return 1;
127 static void read_error() {
128 perror("read error!\n");
129 assert_dbg(0);
132 static void read_error_short() {
133 perror("read error (short)!\n");
134 assert_dbg(0);
137 int ByteArray_open_file(struct ByteArray* self, const char* filename) {
138 struct stat st;
139 self->type = BAT_FILESTREAM;
140 self->pos = 0;
141 self->size = 0;
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) {
149 close(self->fd);
150 self->fd = -1;
153 int ByteArray_open_mem(struct ByteArray* self, char* data, size_t size) {
154 self->pos = 0;
155 self->size = size;
156 self->type = BAT_MEMSTREAM;
157 self->start_addr = data;
158 return 1;
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);
166 } else {
167 ssize_t ret = read(self->fd, buffer, len);
168 if(ret == -1) {
169 read_error();
170 return;
171 } else if(ret != (ssize_t) len) {
172 read_error_short();
173 self->pos += len;
174 return;
177 self->pos += 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) {
190 oob();
191 len = left;
193 if(len == 0) return 0;
194 else if (len > start + dest->size) {
195 oob();
196 len = start + dest->size;
197 if(len == 0) return 0;
199 if(dest->type != BAT_MEMSTREAM) {
200 assert_dbg(0);
202 self->readMultiByte(self, &dest->start_addr[start], len);
203 return len;
206 off_t ByteArray_bytesAvailable(struct ByteArray* self) {
207 if(self->pos < self->size) return self->size - self->pos;
208 return 0;
211 unsigned int ByteArray_readUnsignedInt(struct ByteArray* self) {
212 union {
213 unsigned int intval;
214 unsigned char charval[sizeof(unsigned int)];
215 } buf;
216 self->readMultiByte(self, (char*) buf.charval, 4);
217 if(self->endian != self->sys_endian) {
218 buf.intval = byteswap32(buf.intval);
220 return buf.intval;
223 int ByteArray_readInt(struct ByteArray* self) {
224 union {
225 unsigned int intval;
226 unsigned char charval[sizeof(unsigned int)];
227 } buf;
228 self->readMultiByte(self, (char*) buf.charval, 4);
229 if(self->endian != self->sys_endian) {
230 buf.intval = byteswap32(buf.intval);
232 return buf.intval;
235 unsigned short ByteArray_readUnsignedShort(struct ByteArray* self) {
236 union {
237 unsigned short intval;
238 unsigned char charval[sizeof(unsigned short)];
239 } buf;
240 self->readMultiByte(self, (char*) buf.charval, 2);
241 if(self->endian != self->sys_endian) {
242 buf.intval = byteswap16(buf.intval);
244 return buf.intval;
247 short ByteArray_readShort(struct ByteArray* self) {
248 union {
249 unsigned short intval;
250 unsigned char charval[sizeof(unsigned short)];
251 } buf;
252 self->readMultiByte(self, (char*) buf.charval, 2);
253 if(self->endian != self->sys_endian) {
254 buf.intval = byteswap16(buf.intval);
256 return buf.intval;
259 unsigned char ByteArray_readUnsignedByte(struct ByteArray* self) {
260 union {
261 unsigned char intval;
262 } buf;
263 self->readMultiByte(self, (char*) &buf.intval, 1);
264 return buf.intval;
267 signed char ByteArray_readByte(struct ByteArray* self) {
268 union {
269 signed char intval;
270 } buf;
271 self->readMultiByte(self, (char*) &buf.intval, 1);
272 return buf.intval;
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]);
282 } else {
283 off_t save = self->pos;
284 unsigned char res;
285 ByteArray_set_position(self, index);
286 res = ByteArray_readUnsignedByte(self);
287 ByteArray_set_position(self, save);
288 return res;
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);
297 self->pos = save;
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) {
310 union {
311 short intval;
312 unsigned char charval[sizeof(what)];
313 } u;
314 u.intval = 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) {
322 union {
323 unsigned short intval;
324 unsigned char charval[sizeof(what)];
325 } u;
326 u.intval = 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) {
334 union {
335 int intval;
336 unsigned char charval[sizeof(what)];
337 } u;
338 u.intval = 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) {
346 union {
347 unsigned int intval;
348 unsigned char charval[sizeof(what)];
349 } u;
350 u.intval = 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");
360 assert_dbg(0);
361 return 0;
363 if((off_t)(self->pos + len) > self->size) {
364 fprintf(stderr, "oob write attempted");
365 assert_dbg(0);
366 return 0;
368 assert_op(self->start_addr, !=, 0);
370 memcpy(&self->start_addr[self->pos], what, len);
371 self->pos += len;
372 return 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");
383 assert_dbg(0);
384 return 0;
385 } else {
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) {
391 union {
392 float floatval;
393 unsigned int intval;
394 unsigned char charval[sizeof(what)];
395 } u;
396 u.floatval = 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);
407 close(fd);