summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/util/string.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/util/string.c
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/util/string.c')
-rw-r--r--src/VBox/GuestHost/OpenGL/util/string.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/util/string.c b/src/VBox/GuestHost/OpenGL/util/string.c
new file mode 100644
index 00000000..e41aa1ba
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/string.c
@@ -0,0 +1,589 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_mem.h"
+#include "cr_string.h"
+#include "cr_error.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int crStrlen( const char *str )
+{
+ const char *temp;
+ if (!str) return 0;
+ for (temp = str ; *temp ; temp++);
+ return temp-str;
+}
+
+char *crStrdup( const char *str )
+{
+ int len;
+ char *ret;
+
+ /* Allow strdup'ing of NULL strings -- this makes the __fillin functions
+ * much cleaner. */
+
+ if (str == NULL) return NULL;
+
+ len = crStrlen(str);
+ ret = (char*)crAlloc( len+1 );
+ crMemcpy( ret, str, len );
+ ret[len] = '\0';
+ return ret;
+}
+
+char *crStrndup( const char *str, unsigned int len )
+{
+ char *ret = (char*)crAlloc( len+1 );
+ crMemcpy( ret, str, len );
+ ret[len] = '\0';
+ return ret;
+}
+
+int crStrcmp( const char *str1, const char *str2 )
+{
+ while (*str1 && *str2)
+ {
+ if (*str1 != *str2)
+ {
+ break;
+ }
+ str1++; str2++;
+ }
+ return (*str1 - *str2);
+}
+
+int crStrncmp( const char *str1, const char *str2, int n )
+{
+ int i = 0;
+ while (*str1 && *str2 && i < n)
+ {
+ if (*str1 != *str2)
+ {
+ break;
+ }
+ str1++; str2++; i++;
+ }
+ if (i == n) return 0;
+ return (*str1 - *str2);
+}
+
+static char lowercase[256] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
+};
+
+int crStrcasecmp( const char *str1, const char *str2 )
+{
+ while (*str1 && *str2)
+ {
+ if (lowercase[(int) *str1] != lowercase[(int) *str2])
+ {
+ break;
+ }
+ str1++; str2++;
+ }
+ return (lowercase[(int) *str1] - lowercase[(int) *str2]);
+}
+
+void crStrcpy( char *dest, const char *src )
+{
+ while ((*dest++ = *src++))
+ ;
+}
+
+void crStrncpy( char *dest, const char *src, unsigned int len )
+{
+ const unsigned int str_len = crStrlen(src);
+ if (str_len > len - 1) {
+ crMemcpy( dest, src, len ); /* NOTE: not null-terminated! */
+ }
+ else {
+ crMemcpy( dest, src, str_len + 1 ); /* includes null terminator */
+ }
+}
+
+void crStrcat( char *dest, const char *src )
+{
+ crStrcpy( dest + crStrlen(dest), src );
+}
+
+char *crStrjoin( const char *str1, const char *str2 )
+{
+ const int len1 = crStrlen(str1), len2 = crStrlen(str2);
+ char *s = crAlloc(len1 + len2 + 1);
+ if (s)
+ {
+ crMemcpy( s, str1, len1 );
+ crMemcpy( s + len1, str2, len2 );
+ s[len1 + len2] = '\0';
+ }
+ return s;
+}
+
+char *crStrjoin3( const char *str1, const char *str2, const char *str3 )
+{
+ const int len1 = crStrlen(str1), len2 = crStrlen(str2), len3 = crStrlen(str3);
+ char *s = crAlloc(len1 + len2 + len3 + 1);
+ if (s)
+ {
+ crMemcpy( s, str1, len1 );
+ crMemcpy( s + len1, str2, len2 );
+ crMemcpy( s + len1 + len2, str3, len3 );
+ s[len1 + len2 + len3] = '\0';
+ }
+ return s;
+}
+
+char *crStrstr( const char *str, const char *pat )
+{
+ int pat_len = crStrlen( pat );
+ const char *end = str + crStrlen(str) - pat_len;
+ char first_char = *pat;
+ if (!str) return NULL;
+ for (; str <= end ; str++)
+ {
+ if (*str == first_char && !crMemcmp( str, pat, pat_len ))
+ return (char *) str;
+ }
+ return NULL;
+}
+
+char *crStrchr( const char *str, char c )
+{
+ for ( ; *str ; str++ )
+ {
+ if (*str == c)
+ return (char *) str;
+ }
+ return NULL;
+}
+
+char *crStrrchr( const char *str, char c )
+{
+ const char *temp = str + crStrlen( str );
+ for ( ; temp >= str ; temp-- )
+ {
+ if (*temp == c)
+ return (char *) temp;
+ }
+ return NULL;
+}
+
+/* These functions are from the old wiregl net.c -- hexdumps? Not sure quite yet. */
+
+void crBytesToString( char *string, int nstring, void *data, int ndata )
+{
+ int i, offset;
+ unsigned char *udata;
+
+ offset = 0;
+ udata = (unsigned char *) data;
+ for ( i = 0; i < ndata && ( offset + 4 <= nstring ); i++ )
+ {
+ offset += sprintf( string + offset, "%02x ", udata[i] );
+ }
+
+ if ( i == ndata && offset > 0 )
+ string[offset-1] = '\0';
+ else
+ crStrcpy( string + offset - 3, "..." );
+}
+
+void crWordsToString( char *string, int nstring, void *data, int ndata )
+{
+ int i, offset, ellipsis;
+ unsigned int *udata;
+
+ /* turn byte count into word count */
+ ndata /= 4;
+
+ /* we need an ellipsis if all the words won't fit in the string */
+ ellipsis = ( ndata * 9 > nstring );
+ if ( ellipsis )
+ {
+ ndata = nstring / 9;
+
+ /* if the ellipsis won't fit then print one less word */
+ if ( ndata * 9 + 3 > nstring )
+ ndata--;
+ }
+
+ offset = 0;
+ udata = (unsigned int *) data;
+ for ( i = 0; i < ndata; i++ )
+ {
+ offset += sprintf( string + offset, "%08x ", udata[i] );
+ }
+
+ if ( ellipsis )
+ crStrcpy( string + offset, "..." );
+ else if ( offset > 0 )
+ string[offset-1] = 0;
+}
+
+int crStrToInt( const char *str )
+{
+ if (!str) return 0;
+
+ return atoi(str);
+}
+
+float crStrToFloat( const char *str )
+{
+ if (!str) return 0.0f;
+
+ return (float) atof(str);
+}
+
+static int __numOccurrences( const char *str, const char *substr )
+{
+ int ret = 0;
+ char *temp = (char *) str;
+ while ((temp = crStrstr( temp, substr )) != NULL )
+ {
+ temp += crStrlen(substr);
+ ret++;
+ }
+ return ret;
+}
+
+/**
+ * Split str into a NULL-terminated array of strings, using splitstr as
+ * the separator.
+ * It's the same as the Python call string.split(str, splitstr).
+ * Note: crStrSplit("a b c", " ") returns ["a", "b", "", "c", NULL] though!!!
+ */
+char **crStrSplit( const char *str, const char *splitstr )
+{
+ char *temp = (char *) str;
+ int num_args = __numOccurrences( str, splitstr ) + 1;
+ char **faked_argv = (char **) crAlloc( (num_args + 1)*sizeof( *faked_argv ) );
+ int i;
+
+ for (i = 0 ; i < num_args ; i++)
+ {
+ char *end;
+ end = crStrstr( temp, splitstr );
+ if (!end)
+ end = temp + crStrlen( temp );
+ faked_argv[i] = crStrndup( temp, end-temp );
+ temp = end + crStrlen(splitstr);
+ }
+ faked_argv[num_args] = NULL;
+ return faked_argv;
+}
+
+char **crStrSplitn( const char *str, const char *splitstr, int n )
+{
+ char **faked_argv;
+ int i;
+ char *temp = (char *) str;
+ int num_args = __numOccurrences( str, splitstr );
+
+ if (num_args > n)
+ num_args = n;
+ num_args++;
+
+ faked_argv = (char **) crAlloc( (num_args + 1) * sizeof( *faked_argv ) );
+ for (i = 0 ; i < num_args ; i++)
+ {
+ char *end;
+ end = crStrstr( temp, splitstr );
+ if (!end || i == num_args - 1 )
+ end = temp + crStrlen( temp );
+ faked_argv[i] = crStrndup( temp, end-temp );
+ temp = end + crStrlen(splitstr);
+ }
+ faked_argv[num_args] = NULL;
+ return faked_argv;
+}
+
+/* Free an array of strings, as returned by crStrSplit() and crStrSplitn(). */
+void crFreeStrings( char **strings )
+{
+ int i;
+ for (i = 0; strings[i]; i++) {
+ crFree(strings[i]);
+ }
+ crFree(strings);
+}
+
+
+/* Intersect two strings on a word-by-word basis (separated by spaces).
+ * We typically use this to intersect OpenGL extension strings.
+ * Example: if s1 = "apple banana plum pear"
+ * and s2 = "plum banana orange"
+ * then return "banana plum" (or "plum banana").
+ */
+char *crStrIntersect( const char *s1, const char *s2 )
+{
+ int len1, len2;
+ int resultLen;
+ char *result;
+ char **exten1, **exten2;
+ int i, j;
+
+ if (!s1 || !s2) {
+ /* null strings, no intersection */
+ return NULL;
+ }
+
+ len1 = crStrlen(s1);
+ len2 = crStrlen(s2);
+
+ /* allocate storage for result (a conservative estimate) */
+ resultLen = ((len1 > len2) ? len1 : len2) + 2;
+ result = (char *) crAlloc(resultLen);
+ if (!result)
+ {
+ return NULL;
+ }
+ result[0] = 0;
+
+ /* split s1 and s2 at space chars */
+ exten1 = crStrSplit(s1, " ");
+ exten2 = crStrSplit(s2, " ");
+
+ for (i = 0; exten1[i]; i++)
+ {
+ for (j = 0; exten2[j]; j++)
+ {
+ if (crStrcmp(exten1[i], exten2[j]) == 0)
+ {
+ /* found an intersection, append to result */
+ crStrcat(result, exten1[i]);
+ crStrcat(result, " ");
+ break;
+ }
+ }
+ }
+
+ /* free split strings */
+ crFreeStrings( exten1 );
+ crFreeStrings( exten2 );
+
+ /*CRASSERT(crStrlen(result) < resultLen);*/
+
+ /* all done! */
+ return result;
+}
+
+
+int crIsDigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+
+static int crStrParseGlSubver(const char * ver, const char ** pNext, bool bSpacePrefixAllowed)
+{
+ const char * initVer = ver;
+ int val = 0;
+
+ for(;;++ver)
+ {
+ if(*ver >= '0' && *ver <= '9')
+ {
+ if(!val)
+ {
+ if(*ver == '0')
+ continue;
+ }
+ else
+ {
+ val *= 10;
+ }
+ val += *ver - '0';
+ }
+ else if(*ver == '.')
+ {
+ *pNext = ver+1;
+ break;
+ }
+ else if(*ver == '\0')
+ {
+ *pNext = NULL;
+ break;
+ }
+ else if(*ver == ' ' || *ver == '\t' || *ver == 0x0d || *ver == 0x0a)
+ {
+ if(bSpacePrefixAllowed)
+ {
+ if(!val)
+ {
+ continue;
+ }
+ }
+
+ /* treat this as the end of version string */
+ *pNext = NULL;
+ break;
+ }
+ else
+ {
+ crWarning("error parsing version %s", initVer);
+ val = -1;
+ break;
+ }
+ }
+
+ return val;
+}
+
+int crStrParseGlVersion(const char * ver)
+{
+ const char * initVer = ver;
+ int tmp;
+ int iVer = crStrParseGlSubver(ver, &ver, true);
+ if(iVer <= 0)
+ {
+ crWarning("parsing major version returned %d, '%s'", iVer, initVer);
+ return iVer;
+ }
+
+ if (iVer > CR_GLVERSION_MAX_MAJOR)
+ {
+ crWarning("major version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
+ return -1;
+ }
+
+ iVer <<= CR_GLVERSION_OFFSET_MAJOR;
+ if(!ver)
+ {
+ crDebug("no minor version supplied");
+ goto done;
+ }
+
+ tmp = crStrParseGlSubver(ver, &ver, false);
+ if (tmp < 0)
+ {
+ crWarning("parsing minor version failed, '%s'", initVer);
+ return -1;
+ }
+
+ if (tmp > CR_GLVERSION_MAX_MINOR)
+ {
+ crWarning("minor version %d is bigger than the max supported %#x, this is somewhat not expected, failing", iVer, CR_GLVERSION_MAX_MAJOR);
+ return -1;
+ }
+
+ iVer |= tmp << CR_GLVERSION_OFFSET_MINOR;
+
+ if (!ver)
+ {
+ crDebug("no build version supplied");
+ goto done;
+ }
+
+ tmp = crStrParseGlSubver(ver, &ver, false);
+ if (tmp < 0)
+ {
+ crWarning("parsing build version failed, '%s', using 0", initVer);
+ tmp = 0;
+ }
+
+ if (tmp > CR_GLVERSION_MAX_BUILD)
+ {
+ crWarning("build version %d is bigger than the max supported, using max supported val %#x", tmp, CR_GLVERSION_MAX_BUILD);
+ tmp = CR_GLVERSION_MAX_MAJOR;
+ }
+
+ iVer |= tmp << CR_GLVERSION_OFFSET_BUILD;
+
+done:
+ crDebug("returning version %#x for string '%s'", iVer, initVer);
+
+ return iVer;
+}
+
+int32_t crStrParseI32(const char *pszStr, const int32_t defaultVal)
+{
+ int32_t result = 0;
+ bool neg = false;
+ unsigned char iDigit = 0;
+ if (!pszStr || pszStr[0] == '\0')
+ return defaultVal;
+
+ for (;;)
+ {
+ if (pszStr[0] == '\0')
+ return defaultVal;
+
+ if (pszStr[0] == ' ' || pszStr[0] == '\t' || pszStr[0] == '\n')
+ {
+ ++pszStr;
+ continue;
+ }
+
+ if (pszStr[0] == '-')
+ {
+ if (neg)
+ return defaultVal;
+
+ neg = true;
+ ++pszStr;
+ continue;
+ }
+
+ break;
+ }
+
+ for (;;)
+ {
+ unsigned char digit;
+ if (pszStr[0] == '\0')
+ {
+ if (!iDigit)
+ return defaultVal;
+ break;
+ }
+
+ digit = pszStr[0] - '0';
+ if (digit > 9)
+ return defaultVal;
+
+ result *= 10;
+ result += digit;
+ ++iDigit;
+
+ ++pszStr;
+ }
+
+ return !neg ? result : -result;
+}