glib_compat: lift string functions from glib. remove unused API g_win32_error_message()

This commit is contained in:
Nguyen Anh Quynh 2016-12-26 22:36:47 +08:00
parent c5b8fbfbc6
commit 520f335a2a
4 changed files with 97 additions and 121 deletions

View File

@ -24,11 +24,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include "glib_compat.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define GPOINTER_TO_UINT(p) ((guint) (gulong) (p))
#define G_MAXINT INT_MAX
/* All functions below added to eliminate GLIB dependency */
@ -1312,7 +1314,25 @@ gpointer g_renew_(size_t sz, gpointer mem, size_t n_structs)
return g_realloc(mem, need);
}
char *g_strconcat (const char *string1, ...)
/**
* g_strconcat:
* @string1: the first string to add, which must not be %NULL
* @Varargs: a %NULL-terminated list of strings to append to the string
*
* Concatenates all of the given strings into one long string.
* The returned string should be freed with g_free() when no longer needed.
*
* Note that this function is usually not the right function to use to
* assemble a translated message from pieces, since proper translation
* often requires the pieces to be reordered.
*
* <warning><para>The variable argument list <emphasis>must</emphasis> end
* with %NULL. If you forget the %NULL, g_strconcat() will start appending
* random memory junk to your string.</para></warning>
*
* Returns: a newly-allocated string containing all the string arguments
*/
gchar* g_strconcat (const gchar *string1, ...)
{
va_list ap;
char *res;
@ -1336,64 +1356,76 @@ char *g_strconcat (const char *string1, ...)
return res;
}
char **g_strsplit(const char *string, const char *delimiter, int max_tokens)
/**
* g_strsplit:
* @string: a string to split.
* @delimiter: a string which specifies the places at which to split the string.
* The delimiter is not included in any of the resulting strings, unless
* @max_tokens is reached.
* @max_tokens: the maximum number of pieces to split @string into. If this is
* less than 1, the string is split completely.
*
* Splits a string into a maximum of @max_tokens pieces, using the given
* @delimiter. If @max_tokens is reached, the remainder of @string is appended
* to the last token.
*
* As a special case, the result of splitting the empty string "" is an empty
* vector, not a vector containing a single string. The reason for this
* special case is that being able to represent a empty vector is typically
* more useful than consistent handling of empty elements. If you do need
* to represent empty elements, you'll need to check for the empty string
* before calling g_strsplit().
*
* Return value: a newly-allocated %NULL-terminated array of strings. Use
* g_strfreev() to free it.
**/
gchar** g_strsplit (const gchar *string,
const gchar *delimiter,
gint max_tokens)
{
char **res;
if (string == NULL || *string == 0) {
res = (char**)g_malloc(sizeof(char*));
*res = NULL;
} else {
uint32_t ntokens, i, max = (uint32_t) max_tokens;
if (max == 0) max--;
int dlen = strlen(delimiter);
const char *p = string, *b;
for (ntokens = 1; ntokens < max; ntokens++) {
p = strstr(p, delimiter);
if (p == NULL) break;
p += dlen;
}
res = (char**)g_new_(sizeof(char*), ntokens + 1);
p = string;
for (b = p, i = 0; i < ntokens; b = p, i++) {
int len;
if (i == (ntokens - 1)) {
/* last piece special handling */
res[i] = strdup(b);
} else {
p = strstr(b, delimiter);
len = p - b;
res[i] = (char*)g_malloc(len + 1);
memcpy(res[i], b, len);
res[i][len] = 0;
p += dlen;
}
}
res[ntokens] = NULL;
}
return res;
GSList *string_list = NULL, *slist;
gchar **str_array, *s;
guint n = 0;
const gchar *remainder;
if (string == NULL) return NULL;
if (delimiter == NULL) return NULL;
if (delimiter[0] == '\0') return NULL;
if (max_tokens < 1)
max_tokens = G_MAXINT;
remainder = string;
s = strstr (remainder, delimiter);
if (s)
{
gsize delimiter_len = strlen (delimiter);
while (--max_tokens && s)
{
gsize len;
len = s - remainder;
string_list = g_slist_prepend (string_list,
g_strndup (remainder, len));
n++;
remainder = s + delimiter_len;
s = strstr (remainder, delimiter);
}
}
if (*string)
{
n++;
string_list = g_slist_prepend (string_list, g_strdup (remainder));
}
str_array = g_new (gchar*, n + 1);
str_array[n--] = NULL;
for (slist = string_list; slist; slist = slist->next)
str_array[n--] = slist->data;
g_slist_free (string_list);
return str_array;
}
#ifdef _WIN32
#include <windows.h>
char *g_win32_error_message(int error)
{
char *msg;
char *winMsg = NULL;
if (error == 0) {
return (char*)g_malloc0(1);
}
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
/* give the caller something they can just free */
msg = strdup(winMsg);
/* Free the allocated message. */
HeapFree(GetProcessHeap(), 0, winMsg);
return msg;
}
#endif

View File

@ -45,6 +45,7 @@ typedef unsigned int guint;
typedef char gchar;
typedef int gboolean;
typedef unsigned long gulong;
typedef unsigned long gsize;
typedef gint (*GCompareDataFunc)(gconstpointer a,
gconstpointer b,
@ -121,16 +122,14 @@ gpointer g_memdup(gconstpointer mem, size_t byte_size);
gpointer g_new_(size_t sz, size_t n_structs);
gpointer g_new0_(size_t sz, size_t n_structs);
gpointer g_renew_(size_t sz, gpointer mem, size_t n_structs);
char *g_strconcat(const char *string1, ...);
gchar* g_strconcat (const gchar *string1, ...);
gchar** g_strsplit (const gchar *string,
const gchar *delimiter,
gint max_tokens);
char **g_strsplit(const char *string, const char *delimiter, int max_tokens);
#define g_new(struct_type, n_structs) ((struct_type*)g_new_(sizeof(struct_type), n_structs))
#define g_new0(struct_type, n_structs) ((struct_type*)g_new0_(sizeof(struct_type), n_structs))
#define g_renew(struct_type, mem, n_structs) ((struct_type*)g_renew_(sizeof(struct_type), mem, n_structs))
#ifdef _WIN32
char *g_win32_error_message(int error);
#endif
#endif

View File

@ -38,16 +38,6 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
void error_set_errno(Error **errp, int os_error, ErrorClass err_class,
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
#ifdef _WIN32
/**
* Set an indirect pointer to an error given a ErrorClass value and a
* printf-style human message, followed by a g_win32_error_message() string if
* @win32_err is not zero.
*/
void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
#endif
/**
* Same as error_set(), but sets a generic error
*/
@ -56,11 +46,6 @@ void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
#define error_setg_errno(errp, os_error, fmt, ...) \
error_set_errno(errp, os_error, ERROR_CLASS_GENERIC_ERROR, \
fmt, ## __VA_ARGS__)
#ifdef _WIN32
#define error_setg_win32(errp, win32_err, fmt, ...) \
error_set_win32(errp, win32_err, ERROR_CLASS_GENERIC_ERROR, \
fmt, ## __VA_ARGS__)
#endif
/**
* Helper for open() errors

View File

@ -88,46 +88,6 @@ void error_setg_file_open(Error **errp, int os_errno, const char *filename)
error_setg_errno(errp, os_errno, "Could not open '%s'", filename);
}
#ifdef _WIN32
void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
const char *fmt, ...)
{
Error *err;
char *msg1;
va_list ap;
if (errp == NULL) {
return;
}
assert(*errp == NULL);
err = g_malloc0(sizeof(*err));
va_start(ap, fmt);
msg1 = g_strdup_vprintf(fmt, ap);
if (win32_err != 0) {
char *msg2 = g_win32_error_message(win32_err);
err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
(unsigned)win32_err);
g_free(msg2);
g_free(msg1);
} else {
err->msg = msg1;
}
va_end(ap);
err->err_class = err_class;
if (errp == &error_abort) {
// error_report("%s", error_get_pretty(err));
abort();
}
*errp = err;
}
#endif
Error *error_copy(const Error *err)
{
Error *err_new;