1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "util.h"
5 #include "log.h"
6 #include <1541img/event.h>
7
8 #include <1541img/filedata.h>
9
10 #define FD_CHUNKSIZE 1024
11
12 struct FileData
13 {
14 size_t size;
15 size_t capacity;
16 Event *changedEvent;
17 uint8_t *content;
18 };
19
FileData_create(void)20 SOEXPORT FileData *FileData_create(void)
21 {
22 FileData *self = xmalloc(sizeof *self);
23 self->content = xmalloc(FD_CHUNKSIZE);
24 self->size = 0;
25 self->capacity = FD_CHUNKSIZE;
26 self->changedEvent = Event_create(0, self);
27 return self;
28 }
29
FileData_clone(const FileData * self)30 SOEXPORT FileData *FileData_clone(const FileData *self)
31 {
32 FileData *cloned = xmalloc(sizeof *cloned);
33 cloned->size = self->size;
34 cloned->capacity = self->capacity;
35 cloned->content = xmalloc(self->capacity);
36 cloned->changedEvent = Event_create(0, cloned);
37 memcpy(cloned->content, self->content, self->size);
38 return cloned;
39 }
40
FileData_size(const FileData * self)41 SOEXPORT size_t FileData_size(const FileData *self)
42 {
43 return self->size;
44 }
45
FileData_rcontent(const FileData * self)46 SOEXPORT const uint8_t *FileData_rcontent(const FileData *self)
47 {
48 return self->content;
49 }
50
FileData_append(FileData * self,const uint8_t * data,size_t size)51 SOEXPORT int FileData_append(FileData *self, const uint8_t *data, size_t size)
52 {
53 if (self->size + size < size || self->size + size > FILEDATA_MAXSIZE)
54 {
55 logmsg(L_ERROR, "FileData_append: maximum size exceeded.");
56 return -1;
57 }
58 while (self->size + size > self->capacity)
59 {
60 self->capacity += FD_CHUNKSIZE;
61 self->content = xrealloc(self->content, self->capacity);
62 }
63 memcpy(self->content + self->size, data, size);
64 self->size += size;
65 Event_raise(self->changedEvent, 0);
66 return 0;
67 }
68
FileData_appendByte(FileData * self,uint8_t byte)69 SOEXPORT int FileData_appendByte(FileData *self, uint8_t byte)
70 {
71 if (self->size == FILEDATA_MAXSIZE)
72 {
73 logmsg(L_ERROR, "FileData_appendByte: maximum size exceeded.");
74 return -1;
75 }
76 if (self->size == self->capacity)
77 {
78 self->capacity += FD_CHUNKSIZE;
79 self->content = xrealloc(self->content, self->capacity);
80 }
81 self->content[self->size++] = byte;
82 Event_raise(self->changedEvent, 0);
83 return 0;
84 }
85
FileData_appendBytes(FileData * self,uint8_t byte,size_t count)86 SOEXPORT int FileData_appendBytes(FileData *self, uint8_t byte, size_t count)
87 {
88 if (self->size + count < count || self->size + count > FILEDATA_MAXSIZE)
89 {
90 logmsg(L_ERROR, "FileData_appendBytes: maximum size exceeded.");
91 return -1;
92 }
93 while (self->size + count > self->capacity)
94 {
95 self->capacity += FD_CHUNKSIZE;
96 self->content = xrealloc(self->content, self->capacity);
97 }
98 memset(self->content + self->size, byte, count);
99 self->size += count;
100 Event_raise(self->changedEvent, 0);
101 return 0;
102 }
103
FileData_setByte(FileData * self,uint8_t byte,size_t pos)104 SOEXPORT int FileData_setByte(FileData *self, uint8_t byte, size_t pos)
105 {
106 if (pos >= self->size)
107 {
108 logmsg(L_ERROR, "FileData_setByte: invalid position.");
109 return -1;
110 }
111 self->content[pos] = byte;
112 return 0;
113 }
114
FileData_changedEvent(FileData * self)115 SOEXPORT Event *FileData_changedEvent(FileData *self)
116 {
117 return self->changedEvent;
118 }
119
FileData_destroy(FileData * self)120 SOEXPORT void FileData_destroy(FileData *self)
121 {
122 if (!self) return;
123 Event_destroy(self->changedEvent);
124 free(self->content);
125 free(self);
126 }
127