X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=eglib%2Fsrc%2Fgstr.c;h=98d8faf2679e9822d47a3831b32f3160d766a194;hb=f1ff42789be45c30cf3537ee986529179870df1e;hp=0f66a43372e96e0f2ad6db4ac0ec3ef76290ecd6;hpb=da333100c1ff5c8c1fab022b8e220f239b7c93e5;p=mono.git diff --git a/eglib/src/gstr.c b/eglib/src/gstr.c index 0f66a43372e..98d8faf2679 100644 --- a/eglib/src/gstr.c +++ b/eglib/src/gstr.c @@ -32,11 +32,23 @@ #include #include +#ifndef G_OS_WIN32 +#include +#endif + +#include + +/* + * g_strndup and g_vasprintf need to allocate memory with g_malloc if + * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free + * rather than free. + */ + /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */ gchar * g_strndup (const gchar *str, gsize n) { -#ifdef HAVE_STRNDUP +#if defined (HAVE_STRNDUP) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) return strndup (str, n); #else if (str) { @@ -50,6 +62,37 @@ g_strndup (const gchar *str, gsize n) #endif } +gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap) +{ +#if defined (HAVE_VASPRINTF) && !defined (ENABLE_OVERRIDABLE_ALLOCATORS) + return vasprintf (ret, fmt, ap); +#else + char *buf; + int len; + size_t buflen; + va_list ap2; + +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) + ap2 = ap; + len = _vscprintf(fmt, ap2); // NOTE MS specific extension ( :-( ) +#else + va_copy(ap2, ap); + len = vsnprintf(NULL, 0, fmt, ap2); +#endif + + if (len >= 0 && (buf = g_malloc ((buflen = (size_t) (len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; +#endif +} + void g_strfreev (gchar **str_array) { @@ -131,7 +174,7 @@ g_strdup_vprintf (const gchar *format, va_list args) int n; char *ret; - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); if (n == -1) return NULL; @@ -146,7 +189,7 @@ g_strdup_printf (const gchar *format, ...) int n; va_start (args, format); - n = vasprintf (&ret, format, args); + n = g_vasprintf (&ret, format, args); va_end (args); if (n == -1) return NULL; @@ -154,10 +197,72 @@ g_strdup_printf (const gchar *format, ...) return ret; } + +/* +Max error number we support. It's empirically found by looking at our target OS. + +Last this was checked was June-2017. + +Apple is at 106. +Android is at 133. +*/ +#define MONO_ERRNO_MAX 200 +#define str(s) #s + +#ifndef G_OS_WIN32 +static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +static char *error_messages [MONO_ERRNO_MAX]; + const gchar * g_strerror (gint errnum) { - return strerror (errnum); + if (errnum < 0) + errnum = -errnum; + if (errnum >= MONO_ERRNO_MAX) + return ("Error number higher than " str (MONO_ERRNO_MAX)); + + if (!error_messages [errnum]) { +#ifndef G_OS_WIN32 + pthread_mutex_lock (&strerror_lock); +#endif + +#ifdef HAVE_STRERROR_R + char tmp_buff [128]; //Quite arbitrary, should be large enough + char *buff = tmp_buff; + int buff_len = sizeof (tmp_buff); + int r; + buff [0] = 0; + + while ((r = strerror_r (errnum, buff, buff_len - 1))) { + if (r != ERANGE) { + buff = g_strdup_printf ("Invalid Error code '%d'", errnum); + break; + } + if (buff == tmp_buff) + buff = g_malloc (buff_len * 2); + else + buff = g_realloc (buff, buff_len * 2); + buff_len *= 2; + //Spec is not clean on whether size argument includes space for null terminator or not + } + if (!error_messages [errnum]) + error_messages [errnum] = g_strdup (buff); + if (buff != tmp_buff) + g_free (buff); +#else + if (!error_messages [errnum]) + error_messages [errnum] = g_strdup_printf ("Error code '%d'", errnum); +#endif + + +#ifndef G_OS_WIN32 + pthread_mutex_unlock (&strerror_lock); +#endif + + } + return error_messages [errnum]; } gchar * @@ -251,8 +356,12 @@ g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) } if (*string) { - /* Add the rest of the string as the last element */ - add_to_vector (&vector, size, g_strdup (string)); + if (strcmp (string, delimiter) == 0) + add_to_vector (&vector, size, g_strdup ("")); + else { + /* Add the rest of the string as the last element */ + add_to_vector (&vector, size, g_strdup (string)); + } size++; }