… | |
… | |
25 | |
25 | |
26 | #include "list.h" |
26 | #include "list.h" |
27 | #include "error.h" |
27 | #include "error.h" |
28 | #include "buffer.h" |
28 | #include "buffer.h" |
29 | |
29 | |
|
|
30 | #ifdef DMALLOC |
|
|
31 | #include <dmalloc.h> |
|
|
32 | #endif |
|
|
33 | |
|
|
34 | typedef struct psiconv_relocation_s { |
|
|
35 | psiconv_u32 offset; |
|
|
36 | int id; |
|
|
37 | } *psiconv_relocation; |
|
|
38 | |
30 | struct psiconv_buffer_s { |
39 | struct psiconv_buffer_s { |
31 | psiconv_u32 base_offset; |
40 | psiconv_list reloc_target; /* of struct relocation_s */ |
32 | psiconv_list data; |
41 | psiconv_list reloc_ref; /* of struct relocation_s */ |
|
|
42 | psiconv_list data; /* of psiconv_u8 */ |
33 | }; |
43 | }; |
34 | |
44 | |
35 | psiconv_buffer psiconv_buffer_new(psiconv_u32 base_offset) |
45 | static psiconv_u32 unique_id = 1; |
|
|
46 | |
|
|
47 | psiconv_u32 psiconv_buffer_unique_id(void) |
|
|
48 | { |
|
|
49 | return unique_id ++; |
|
|
50 | } |
|
|
51 | |
|
|
52 | psiconv_buffer psiconv_buffer_new(void) |
36 | { |
53 | { |
37 | psiconv_buffer buf; |
54 | psiconv_buffer buf; |
38 | if (!(buf = malloc(sizeof(*buf)))) |
55 | if (!(buf = malloc(sizeof(*buf)))) |
39 | return NULL; |
56 | goto ERROR1; |
40 | if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) { |
57 | if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) |
41 | free(buf); |
58 | goto ERROR2; |
42 | return NULL; |
59 | if (!(buf->reloc_target = psiconv_list_new( |
43 | } |
60 | sizeof(struct psiconv_relocation_s)))) |
44 | buf->base_offset = base_offset; |
61 | goto ERROR3; |
|
|
62 | if (!(buf->reloc_ref = psiconv_list_new( |
|
|
63 | sizeof(struct psiconv_relocation_s)))) |
|
|
64 | goto ERROR4; |
45 | return buf; |
65 | return buf; |
|
|
66 | ERROR4: |
|
|
67 | psiconv_list_free(buf->reloc_target); |
|
|
68 | ERROR3: |
|
|
69 | psiconv_list_free(buf->data); |
|
|
70 | ERROR2: |
|
|
71 | free(buf); |
|
|
72 | ERROR1: |
|
|
73 | return NULL; |
46 | } |
74 | } |
47 | |
75 | |
48 | void psiconv_buffer_free(psiconv_buffer buf) |
76 | void psiconv_buffer_free(psiconv_buffer buf) |
49 | { |
77 | { |
|
|
78 | psiconv_list_free(buf->reloc_ref); |
|
|
79 | psiconv_list_free(buf->reloc_target); |
50 | psiconv_list_free(buf->data); |
80 | psiconv_list_free(buf->data); |
51 | free(buf); |
81 | free(buf); |
52 | } |
82 | } |
53 | |
83 | |
54 | psiconv_u32 psiconv_buffer_base_offset(const psiconv_buffer buf) |
|
|
55 | { |
|
|
56 | return buf->base_offset; |
|
|
57 | } |
|
|
58 | |
|
|
59 | psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf) |
84 | psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf) |
60 | { |
85 | { |
61 | return psiconv_list_length(buf->data); |
86 | return psiconv_list_length(buf->data); |
62 | } |
87 | } |
63 | |
88 | |
64 | |
|
|
65 | psiconv_u8 *psiconv_buffer_get(const psiconv_buffer buf, psiconv_u32 off) |
89 | psiconv_u8 *psiconv_buffer_get(const psiconv_buffer buf, psiconv_u32 off) |
66 | { |
90 | { |
67 | return psiconv_list_get(buf->data,off); |
91 | return psiconv_list_get(buf->data,off); |
68 | } |
92 | } |
69 | |
93 | |
70 | int psiconv_buffer_add(psiconv_buffer buf,psiconv_u8 data) |
94 | int psiconv_buffer_add(psiconv_buffer buf,psiconv_u8 data) |
71 | { |
95 | { |
72 | return psiconv_list_add(buf->data,&data); |
96 | return psiconv_list_add(buf->data,&data); |
73 | } |
97 | } |
74 | |
98 | |
75 | size_t psiconv_buffer_fread(psiconv_buffer buf,size_t size, FILE *f) |
99 | size_t psiconv_buffer_fread(psiconv_buffer buf, size_t size, FILE *f) |
76 | { |
100 | { |
77 | return psiconv_list_fread(buf->data,size,f); |
101 | return psiconv_list_fread(buf->data,size,f); |
78 | } |
102 | } |
79 | |
103 | |
80 | int psiconv_buffer_fread_all(psiconv_buffer buf, FILE *f) |
104 | int psiconv_buffer_fread_all(psiconv_buffer buf, FILE *f) |
… | |
… | |
85 | int psiconv_buffer_fwrite_all(const psiconv_buffer buf, FILE *f) |
109 | int psiconv_buffer_fwrite_all(const psiconv_buffer buf, FILE *f) |
86 | { |
110 | { |
87 | return psiconv_list_fwrite_all(buf->data,f); |
111 | return psiconv_list_fwrite_all(buf->data,f); |
88 | } |
112 | } |
89 | |
113 | |
|
|
114 | int psiconv_buffer_subbuffer(psiconv_buffer *buf, const psiconv_buffer org, |
|
|
115 | psiconv_u32 offset, psiconv_u32 length) |
|
|
116 | { |
|
|
117 | int i; |
|
|
118 | int res; |
|
|
119 | psiconv_u8 *data; |
|
|
120 | if (! (*buf = psiconv_buffer_new())) { |
|
|
121 | res = PSICONV_E_NOMEM; |
|
|
122 | goto ERROR1; |
|
|
123 | } |
|
|
124 | for (i = 0; i < length; i++) { |
|
|
125 | if (!(data = psiconv_buffer_get(org,offset+i))) { |
|
|
126 | res = PSICONV_E_OTHER; |
|
|
127 | goto ERROR2; |
|
|
128 | } |
|
|
129 | if ((res = psiconv_buffer_add(*buf,*data))) { |
|
|
130 | goto ERROR2; |
|
|
131 | } |
|
|
132 | } |
|
|
133 | return 0; |
|
|
134 | |
|
|
135 | ERROR2: |
|
|
136 | psiconv_buffer_free(*buf); |
|
|
137 | ERROR1: |
|
|
138 | return res; |
|
|
139 | } |
|
|
140 | |
90 | int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra) |
141 | int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra) |
91 | { |
142 | { |
|
|
143 | int res; |
|
|
144 | psiconv_u32 i; |
|
|
145 | psiconv_relocation reloc; |
|
|
146 | |
|
|
147 | |
|
|
148 | for (i = 0; i < psiconv_list_length(extra->reloc_target); i++) { |
|
|
149 | if (!(reloc = psiconv_list_get(extra->reloc_target,i))) |
|
|
150 | return -PSICONV_E_OTHER; |
|
|
151 | reloc->offset += psiconv_list_length(buf->data); |
|
|
152 | if ((res=psiconv_list_add(buf->reloc_target,reloc))) |
|
|
153 | return res; |
|
|
154 | } |
|
|
155 | for (i = 0; i < psiconv_list_length(extra->reloc_ref); i++) { |
|
|
156 | if (!(reloc = psiconv_list_get(extra->reloc_ref,i))) |
|
|
157 | return -PSICONV_E_OTHER; |
|
|
158 | reloc->offset += psiconv_list_length(buf->data); |
|
|
159 | if ((res = psiconv_list_add(buf->reloc_ref,reloc))) |
|
|
160 | return res; |
|
|
161 | } |
92 | return psiconv_list_concat(buf->data,extra->data); |
162 | return psiconv_list_concat(buf->data,extra->data); |
93 | } |
163 | } |
|
|
164 | |
|
|
165 | int psiconv_buffer_resolve(psiconv_buffer buf) |
|
|
166 | { |
|
|
167 | int res; |
|
|
168 | psiconv_u32 i,j,temp; |
|
|
169 | psiconv_relocation target,ref; |
|
|
170 | |
|
|
171 | for (i = 0; i < psiconv_list_length(buf->reloc_ref);i++) { |
|
|
172 | if (!(ref = psiconv_list_get(buf->reloc_ref,i))) |
|
|
173 | return -PSICONV_E_OTHER; |
|
|
174 | for (j = 0; j < psiconv_list_length(buf->reloc_target);j++) { |
|
|
175 | if (!(target = psiconv_list_get(buf->reloc_target,j))) |
|
|
176 | return -PSICONV_E_OTHER; |
|
|
177 | if (ref->id == target->id) { |
|
|
178 | temp = target->offset & 0xff; |
|
|
179 | if ((res = psiconv_list_replace(buf->data,ref->offset,&temp))) |
|
|
180 | return -PSICONV_E_OTHER; |
|
|
181 | temp = (target->offset >> 8) & 0xff; |
|
|
182 | if ((res = psiconv_list_replace(buf->data,ref->offset + 1,&temp))) |
|
|
183 | return -PSICONV_E_OTHER; |
|
|
184 | temp = (target->offset >> 16) & 0xff; |
|
|
185 | if ((res = psiconv_list_replace(buf->data,ref->offset + 2,&temp))) |
|
|
186 | return -PSICONV_E_OTHER; |
|
|
187 | temp = (target->offset >> 24) & 0xff; |
|
|
188 | if ((res = psiconv_list_replace(buf->data,ref->offset + 3,&temp))) |
|
|
189 | return -PSICONV_E_OTHER; |
|
|
190 | break; |
|
|
191 | } |
|
|
192 | } |
|
|
193 | if (j == psiconv_list_length(buf->reloc_target)) |
|
|
194 | return -PSICONV_E_OTHER; |
|
|
195 | } |
|
|
196 | psiconv_list_empty(buf->reloc_target); |
|
|
197 | psiconv_list_empty(buf->reloc_ref); |
|
|
198 | return -PSICONV_E_OK; |
|
|
199 | } |
|
|
200 | |
|
|
201 | int psiconv_buffer_add_reference(psiconv_buffer buf,int id) |
|
|
202 | { |
|
|
203 | struct psiconv_relocation_s reloc; |
|
|
204 | int res,i; |
|
|
205 | psiconv_u8 data; |
|
|
206 | |
|
|
207 | reloc.offset = psiconv_list_length(buf->data); |
|
|
208 | reloc.id = id; |
|
|
209 | if ((res = psiconv_list_add(buf->reloc_ref,&reloc))) |
|
|
210 | return res; |
|
|
211 | data = 0x00; |
|
|
212 | for (i = 0; i < 4; i++) |
|
|
213 | if ((res = psiconv_list_add(buf->data,&data))) |
|
|
214 | return res; |
|
|
215 | return -PSICONV_E_OK; |
|
|
216 | } |
|
|
217 | |
|
|
218 | int psiconv_buffer_add_target(psiconv_buffer buf, int id) |
|
|
219 | { |
|
|
220 | struct psiconv_relocation_s reloc; |
|
|
221 | |
|
|
222 | reloc.offset = psiconv_list_length(buf->data); |
|
|
223 | reloc.id = id; |
|
|
224 | return psiconv_list_add(buf->reloc_target,&reloc); |
|
|
225 | } |