]> code.delx.au - refind/blob - filesystems/fsw_lib.c
Previous commit broke loading of EFI drivers with SB active; fix it.
[refind] / filesystems / fsw_lib.c
1 /**
2 * \file fsw_lib.c
3 * Core file system wrapper library functions.
4 */
5
6 /*-
7 * Copyright (c) 2006 Christoph Pfisterer
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the
19 * distribution.
20 *
21 * * Neither the name of Christoph Pfisterer nor the names of the
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "fsw_core.h"
39
40 /* Include generated string encoding specific functions */
41 #include "fsw_strfunc.h"
42
43
44 /**
45 * Allocate memory and clear it.
46 */
47
48 fsw_status_t fsw_alloc_zero(int len, void **ptr_out)
49 {
50 fsw_status_t status;
51
52 status = fsw_alloc(len, ptr_out);
53 if (status)
54 return status;
55 fsw_memzero(*ptr_out, len);
56 return FSW_SUCCESS;
57 }
58
59 /**
60 * Duplicate a piece of data.
61 */
62
63 fsw_status_t fsw_memdup(void **dest_out, void *src, int len)
64 {
65 fsw_status_t status;
66
67 status = fsw_alloc(len, dest_out);
68 if (status)
69 return status;
70 fsw_memcpy(*dest_out, src, len);
71 return FSW_SUCCESS;
72 }
73
74 /**
75 * Get the length of a string. Returns the number of characters in the string.
76 */
77
78 int fsw_strlen(struct fsw_string *s)
79 {
80 if (s->type == FSW_STRING_TYPE_EMPTY)
81 return 0;
82 return s->len;
83 }
84
85 /**
86 * Compare two strings for equality. The two strings are compared, taking their
87 * encoding into account. If they are considered equal, boolean true is returned.
88 * Otherwise, boolean false is returned.
89 */
90
91 int fsw_streq(struct fsw_string *s1, struct fsw_string *s2)
92 {
93 struct fsw_string temp_s;
94
95 // handle empty strings
96 if (s1->type == FSW_STRING_TYPE_EMPTY) {
97 temp_s.type = FSW_STRING_TYPE_ISO88591;
98 temp_s.size = temp_s.len = 0;
99 temp_s.data = NULL;
100 return fsw_streq(&temp_s, s2);
101 }
102 if (s2->type == FSW_STRING_TYPE_EMPTY) {
103 temp_s.type = FSW_STRING_TYPE_ISO88591;
104 temp_s.size = temp_s.len = 0;
105 temp_s.data = NULL;
106 return fsw_streq(s1, &temp_s);
107 }
108
109 // check length (count of chars)
110 if (s1->len != s2->len)
111 return 0;
112 if (s1->len == 0) // both strings are empty
113 return 1;
114
115 if (s1->type == s2->type) {
116 // same type, do a dumb memory compare
117 if (s1->size != s2->size)
118 return 0;
119 return fsw_memeq(s1->data, s2->data, s1->size);
120 }
121
122 // dispatch to type-specific functions
123 #define STREQ_DISPATCH(type1, type2) \
124 if (s1->type == FSW_STRING_TYPE_##type1 && s2->type == FSW_STRING_TYPE_##type2) \
125 return fsw_streq_##type1##_##type2(s1->data, s2->data, s1->len); \
126 if (s2->type == FSW_STRING_TYPE_##type1 && s1->type == FSW_STRING_TYPE_##type2) \
127 return fsw_streq_##type1##_##type2(s2->data, s1->data, s1->len);
128 STREQ_DISPATCH(ISO88591, UTF8);
129 STREQ_DISPATCH(ISO88591, UTF16);
130 STREQ_DISPATCH(ISO88591, UTF16_SWAPPED);
131 STREQ_DISPATCH(UTF8, UTF16);
132 STREQ_DISPATCH(UTF8, UTF16_SWAPPED);
133 STREQ_DISPATCH(UTF16, UTF16_SWAPPED);
134
135 // final fallback
136 return 0;
137 }
138
139 /**
140 * Compare a string with a C string constant. This sets up a string descriptor
141 * for the string constant (second argument) and runs fsw_streq on the two
142 * strings. Currently the C string is interpreted as ISO 8859-1.
143 * Returns boolean true if the strings are considered equal, boolean false otherwise.
144 */
145
146 int fsw_streq_cstr(struct fsw_string *s1, const char *s2)
147 {
148 struct fsw_string temp_s;
149 int i;
150
151 for (i = 0; s2[i]; i++)
152 ;
153
154 temp_s.type = FSW_STRING_TYPE_ISO88591;
155 temp_s.size = temp_s.len = i;
156 temp_s.data = (char *)s2;
157
158 return fsw_streq(s1, &temp_s);
159 }
160
161 /**
162 * Creates a duplicate of a string, converting it to the given encoding during the copy.
163 * If the function returns FSW_SUCCESS, the caller must free the string later with
164 * fsw_strfree.
165 */
166
167 fsw_status_t fsw_strdup_coerce(struct fsw_string *dest, int type, struct fsw_string *src)
168 {
169 fsw_status_t status;
170
171 if (src->type == FSW_STRING_TYPE_EMPTY || src->len == 0) {
172 dest->type = type;
173 dest->size = dest->len = 0;
174 dest->data = NULL;
175 return FSW_SUCCESS;
176 }
177
178 if (src->type == type) {
179 dest->type = type;
180 dest->len = src->len;
181 dest->size = src->size;
182 status = fsw_alloc(dest->size, &dest->data);
183 if (status)
184 return status;
185
186 fsw_memcpy(dest->data, src->data, dest->size);
187 return FSW_SUCCESS;
188 }
189
190 // dispatch to type-specific functions
191 #define STRCOERCE_DISPATCH(type1, type2) \
192 if (src->type == FSW_STRING_TYPE_##type1 && type == FSW_STRING_TYPE_##type2) \
193 return fsw_strcoerce_##type1##_##type2(src->data, src->len, dest);
194 STRCOERCE_DISPATCH(UTF8, ISO88591);
195 STRCOERCE_DISPATCH(UTF16, ISO88591);
196 STRCOERCE_DISPATCH(UTF16_SWAPPED, ISO88591);
197 STRCOERCE_DISPATCH(ISO88591, UTF8);
198 STRCOERCE_DISPATCH(UTF16, UTF8);
199 STRCOERCE_DISPATCH(UTF16_SWAPPED, UTF8);
200 STRCOERCE_DISPATCH(ISO88591, UTF16);
201 STRCOERCE_DISPATCH(UTF8, UTF16);
202 STRCOERCE_DISPATCH(UTF16_SWAPPED, UTF16);
203
204 return FSW_UNSUPPORTED;
205 }
206
207 /**
208 * Splits a string at the first occurence of the separator character.
209 * The buffer string is searched for the separator character. If it is found, the
210 * element string descriptor is filled to point at the part of the buffer string
211 * before the separator. The buffer string itself is adjusted to point at the
212 * remaining part of the string (without the separator).
213 *
214 * If the separator is not found in the buffer string, then element is changed to
215 * point at the whole buffer string, and the buffer string itself is changed into
216 * an empty string.
217 *
218 * This function only manipulates the pointers and lengths in the two string descriptors,
219 * it does not change the actual string. If the buffer string is dynamically allocated,
220 * you must make a copy of it so that you can release it later.
221 */
222
223 void fsw_strsplit(struct fsw_string *element, struct fsw_string *buffer, char separator)
224 {
225 int i, maxlen;
226
227 if (buffer->type == FSW_STRING_TYPE_EMPTY || buffer->len == 0) {
228 element->type = FSW_STRING_TYPE_EMPTY;
229 return;
230 }
231
232 maxlen = buffer->len;
233 *element = *buffer;
234
235 if (buffer->type == FSW_STRING_TYPE_ISO88591) {
236 fsw_u8 *p;
237
238 p = (fsw_u8 *)element->data;
239 for (i = 0; i < maxlen; i++, p++) {
240 if (*p == separator) {
241 buffer->data = p + 1;
242 buffer->len -= i + 1;
243 break;
244 }
245 }
246 element->len = i;
247 if (i == maxlen) {
248 buffer->data = p;
249 buffer->len -= i;
250 }
251
252 element->size = element->len;
253 buffer->size = buffer->len;
254
255 } else if (buffer->type == FSW_STRING_TYPE_UTF16) {
256 fsw_u16 *p;
257
258 p = (fsw_u16 *)element->data;
259 for (i = 0; i < maxlen; i++, p++) {
260 if (*p == separator) {
261 buffer->data = p + 1;
262 buffer->len -= i + 1;
263 break;
264 }
265 }
266 element->len = i;
267 if (i == maxlen) {
268 buffer->data = p;
269 buffer->len -= i;
270 }
271
272 element->size = element->len * sizeof(fsw_u16);
273 buffer->size = buffer->len * sizeof(fsw_u16);
274
275 } else {
276 // fallback
277 buffer->type = FSW_STRING_TYPE_EMPTY;
278 }
279
280 // TODO: support UTF8 and UTF16_SWAPPED
281 }
282
283 /**
284 * Frees the memory used by a string returned from fsw_strdup_coerce.
285 */
286
287 void fsw_strfree(struct fsw_string *s)
288 {
289 if (s->type != FSW_STRING_TYPE_EMPTY && s->data)
290 fsw_free(s->data);
291 s->type = FSW_STRING_TYPE_EMPTY;
292 }
293
294 // EOF