VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/string.c@ 69400

Last change on this file since 69400 was 53726, checked in by vboxsync, 10 years ago

properties.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_string.h"
9#include "cr_error.h"
10
11#include <string.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15int crStrlen( const char *str )
16{
17 const char *temp;
18 if (!str) return 0;
19 for (temp = str ; *temp ; temp++);
20 return temp-str;
21}
22
23char *crStrdup( const char *str )
24{
25 int len;
26 char *ret;
27
28 /* Allow strdup'ing of NULL strings -- this makes the __fillin functions
29 * much cleaner. */
30
31 if (str == NULL) return NULL;
32
33 len = crStrlen(str);
34 ret = (char*)crAlloc( len+1 );
35 crMemcpy( ret, str, len );
36 ret[len] = '\0';
37 return ret;
38}
39
40char *crStrndup( const char *str, unsigned int len )
41{
42 char *ret = (char*)crAlloc( len+1 );
43 crMemcpy( ret, str, len );
44 ret[len] = '\0';
45 return ret;
46}
47
48int crStrcmp( const char *str1, const char *str2 )
49{
50 while (*str1 && *str2)
51 {
52 if (*str1 != *str2)
53 {
54 break;
55 }
56 str1++; str2++;
57 }
58 return (*str1 - *str2);
59}
60
61int crStrncmp( const char *str1, const char *str2, int n )
62{
63 int i = 0;
64 while (*str1 && *str2 && i < n)
65 {
66 if (*str1 != *str2)
67 {
68 break;
69 }
70 str1++; str2++; i++;
71 }
72 if (i == n) return 0;
73 return (*str1 - *str2);
74}
75
76static char lowercase[256] = {
77 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
78 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
79 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
80 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
81 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
82 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
83 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
84 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
85 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
86 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
87 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
88 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
89 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
90 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
91 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
92 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
93 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
94 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
95 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
96 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
97 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
98 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
99 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
100 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
101 '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
102 '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
103 '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
104 '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
105 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
106 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
107 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
108 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
109};
110
111int crStrcasecmp( const char *str1, const char *str2 )
112{
113 while (*str1 && *str2)
114 {
115 if (lowercase[(int) *str1] != lowercase[(int) *str2])
116 {
117 break;
118 }
119 str1++; str2++;
120 }
121 return (lowercase[(int) *str1] - lowercase[(int) *str2]);
122}
123
124void crStrcpy( char *dest, const char *src )
125{
126 while ((*dest++ = *src++))
127 ;
128}
129
130void crStrncpy( char *dest, const char *src, unsigned int len )
131{
132 const unsigned int str_len = crStrlen(src);
133 if (str_len > len - 1) {
134 crMemcpy( dest, src, len ); /* NOTE: not null-terminated! */
135 }
136 else {
137 crMemcpy( dest, src, str_len + 1 ); /* includes null terminator */
138 }
139}
140
141void crStrcat( char *dest, const char *src )
142{
143 crStrcpy( dest + crStrlen(dest), src );
144}
145
146char *crStrjoin( const char *str1, const char *str2 )
147{
148 const int len1 = crStrlen(str1), len2 = crStrlen(str2);
149 char *s = crAlloc(len1 + len2 + 1);
150 if (s)
151 {
152 crMemcpy( s, str1, len1 );
153 crMemcpy( s + len1, str2, len2 );
154 s[len1 + len2] = '\0';
155 }
156 return s;
157}
158
159char *crStrjoin3( const char *str1, const char *str2, const char *str3 )
160{
161 const int len1 = crStrlen(str1), len2 = crStrlen(str2), len3 = crStrlen(str3);
162 char *s = crAlloc(len1 + len2 + len3 + 1);
163 if (s)
164 {
165 crMemcpy( s, str1, len1 );
166 crMemcpy( s + len1, str2, len2 );
167 crMemcpy( s + len1 + len2, str3, len3 );
168 s[len1 + len2 + len3] = '\0';
169 }
170 return s;
171}
172
173char *crStrstr( const char *str, const char *pat )
174{
175 int pat_len = crStrlen( pat );
176 const char *end = str + crStrlen(str) - pat_len;
177 char first_char = *pat;
178 if (!str) return NULL;
179 for (; str <= end ; str++)
180 {
181 if (*str == first_char && !crMemcmp( str, pat, pat_len ))
182 return (char *) str;
183 }
184 return NULL;
185}
186
187char *crStrchr( const char *str, char c )
188{
189 for ( ; *str ; str++ )
190 {
191 if (*str == c)
192 return (char *) str;
193 }
194 return NULL;
195}
196
197char *crStrrchr( const char *str, char c )
198{
199 const char *temp = str + crStrlen( str );
200 for ( ; temp >= str ; temp-- )
201 {
202 if (*temp == c)
203 return (char *) temp;
204 }
205 return NULL;
206}
207
208/* These functions are from the old wiregl net.c -- hexdumps? Not sure quite yet. */
209
210void crBytesToString( char *string, int nstring, void *data, int ndata )
211{
212 int i, offset;
213 unsigned char *udata;
214
215 offset = 0;
216 udata = (unsigned char *) data;
217 for ( i = 0; i < ndata && ( offset + 4 <= nstring ); i++ )
218 {
219 offset += sprintf( string + offset, "%02x ", udata[i] );
220 }
221
222 if ( i == ndata && offset > 0 )
223 string[offset-1] = '\0';
224 else
225 crStrcpy( string + offset - 3, "..." );
226}
227
228void crWordsToString( char *string, int nstring, void *data, int ndata )
229{
230 int i, offset, ellipsis;
231 unsigned int *udata;
232
233 /* turn byte count into word count */
234 ndata /= 4;
235
236 /* we need an ellipsis if all the words won't fit in the string */
237 ellipsis = ( ndata * 9 > nstring );
238 if ( ellipsis )
239 {
240 ndata = nstring / 9;
241
242 /* if the ellipsis won't fit then print one less word */
243 if ( ndata * 9 + 3 > nstring )
244 ndata--;
245 }
246
247 offset = 0;
248 udata = (unsigned int *) data;
249 for ( i = 0; i < ndata; i++ )
250 {
251 offset += sprintf( string + offset, "%08x ", udata[i] );
252 }
253
254 if ( ellipsis )
255 crStrcpy( string + offset, "..." );
256 else if ( offset > 0 )
257 string[offset-1] = 0;
258}
259
260int crStrToInt( const char *str )
261{
262 if (!str) return 0;
263
264 return atoi(str);
265}
266
267float crStrToFloat( const char *str )
268{
269 if (!str) return 0.0f;
270
271 return (float) atof(str);
272}
273
274static int __numOccurrences( const char *str, const char *substr )
275{
276 int ret = 0;
277 char *temp = (char *) str;
278 while ((temp = crStrstr( temp, substr )) != NULL )
279 {
280 temp += crStrlen(substr);
281 ret++;
282 }
283 return ret;
284}
285
286/**
287 * Split str into a NULL-terminated array of strings, using splitstr as
288 * the separator.
289 * It's the same as the Python call string.split(str, splitstr).
290 * Note: crStrSplit("a b c", " ") returns ["a", "b", "", "c", NULL] though!!!
291 */
292char **crStrSplit( const char *str, const char *splitstr )
293{
294 char *temp = (char *) str;
295 int num_args = __numOccurrences( str, splitstr ) + 1;
296 char **faked_argv = (char **) crAlloc( (num_args + 1)*sizeof( *faked_argv ) );
297 int i;
298
299 for (i = 0 ; i < num_args ; i++)
300 {
301 char *end;
302 end = crStrstr( temp, splitstr );
303 if (!end)
304 end = temp + crStrlen( temp );
305 faked_argv[i] = crStrndup( temp, end-temp );
306 temp = end + crStrlen(splitstr);
307 }
308 faked_argv[num_args] = NULL;
309 return faked_argv;
310}
311
312char **crStrSplitn( const char *str, const char *splitstr, int n )
313{
314 char **faked_argv;
315 int i;
316 char *temp = (char *) str;
317 int num_args = __numOccurrences( str, splitstr );
318
319 if (num_args > n)
320 num_args = n;
321 num_args++;
322
323 faked_argv = (char **) crAlloc( (num_args + 1) * sizeof( *faked_argv ) );
324 for (i = 0 ; i < num_args ; i++)
325 {
326 char *end;
327 end = crStrstr( temp, splitstr );
328 if (!end || i == num_args - 1 )
329 end = temp + crStrlen( temp );
330 faked_argv[i] = crStrndup( temp, end-temp );
331 temp = end + crStrlen(splitstr);
332 }
333 faked_argv[num_args] = NULL;
334 return faked_argv;
335}
336
337/* Free an array of strings, as returned by crStrSplit() and crStrSplitn(). */
338void crFreeStrings( char **strings )
339{
340 int i;
341 for (i = 0; strings[i]; i++) {
342 crFree(strings[i]);
343 }
344 crFree(strings);
345}
346
347
348/* Intersect two strings on a word-by-word basis (separated by spaces).
349 * We typically use this to intersect OpenGL extension strings.
350 * Example: if s1 = "apple banana plum pear"
351 * and s2 = "plum banana orange"
352 * then return "banana plum" (or "plum banana").
353 */
354char *crStrIntersect( const char *s1, const char *s2 )
355{
356 int len1, len2;
357 int resultLen;
358 char *result;
359 char **exten1, **exten2;
360 int i, j;
361
362 if (!s1 || !s2) {
363 /* null strings, no intersection */
364 return NULL;
365 }
366
367 len1 = crStrlen(s1);
368 len2 = crStrlen(s2);
369
370 /* allocate storage for result (a conservative estimate) */
371 resultLen = ((len1 > len2) ? len1 : len2) + 2;
372 result = (char *) crAlloc(resultLen);
373 if (!result)
374 {
375 return NULL;
376 }
377 result[0] = 0;
378
379 /* split s1 and s2 at space chars */
380 exten1 = crStrSplit(s1, " ");
381 exten2 = crStrSplit(s2, " ");
382
383 for (i = 0; exten1[i]; i++)
384 {
385 for (j = 0; exten2[j]; j++)
386 {
387 if (crStrcmp(exten1[i], exten2[j]) == 0)
388 {
389 /* found an intersection, append to result */
390 crStrcat(result, exten1[i]);
391 crStrcat(result, " ");
392 break;
393 }
394 }
395 }
396
397 /* free split strings */
398 crFreeStrings( exten1 );
399 crFreeStrings( exten2 );
400
401 /*CRASSERT(crStrlen(result) < resultLen);*/
402
403 /* all done! */
404 return result;
405}
406
407
408int crIsDigit(char c)
409{
410 return c >= '0' && c <= '9';
411}
412
413
414static int crStrParseGlSubver(const char * ver, const char ** pNext, bool bSpacePrefixAllowed)
415{
416 const char * initVer = ver;
417 int val = 0;
418
419 for(;;++ver)
420 {
421 if(*ver >= '0' && *ver <= '9')
422 {
423 if(!val)
424 {
425 if(*ver == '0')
426 continue;
427 }
428 else
429 {
430 val *= 10;
431 }
432 val += *ver - '0';
433 }
434 else if(*ver == '.')
435 {
436 *pNext = ver+1;
437 break;
438 }
439 else if(*ver == '\0')
440 {
441 *pNext = NULL;
442 break;
443 }
444 else if(*ver == ' ' || *ver == '\t' || *ver == 0x0d || *ver == 0x0a)
445 {
446 if(bSpacePrefixAllowed)
447 {
448 if(!val)
449 {
450 continue;
451 }
452 }
453
454 /* treat this as the end of version string */
455 *pNext = NULL;
456 break;
457 }
458 else
459 {
460 crWarning("error parsing version %s", initVer);
461 val = -1;
462 break;
463 }
464 }
465
466 return val;
467}
468
469int crStrParseGlVersion(const char * ver)
470{
471 const char * initVer = ver;
472 int tmp;
473 int iVer = crStrParseGlSubver(ver, &ver, true);
474 if(iVer <= 0)
475 {
476 crWarning("parsing major version returned %d, '%s'", iVer, initVer);
477 return iVer;
478 }
479
480 if (iVer > CR_GLVERSION_MAX_MAJOR)
481 {
482 crWarning("major version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
483 return -1;
484 }
485
486 iVer <<= CR_GLVERSION_OFFSET_MAJOR;
487 if(!ver)
488 {
489 crDebug("no minor version supplied");
490 goto done;
491 }
492
493 tmp = crStrParseGlSubver(ver, &ver, false);
494 if (tmp < 0)
495 {
496 crWarning("parsing minor version failed, '%s'", initVer);
497 return -1;
498 }
499
500 if (tmp > CR_GLVERSION_MAX_MINOR)
501 {
502 crWarning("minor version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
503 return -1;
504 }
505
506 iVer |= tmp << CR_GLVERSION_OFFSET_MINOR;
507
508 if (!ver)
509 {
510 crDebug("no build version supplied");
511 goto done;
512 }
513
514 tmp = crStrParseGlSubver(ver, &ver, false);
515 if (tmp < 0)
516 {
517 crWarning("parsing build version failed, '%s', using 0", initVer);
518 tmp = 0;
519 }
520
521 if (tmp > CR_GLVERSION_MAX_BUILD)
522 {
523 crWarning("build version %d is bigger than the max supported, using max supported val %#x", tmp, CR_GLVERSION_MAX_BUILD);
524 tmp = CR_GLVERSION_MAX_MAJOR;
525 }
526
527 iVer |= tmp << CR_GLVERSION_OFFSET_BUILD;
528
529done:
530 crDebug("returning version %#x for string '%s'", iVer, initVer);
531
532 return iVer;
533}
534
535int32_t crStrParseI32(const char *pszStr, const int32_t defaultVal)
536{
537 int32_t result = 0;
538 bool neg = false;
539 unsigned char iDigit = 0;
540 if (!pszStr || pszStr[0] == '\0')
541 return defaultVal;
542
543 for (;;)
544 {
545 if (pszStr[0] == '\0')
546 return defaultVal;
547
548 if (pszStr[0] == ' ' || pszStr[0] == '\t' || pszStr[0] == '\n')
549 {
550 ++pszStr;
551 continue;
552 }
553
554 if (pszStr[0] == '-')
555 {
556 if (neg)
557 return defaultVal;
558
559 neg = true;
560 ++pszStr;
561 continue;
562 }
563
564 break;
565 }
566
567 for (;;)
568 {
569 unsigned char digit;
570 if (pszStr[0] == '\0')
571 {
572 if (!iDigit)
573 return defaultVal;
574 break;
575 }
576
577 digit = pszStr[0] - '0';
578 if (digit > 9)
579 return defaultVal;
580
581 result *= 10;
582 result += digit;
583 ++iDigit;
584
585 ++pszStr;
586 }
587
588 return !neg ? result : -result;
589}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette