]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/string.c
1.1.07 release
[Ventoy.git] / wimboot / wimboot-2.7.3 / src / string.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 /**
21 * @file
22 *
23 * String functions
24 *
25 */
26
27 #include <stddef.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include "ctype.h"
31 #include "wctype.h"
32
33 /**
34 * Copy memory area
35 *
36 * @v dest Destination address
37 * @v src Source address
38 * @v len Length
39 * @ret dest Destination address
40 */
41 void * memcpy ( void *dest, const void *src, size_t len ) {
42 void *edi = dest;
43 const void *esi = src;
44 int discard_ecx;
45
46 /* Perform dword-based copy for bulk, then byte-based for remainder */
47 __asm__ __volatile__ ( "rep movsl"
48 : "=&D" ( edi ), "=&S" ( esi ),
49 "=&c" ( discard_ecx )
50 : "0" ( edi ), "1" ( esi ), "2" ( len >> 2 )
51 : "memory" );
52 __asm__ __volatile__ ( "rep movsb"
53 : "=&D" ( edi ), "=&S" ( esi ),
54 "=&c" ( discard_ecx )
55 : "0" ( edi ), "1" ( esi ), "2" ( len & 3 )
56 : "memory" );
57 return dest;
58 }
59
60 /**
61 * Copy memory area backwards
62 *
63 * @v dest Destination address
64 * @v src Source address
65 * @v len Length
66 * @ret dest Destination address
67 */
68 static void * memcpy_reverse ( void *dest, const void *src, size_t len ) {
69 void *edi = ( dest + len - 1 );
70 const void *esi = ( src + len - 1 );
71 int discard_ecx;
72
73 /* Assume memmove() is not performance-critical, and perform a
74 * bytewise copy for simplicity.
75 *
76 * Disable interrupts to avoid known problems on platforms
77 * that assume the direction flag always remains cleared.
78 */
79 __asm__ __volatile__ ( "pushf\n\t"
80 "cli\n\t"
81 "std\n\t"
82 "rep movsb\n\t"
83 "popf\n\t"
84 : "=&D" ( edi ), "=&S" ( esi ),
85 "=&c" ( discard_ecx )
86 : "0" ( edi ), "1" ( esi ),
87 "2" ( len )
88 : "memory" );
89 return dest;
90 }
91
92 /**
93 * Copy (possibly overlapping) memory area
94 *
95 * @v dest Destination address
96 * @v src Source address
97 * @v len Length
98 * @ret dest Destination address
99 */
100 void * memmove ( void *dest, const void *src, size_t len ) {
101
102 if ( dest <= src ) {
103 return memcpy ( dest, src, len );
104 } else {
105 return memcpy_reverse ( dest, src, len );
106 }
107 }
108
109 /**
110 * Set memory area
111 *
112 * @v dest Destination address
113 * @v src Source address
114 * @v len Length
115 * @ret dest Destination address
116 */
117 void * memset ( void *dest, int c, size_t len ) {
118 void *edi = dest;
119 int eax = c;
120 int discard_ecx;
121
122 /* Expand byte to whole dword */
123 eax |= ( eax << 8 );
124 eax |= ( eax << 16 );
125
126 /* Perform dword-based set for bulk, then byte-based for remainder */
127 __asm__ __volatile__ ( "rep stosl"
128 : "=&D" ( edi ), "=&a" ( eax ),
129 "=&c" ( discard_ecx )
130 : "0" ( edi ), "1" ( eax ), "2" ( len >> 2 )
131 : "memory" );
132 __asm__ __volatile__ ( "rep stosb"
133 : "=&D" ( edi ), "=&a" ( eax ),
134 "=&c" ( discard_ecx )
135 : "0" ( edi ), "1" ( eax ), "2" ( len & 3 )
136 : "memory" );
137 return dest;
138 }
139
140 /**
141 * Compare memory areas
142 *
143 * @v src1 First source area
144 * @v src2 Second source area
145 * @v len Length
146 * @ret diff Difference
147 */
148 int memcmp ( const void *src1, const void *src2, size_t len ) {
149 const uint8_t *bytes1 = src1;
150 const uint8_t *bytes2 = src2;
151 int diff;
152
153 while ( len-- ) {
154 if ( ( diff = ( *(bytes1++) - *(bytes2++) ) ) )
155 return diff;
156 }
157 return 0;
158 }
159
160 /**
161 * Compare two strings
162 *
163 * @v str1 First string
164 * @v str2 Second string
165 * @ret diff Difference
166 */
167 int strcmp ( const char *str1, const char *str2 ) {
168 int c1;
169 int c2;
170
171 do {
172 c1 = *(str1++);
173 c2 = *(str2++);
174 } while ( ( c1 != '\0' ) && ( c1 == c2 ) );
175
176 return ( c1 - c2 );
177 }
178
179 /**
180 * Compare two strings, case-insensitively
181 *
182 * @v str1 First string
183 * @v str2 Second string
184 * @ret diff Difference
185 */
186 int strcasecmp ( const char *str1, const char *str2 ) {
187 int c1;
188 int c2;
189
190 do {
191 c1 = toupper ( *(str1++) );
192 c2 = toupper ( *(str2++) );
193 } while ( ( c1 != '\0' ) && ( c1 == c2 ) );
194
195 return ( c1 - c2 );
196 }
197
198 /**
199 * Compare two wide-character strings, case-insensitively
200 *
201 * @v str1 First string
202 * @v str2 Second string
203 * @ret diff Difference
204 */
205 int wcscasecmp ( const wchar_t *str1, const wchar_t *str2 ) {
206 int c1;
207 int c2;
208
209 do {
210 c1 = towupper ( *(str1++) );
211 c2 = towupper ( *(str2++) );
212 } while ( ( c1 != L'\0' ) && ( c1 == c2 ) );
213
214 return ( c1 - c2 );
215 }
216
217 /**
218 * Get length of string
219 *
220 * @v str String
221 * @ret len Length
222 */
223 size_t strlen ( const char *str ) {
224 size_t len = 0;
225
226 while ( *(str++) )
227 len++;
228 return len;
229 }
230
231 /**
232 * Get length of wide-character string
233 *
234 * @v str String
235 * @ret len Length (in characters)
236 */
237 size_t wcslen ( const wchar_t *str ) {
238 size_t len = 0;
239
240 while ( *(str++) )
241 len++;
242 return len;
243 }
244
245 /**
246 * Find character in wide-character string
247 *
248 * @v str String
249 * @v c Wide character
250 * @ret first First occurrence of wide character in string, or NULL
251 */
252 wchar_t * wcschr ( const wchar_t *str, wchar_t c ) {
253
254 for ( ; *str ; str++ ) {
255 if ( *str == c )
256 return ( ( wchar_t * )str );
257 }
258 return NULL;
259 }
260
261 char *strchr(const char *str, char c) {
262 for ( ; *str ; str++ ) {
263 if ( *str == c )
264 return ( ( char * )str );
265 }
266 return NULL;
267 }
268
269 /**
270 * Check to see if character is a space
271 *
272 * @v c Character
273 * @ret isspace Character is a space
274 */
275 int isspace ( int c ) {
276 switch ( c ) {
277 case ' ' :
278 case '\f' :
279 case '\n' :
280 case '\r' :
281 case '\t' :
282 case '\v' :
283 return 1;
284 default:
285 return 0;
286 }
287 }
288
289 /**
290 * Convert a string to an unsigned integer
291 *
292 * @v nptr String
293 * @v endptr End pointer to fill in (or NULL)
294 * @v base Numeric base
295 * @ret val Value
296 */
297 unsigned long strtoul ( const char *nptr, char **endptr, int base ) {
298 unsigned long val = 0;
299 int negate = 0;
300 unsigned int digit;
301
302 /* Skip any leading whitespace */
303 while ( isspace ( *nptr ) )
304 nptr++;
305
306 /* Parse sign, if present */
307 if ( *nptr == '+' ) {
308 nptr++;
309 } else if ( *nptr == '-' ) {
310 nptr++;
311 negate = 1;
312 }
313
314 /* Parse base */
315 if ( base == 0 ) {
316
317 /* Default to decimal */
318 base = 10;
319
320 /* Check for octal or hexadecimal markers */
321 if ( *nptr == '0' ) {
322 nptr++;
323 base = 8;
324 if ( ( *nptr | 0x20 ) == 'x' ) {
325 nptr++;
326 base = 16;
327 }
328 }
329 }
330
331 /* Parse digits */
332 for ( ; ; nptr++ ) {
333 digit = *nptr;
334 if ( digit >= 'a' ) {
335 digit = ( digit - 'a' + 10 );
336 } else if ( digit >= 'A' ) {
337 digit = ( digit - 'A' + 10 );
338 } else if ( digit <= '9' ) {
339 digit = ( digit - '0' );
340 }
341 if ( digit >= ( unsigned int ) base )
342 break;
343 val = ( ( val * base ) + digit );
344 }
345
346 /* Record end marker, if applicable */
347 if ( endptr )
348 *endptr = ( ( char * ) nptr );
349
350 /* Return value */
351 return ( negate ? -val : val );
352 }