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