/[public]/psiconv/trunk/lib/psiconv/buffer.c
ViewVC logotype

Contents of /psiconv/trunk/lib/psiconv/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 158 - (show annotations)
Tue Nov 18 11:25:10 2003 UTC (20 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 6105 byte(s)
(Frodo) Add function psiconv_buffer_subbuffer

1 /*
2 buffer.c - Part of psiconv, a PSION 5 file formats converter
3 Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20
21 #include "config.h"
22 #include "compat.h"
23
24 #include <stdlib.h>
25
26 #include "list.h"
27 #include "error.h"
28 #include "buffer.h"
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
39 struct psiconv_buffer_s {
40 psiconv_list reloc_target; /* of struct relocation_s */
41 psiconv_list reloc_ref; /* of struct relocation_s */
42 psiconv_list data; /* of psiconv_u8 */
43 };
44
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)
53 {
54 psiconv_buffer buf;
55 if (!(buf = malloc(sizeof(*buf))))
56 goto ERROR1;
57 if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8))))
58 goto ERROR2;
59 if (!(buf->reloc_target = psiconv_list_new(
60 sizeof(struct psiconv_relocation_s))))
61 goto ERROR3;
62 if (!(buf->reloc_ref = psiconv_list_new(
63 sizeof(struct psiconv_relocation_s))))
64 goto ERROR4;
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;
74 }
75
76 void psiconv_buffer_free(psiconv_buffer buf)
77 {
78 psiconv_list_free(buf->reloc_ref);
79 psiconv_list_free(buf->reloc_target);
80 psiconv_list_free(buf->data);
81 free(buf);
82 }
83
84 psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf)
85 {
86 return psiconv_list_length(buf->data);
87 }
88
89 psiconv_u8 *psiconv_buffer_get(const psiconv_buffer buf, psiconv_u32 off)
90 {
91 return psiconv_list_get(buf->data,off);
92 }
93
94 int psiconv_buffer_add(psiconv_buffer buf,psiconv_u8 data)
95 {
96 return psiconv_list_add(buf->data,&data);
97 }
98
99 size_t psiconv_buffer_fread(psiconv_buffer buf, size_t size, FILE *f)
100 {
101 return psiconv_list_fread(buf->data,size,f);
102 }
103
104 int psiconv_buffer_fread_all(psiconv_buffer buf, FILE *f)
105 {
106 return psiconv_list_fread_all(buf->data,f);
107 }
108
109 int psiconv_buffer_fwrite_all(const psiconv_buffer buf, FILE *f)
110 {
111 return psiconv_list_fwrite_all(buf->data,f);
112 }
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
134 ERROR2:
135 psiconv_buffer_free(*buf);
136 ERROR1:
137 return res;
138 }
139
140 int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra)
141 {
142 int res;
143 psiconv_u32 i;
144 psiconv_relocation reloc;
145
146
147 for (i = 0; i < psiconv_list_length(extra->reloc_target); i++) {
148 if (!(reloc = psiconv_list_get(extra->reloc_target,i)))
149 return -PSICONV_E_OTHER;
150 reloc->offset += psiconv_list_length(buf->data);
151 if ((res=psiconv_list_add(buf->reloc_target,reloc)))
152 return res;
153 }
154 for (i = 0; i < psiconv_list_length(extra->reloc_ref); i++) {
155 if (!(reloc = psiconv_list_get(extra->reloc_ref,i)))
156 return -PSICONV_E_OTHER;
157 reloc->offset += psiconv_list_length(buf->data);
158 if ((res = psiconv_list_add(buf->reloc_ref,reloc)))
159 return res;
160 }
161 return psiconv_list_concat(buf->data,extra->data);
162 }
163
164 int psiconv_buffer_resolve(psiconv_buffer buf)
165 {
166 int res;
167 psiconv_u32 i,j,temp;
168 psiconv_relocation target,ref;
169
170 for (i = 0; i < psiconv_list_length(buf->reloc_ref);i++) {
171 if (!(ref = psiconv_list_get(buf->reloc_ref,i)))
172 return -PSICONV_E_OTHER;
173 for (j = 0; j < psiconv_list_length(buf->reloc_target);j++) {
174 if (!(target = psiconv_list_get(buf->reloc_target,j)))
175 return -PSICONV_E_OTHER;
176 if (ref->id == target->id) {
177 temp = target->offset & 0xff;
178 if ((res = psiconv_list_replace(buf->data,ref->offset,&temp)))
179 return -PSICONV_E_OTHER;
180 temp = (target->offset >> 8) & 0xff;
181 if ((res = psiconv_list_replace(buf->data,ref->offset + 1,&temp)))
182 return -PSICONV_E_OTHER;
183 temp = (target->offset >> 16) & 0xff;
184 if ((res = psiconv_list_replace(buf->data,ref->offset + 2,&temp)))
185 return -PSICONV_E_OTHER;
186 temp = (target->offset >> 24) & 0xff;
187 if ((res = psiconv_list_replace(buf->data,ref->offset + 3,&temp)))
188 return -PSICONV_E_OTHER;
189 break;
190 }
191 }
192 if (j == psiconv_list_length(buf->reloc_target))
193 return -PSICONV_E_OTHER;
194 }
195 psiconv_list_empty(buf->reloc_target);
196 psiconv_list_empty(buf->reloc_ref);
197 return -PSICONV_E_OK;
198 }
199
200 int psiconv_buffer_add_reference(psiconv_buffer buf,int id)
201 {
202 struct psiconv_relocation_s reloc;
203 int res,i;
204 psiconv_u8 data;
205
206 reloc.offset = psiconv_list_length(buf->data);
207 reloc.id = id;
208 if ((res = psiconv_list_add(buf->reloc_ref,&reloc)))
209 return res;
210 data = 0x00;
211 for (i = 0; i < 4; i++)
212 if ((res = psiconv_list_add(buf->data,&data)))
213 return res;
214 return -PSICONV_E_OK;
215 }
216
217 int psiconv_buffer_add_target(psiconv_buffer buf, int id)
218 {
219 struct psiconv_relocation_s reloc;
220
221 reloc.offset = psiconv_list_length(buf->data);
222 reloc.id = id;
223 return psiconv_list_add(buf->reloc_target,&reloc);
224 }

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26