Added some string functions
parent
a664e70488
commit
886b5bc8dd
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
|
||||
* See README for License detail, AUTHORS for developers list.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* wee-string.c: string functions for WeeChat */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#ifndef ICONV_CONST
|
||||
#ifdef ICONV_2ARG_IS_CONST
|
||||
#define ICONV_CONST const
|
||||
#else
|
||||
#define ICONV_CONST
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "weechat.h"
|
||||
#include "wee-string.h"
|
||||
#include "wee-utf8.h"
|
||||
|
||||
|
||||
/*
|
||||
* strndup: define strndup function if not existing (FreeBSD and maybe other)
|
||||
*/
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char *
|
||||
strndup (char *string, int length)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if ((int)strlen (string) < length)
|
||||
return strdup (string);
|
||||
|
||||
result = (char *)malloc (length + 1);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
memcpy (result, string, length);
|
||||
result[length] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* string_tolower: locale independant string conversion to lower case
|
||||
*/
|
||||
|
||||
void
|
||||
string_tolower (char *string)
|
||||
{
|
||||
while (string && string[0])
|
||||
{
|
||||
if ((string[0] >= 'A') && (string[0] <= 'Z'))
|
||||
string[0] += ('a' - 'A');
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* string_toupper: locale independant string conversion to upper case
|
||||
*/
|
||||
|
||||
void
|
||||
string_toupper (char *string)
|
||||
{
|
||||
while (string && string[0])
|
||||
{
|
||||
if ((string[0] >= 'a') && (string[0] <= 'z'))
|
||||
string[0] -= ('a' - 'A');
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* string_strcasecmp: locale and case independent string comparison
|
||||
*/
|
||||
|
||||
int
|
||||
string_strcasecmp (char *string1, char *string2)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
if (!string1 || !string2)
|
||||
return (string1) ? 1 : ((string2) ? -1 : 0);
|
||||
|
||||
while (string1[0] && string2[0])
|
||||
{
|
||||
c1 = (int)((unsigned char) string1[0]);
|
||||
c2 = (int)((unsigned char) string2[0]);
|
||||
|
||||
if ((c1 >= 'A') && (c1 <= 'Z'))
|
||||
c1 += ('a' - 'A');
|
||||
|
||||
if ((c2 >= 'A') && (c2 <= 'Z'))
|
||||
c2 += ('a' - 'A');
|
||||
|
||||
if ((c1 - c2) != 0)
|
||||
return c1 - c2;
|
||||
|
||||
string1++;
|
||||
string2++;
|
||||
}
|
||||
|
||||
return (string1[0]) ? 1 : ((string2[0]) ? -1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* string_strncasecmp: locale and case independent string comparison
|
||||
* with max length
|
||||
*/
|
||||
|
||||
int
|
||||
string_strncasecmp (char *string1, char *string2, int max)
|
||||
{
|
||||
int c1, c2, count;
|
||||
|
||||
if (!string1 || !string2)
|
||||
return (string1) ? 1 : ((string2) ? -1 : 0);
|
||||
|
||||
count = 0;
|
||||
while ((count < max) && string1[0] && string2[0])
|
||||
{
|
||||
c1 = (int)((unsigned char) string1[0]);
|
||||
c2 = (int)((unsigned char) string2[0]);
|
||||
|
||||
if ((c1 >= 'A') && (c1 <= 'Z'))
|
||||
c1 += ('a' - 'A');
|
||||
|
||||
if ((c2 >= 'A') && (c2 <= 'Z'))
|
||||
c2 += ('a' - 'A');
|
||||
|
||||
if ((c1 - c2) != 0)
|
||||
return c1 - c2;
|
||||
|
||||
string1++;
|
||||
string2++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count >= max)
|
||||
return 0;
|
||||
else
|
||||
return (string1[0]) ? 1 : ((string2[0]) ? -1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* string_strcasestr: locale and case independent string search
|
||||
*/
|
||||
|
||||
char *
|
||||
string_strcasestr (char *string, char *search)
|
||||
{
|
||||
int length_search;
|
||||
|
||||
length_search = strlen (search);
|
||||
|
||||
if (!string || !search || (length_search == 0))
|
||||
return NULL;
|
||||
|
||||
while (string[0])
|
||||
{
|
||||
if (string_strncasecmp (string, search, length_search) == 0)
|
||||
return string;
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_replace: replace a string by new one in a string
|
||||
* note: returned value has to be free() after use
|
||||
*/
|
||||
|
||||
char *
|
||||
string_replace (char *string, char *search, char *replace)
|
||||
{
|
||||
char *pos, *new_string;
|
||||
int length1, length2, length_new, count;
|
||||
|
||||
if (!string || !search || !replace)
|
||||
return NULL;
|
||||
|
||||
length1 = strlen (search);
|
||||
length2 = strlen (replace);
|
||||
|
||||
/* count number of strings to replace */
|
||||
count = 0;
|
||||
pos = string;
|
||||
while (pos && pos[0] && (pos = strstr (pos, search)))
|
||||
{
|
||||
count++;
|
||||
pos += length1;
|
||||
}
|
||||
|
||||
/* easy: no string to replace! */
|
||||
if (count == 0)
|
||||
return strdup (string);
|
||||
|
||||
/* compute needed memory for new string */
|
||||
length_new = strlen (string) - (count * length1) + (count * length2) + 1;
|
||||
|
||||
/* allocate new string */
|
||||
new_string = (char *)malloc (length_new * sizeof (char));
|
||||
if (!new_string)
|
||||
return strdup (string);
|
||||
|
||||
/* replace all occurences */
|
||||
new_string[0] = '\0';
|
||||
while (string && string[0])
|
||||
{
|
||||
pos = strstr (string, search);
|
||||
if (pos)
|
||||
{
|
||||
strncat (new_string, string, pos - string);
|
||||
strcat (new_string, replace);
|
||||
pos += length1;
|
||||
}
|
||||
else
|
||||
strcat (new_string, string);
|
||||
string = pos;
|
||||
}
|
||||
return new_string;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_convert_hex_chars: convert hex chars (\x??) to value
|
||||
*/
|
||||
|
||||
char *
|
||||
string_convert_hex_chars (char *string)
|
||||
{
|
||||
char *output, hex_str[8], *error;
|
||||
int pos_output;
|
||||
long number;
|
||||
|
||||
output = (char *)malloc (strlen (string) + 1);
|
||||
if (output)
|
||||
{
|
||||
pos_output = 0;
|
||||
while (string && string[0])
|
||||
{
|
||||
if (string[0] == '\\')
|
||||
{
|
||||
string++;
|
||||
switch (string[0])
|
||||
{
|
||||
case '\\':
|
||||
output[pos_output++] = '\\';
|
||||
string++;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (isxdigit (string[1])
|
||||
&& isxdigit (string[2]))
|
||||
{
|
||||
snprintf (hex_str, sizeof (hex_str),
|
||||
"0x%c%c", string[1], string[2]);
|
||||
number = strtol (hex_str, &error, 16);
|
||||
if (error && (error[0] == '\0'))
|
||||
{
|
||||
output[pos_output++] = number;
|
||||
string += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = '\\';
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
output[pos_output++] = '\\';
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
}
|
||||
}
|
||||
output[pos_output] = '\0';
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_explode: explode a string according to separators
|
||||
*/
|
||||
|
||||
char **
|
||||
string_explode (char *string, char *separators, int num_items_max,
|
||||
int *num_items)
|
||||
{
|
||||
int i, n_items;
|
||||
char **array;
|
||||
char *ptr, *ptr1, *ptr2;
|
||||
|
||||
if (num_items != NULL)
|
||||
*num_items = 0;
|
||||
|
||||
if (!string || !string[0])
|
||||
return NULL;
|
||||
|
||||
/* calculate number of items */
|
||||
ptr = string;
|
||||
i = 1;
|
||||
while ((ptr = strpbrk (ptr, separators)))
|
||||
{
|
||||
while (strchr (separators, ptr[0]) != NULL)
|
||||
ptr++;
|
||||
i++;
|
||||
}
|
||||
n_items = i;
|
||||
|
||||
if ((num_items_max != 0) && (n_items > num_items_max))
|
||||
n_items = num_items_max;
|
||||
|
||||
array =
|
||||
(char **) malloc ((n_items + 1) * sizeof (char *));
|
||||
|
||||
ptr1 = string;
|
||||
ptr2 = string;
|
||||
|
||||
for (i = 0; i < n_items; i++)
|
||||
{
|
||||
while (strchr (separators, ptr1[0]) != NULL)
|
||||
ptr1++;
|
||||
if (i == (n_items - 1) || (ptr2 = strpbrk (ptr1, separators)) == NULL)
|
||||
if ((ptr2 = strchr (ptr1, '\r')) == NULL)
|
||||
if ((ptr2 = strchr (ptr1, '\n')) == NULL)
|
||||
ptr2 = strchr (ptr1, '\0');
|
||||
|
||||
if ((ptr1 == NULL) || (ptr2 == NULL))
|
||||
{
|
||||
array[i] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr2 - ptr1 > 0)
|
||||
{
|
||||
array[i] =
|
||||
(char *) malloc ((ptr2 - ptr1 + 1) * sizeof (char));
|
||||
array[i] = strncpy (array[i], ptr1, ptr2 - ptr1);
|
||||
array[i][ptr2 - ptr1] = '\0';
|
||||
ptr1 = ++ptr2;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array[i] = NULL;
|
||||
if (num_items != NULL)
|
||||
*num_items = i;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_free_exploded: free an exploded string
|
||||
*/
|
||||
|
||||
void
|
||||
string_free_exploded (char **exploded_string)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (exploded_string)
|
||||
{
|
||||
for (i = 0; exploded_string[i]; i++)
|
||||
free (exploded_string[i]);
|
||||
free (exploded_string);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* string_split_multi_command: split a list of commands separated by 'sep'
|
||||
* and ecscaped with '\'
|
||||
* - empty commands are removed
|
||||
* - spaces on the left of each commands are stripped
|
||||
* Result must be freed with free_multi_command
|
||||
*/
|
||||
|
||||
char **
|
||||
string_split_multi_command (char *command, char sep)
|
||||
{
|
||||
int nb_substr, arr_idx, str_idx, type;
|
||||
char **array;
|
||||
char *buffer, *ptr, *p;
|
||||
|
||||
if (command == NULL)
|
||||
return NULL;
|
||||
|
||||
nb_substr = 1;
|
||||
ptr = command;
|
||||
while ( (p = strchr(ptr, sep)) != NULL)
|
||||
{
|
||||
nb_substr++;
|
||||
ptr = ++p;
|
||||
}
|
||||
|
||||
array = (char **) malloc ((nb_substr + 1) * sizeof(char *));
|
||||
if (!array)
|
||||
return NULL;
|
||||
|
||||
buffer = (char *) malloc ( (strlen(command) + 1) * sizeof (char));
|
||||
if (!buffer)
|
||||
{
|
||||
free (array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = command;
|
||||
str_idx = 0;
|
||||
arr_idx = 0;
|
||||
while(*ptr != '\0')
|
||||
{
|
||||
type = 0;
|
||||
if (*ptr == ';')
|
||||
{
|
||||
if (ptr == command)
|
||||
type = 1;
|
||||
else if ( *(ptr-1) != '\\')
|
||||
type = 1;
|
||||
else if ( *(ptr-1) == '\\')
|
||||
type = 2;
|
||||
}
|
||||
if (type == 1)
|
||||
{
|
||||
buffer[str_idx] = '\0';
|
||||
str_idx = -1;
|
||||
p = buffer;
|
||||
/* strip white spaces a the begining of the line */
|
||||
while (*p == ' ') p++;
|
||||
if (p && p[0])
|
||||
array[arr_idx++] = strdup (p);
|
||||
}
|
||||
else if (type == 2)
|
||||
buffer[--str_idx] = *ptr;
|
||||
else
|
||||
buffer[str_idx] = *ptr;
|
||||
str_idx++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
buffer[str_idx] = '\0';
|
||||
p = buffer;
|
||||
while (*p == ' ') p++;
|
||||
if (p && p[0])
|
||||
array[arr_idx++] = strdup (p);
|
||||
|
||||
array[arr_idx] = NULL;
|
||||
|
||||
free (buffer);
|
||||
|
||||
array = (char **) realloc (array, (arr_idx + 1) * sizeof(char *));
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_free_multi_command : free a list of commands splitted
|
||||
* with split_multi_command
|
||||
*/
|
||||
|
||||
void
|
||||
string_free_multi_command (char **commands)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (commands)
|
||||
{
|
||||
for (i = 0; commands[i]; i++)
|
||||
free (commands[i]);
|
||||
free (commands);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* string_iconv: convert string to another charset
|
||||
*/
|
||||
|
||||
char *
|
||||
string_iconv (int from_utf8, char *from_code, char *to_code, char *string)
|
||||
{
|
||||
char *outbuf;
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
iconv_t cd;
|
||||
char *inbuf, *ptr_inbuf, *ptr_outbuf, *next_char;
|
||||
char *ptr_inbuf_shift;
|
||||
int done;
|
||||
size_t err, inbytesleft, outbytesleft;
|
||||
|
||||
if (from_code && from_code[0] && to_code && to_code[0]
|
||||
&& (string_strcasecmp(from_code, to_code) != 0))
|
||||
{
|
||||
cd = iconv_open (to_code, from_code);
|
||||
if (cd == (iconv_t)(-1))
|
||||
outbuf = strdup (string);
|
||||
else
|
||||
{
|
||||
inbuf = strdup (string);
|
||||
ptr_inbuf = inbuf;
|
||||
inbytesleft = strlen (inbuf);
|
||||
outbytesleft = inbytesleft * 4;
|
||||
outbuf = (char *) malloc (outbytesleft + 2);
|
||||
ptr_outbuf = outbuf;
|
||||
ptr_inbuf_shift = NULL;
|
||||
done = 0;
|
||||
while (!done)
|
||||
{
|
||||
err = iconv (cd, (ICONV_CONST char **)(&ptr_inbuf), &inbytesleft,
|
||||
&ptr_outbuf, &outbytesleft);
|
||||
if (err == (size_t)(-1))
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
done = 1;
|
||||
break;
|
||||
case E2BIG:
|
||||
done = 1;
|
||||
break;
|
||||
case EILSEQ:
|
||||
if (from_utf8)
|
||||
{
|
||||
next_char = utf8_next_char (ptr_inbuf);
|
||||
if (next_char)
|
||||
{
|
||||
inbytesleft -= next_char - ptr_inbuf;
|
||||
ptr_inbuf = next_char;
|
||||
}
|
||||
else
|
||||
{
|
||||
inbytesleft--;
|
||||
ptr_inbuf++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr_inbuf++;
|
||||
inbytesleft--;
|
||||
}
|
||||
ptr_outbuf[0] = '?';
|
||||
ptr_outbuf++;
|
||||
outbytesleft--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ptr_inbuf_shift)
|
||||
{
|
||||
ptr_inbuf_shift = ptr_inbuf;
|
||||
ptr_inbuf = NULL;
|
||||
inbytesleft = 0;
|
||||
}
|
||||
else
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
if (ptr_inbuf_shift)
|
||||
ptr_inbuf = ptr_inbuf_shift;
|
||||
ptr_outbuf[0] = '\0';
|
||||
free (inbuf);
|
||||
iconv_close (cd);
|
||||
}
|
||||
}
|
||||
else
|
||||
outbuf = strdup (string);
|
||||
#else
|
||||
/* make C compiler happy */
|
||||
(void) from_utf8;
|
||||
(void) from_code;
|
||||
(void) to_code;
|
||||
outbuf = strdup (string);
|
||||
#endif /* HAVE_ICONV */
|
||||
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_iconv_to_internal: convert user string (input, script, ..) to
|
||||
* WeeChat internal storage charset
|
||||
*/
|
||||
|
||||
char *
|
||||
string_iconv_to_internal (char *charset, char *string)
|
||||
{
|
||||
char *input, *output;
|
||||
|
||||
input = strdup (string);
|
||||
|
||||
/* optimize for UTF-8: if charset is NULL => we use term charset =>
|
||||
if ths charset is already UTF-8, then no iconv needed */
|
||||
if (local_utf8 && (!charset || !charset[0]))
|
||||
return input;
|
||||
|
||||
if (input)
|
||||
{
|
||||
if (utf8_has_8bits (input) && utf8_is_valid (input, NULL))
|
||||
return input;
|
||||
|
||||
output = string_iconv (0,
|
||||
(charset && charset[0]) ?
|
||||
charset : local_charset,
|
||||
WEECHAT_INTERNAL_CHARSET,
|
||||
input);
|
||||
utf8_normalize (output, '?');
|
||||
free (input);
|
||||
return output;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_iconv_from_internal: convert internal string to terminal charset,
|
||||
* for display
|
||||
*/
|
||||
|
||||
char *
|
||||
string_iconv_from_internal (char *charset, char *string)
|
||||
{
|
||||
char *input, *output;
|
||||
|
||||
input = strdup (string);
|
||||
|
||||
/* optimize for UTF-8: if charset is NULL => we use term charset =>
|
||||
if ths charset is already UTF-8, then no iconv needed */
|
||||
if (local_utf8 && (!charset || !charset[0]))
|
||||
return input;
|
||||
|
||||
if (input)
|
||||
{
|
||||
utf8_normalize (input, '?');
|
||||
output = string_iconv (1,
|
||||
WEECHAT_INTERNAL_CHARSET,
|
||||
(charset && charset[0]) ?
|
||||
charset : local_charset,
|
||||
input);
|
||||
free (input);
|
||||
return output;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* string_iconv_fprintf: encode to terminal charset, then call fprintf on a file
|
||||
*/
|
||||
|
||||
void
|
||||
string_iconv_fprintf (FILE *file, char *data, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
static char buf[4096];
|
||||
char *buf2;
|
||||
|
||||
va_start (argptr, data);
|
||||
vsnprintf (buf, sizeof (buf) - 1, data, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
buf2 = string_iconv_from_internal (NULL, buf);
|
||||
fprintf (file, "%s", (buf2) ? buf2 : buf);
|
||||
if (buf2)
|
||||
free (buf2);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org>
|
||||
* See README for License detail, AUTHORS for developers list.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __WEECHAT_STRING_H
|
||||
#define __WEECHAT_STRING_H 1
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
extern char *strndup (char *, int);
|
||||
#endif
|
||||
extern void string_tolower (char *);
|
||||
extern void string_toupper (char *);
|
||||
extern int string_strcasecmp (char *, char *);
|
||||
extern int string_strncasecmp (char *, char *, int);
|
||||
extern char *string_strcasestr (char *, char *);
|
||||
extern char *string_replace (char *, char *, char *);
|
||||
extern char *string_convert_hex_chars (char *);
|
||||
extern char **string_explode (char *, char *, int, int *);
|
||||
extern void string_free_exploded (char **);
|
||||
extern char **string_split_multi_command (char *, char);
|
||||
extern void string_free_multi_command (char **);
|
||||
extern char *string_iconv (int, char *, char *, char *);
|
||||
extern char *string_iconv_to_internal (char *, char *);
|
||||
extern char *string_iconv_from_internal (char *, char *);
|
||||
extern void string_iconv_fprintf (FILE *, char *, ...);
|
||||
|
||||
#endif /* wee-string.h */
|
Loading…
Reference in New Issue