2000-04-26 04:03:38 -04:00
|
|
|
/*
|
|
|
|
misc.c : irssi
|
|
|
|
|
|
|
|
Copyright (C) 1999 Timo Sirainen
|
|
|
|
|
|
|
|
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 2 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.
|
|
|
|
|
2007-05-08 14:41:10 -04:00
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2000-04-26 04:03:38 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "module.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
2000-10-26 14:12:20 -04:00
|
|
|
#ifdef HAVE_REGEX_H
|
|
|
|
# include <regex.h>
|
|
|
|
#endif
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
typedef struct {
|
2000-11-23 18:29:32 -05:00
|
|
|
int condition;
|
2000-04-26 04:03:38 -04:00
|
|
|
GInputFunction function;
|
2000-07-16 16:18:05 -04:00
|
|
|
void *data;
|
2000-04-26 04:03:38 -04:00
|
|
|
} IRSSI_INPUT_REC;
|
|
|
|
|
2000-07-16 16:18:05 -04:00
|
|
|
static int irssi_io_invoke(GIOChannel *source, GIOCondition condition,
|
|
|
|
void *data)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
IRSSI_INPUT_REC *rec = data;
|
2000-11-23 18:29:32 -05:00
|
|
|
int icond = 0;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-08-14 20:22:08 -04:00
|
|
|
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
|
|
|
|
/* error, we have to call the function.. */
|
|
|
|
if (rec->condition & G_IO_IN)
|
|
|
|
icond |= G_INPUT_READ;
|
|
|
|
else
|
|
|
|
icond |= G_INPUT_WRITE;
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
if (condition & (G_IO_IN | G_IO_PRI))
|
|
|
|
icond |= G_INPUT_READ;
|
|
|
|
if (condition & G_IO_OUT)
|
|
|
|
icond |= G_INPUT_WRITE;
|
|
|
|
|
2000-12-04 17:57:18 -05:00
|
|
|
if (rec->condition & icond)
|
|
|
|
rec->function(rec->data, source, icond);
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2000-12-04 17:57:18 -05:00
|
|
|
int g_input_add_full(GIOChannel *source, int priority, int condition,
|
2000-10-01 18:12:01 -04:00
|
|
|
GInputFunction function, void *data)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
IRSSI_INPUT_REC *rec;
|
|
|
|
unsigned int result;
|
2000-08-14 20:22:08 -04:00
|
|
|
GIOCondition cond;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
rec = g_new(IRSSI_INPUT_REC, 1);
|
|
|
|
rec->condition = condition;
|
|
|
|
rec->function = function;
|
|
|
|
rec->data = data;
|
|
|
|
|
2000-11-23 16:40:07 -05:00
|
|
|
cond = (GIOCondition) (G_IO_ERR|G_IO_HUP|G_IO_NVAL);
|
2000-04-26 04:03:38 -04:00
|
|
|
if (condition & G_INPUT_READ)
|
2000-08-14 20:22:08 -04:00
|
|
|
cond |= G_IO_IN|G_IO_PRI;
|
2000-04-26 04:03:38 -04:00
|
|
|
if (condition & G_INPUT_WRITE)
|
|
|
|
cond |= G_IO_OUT;
|
|
|
|
|
2000-12-04 17:57:18 -05:00
|
|
|
result = g_io_add_watch_full(source, priority, cond,
|
2000-04-26 04:03:38 -04:00
|
|
|
irssi_io_invoke, rec, g_free);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2000-12-04 17:57:18 -05:00
|
|
|
int g_input_add(GIOChannel *source, int condition,
|
2000-10-01 18:12:01 -04:00
|
|
|
GInputFunction function, void *data)
|
|
|
|
{
|
|
|
|
return g_input_add_full(source, G_PRIORITY_DEFAULT, condition,
|
|
|
|
function, data);
|
|
|
|
}
|
|
|
|
|
2008-04-25 04:42:47 -04:00
|
|
|
/* easy way to bypass glib polling of io channel internal buffer */
|
|
|
|
int g_input_add_poll(int fd, int priority, int condition,
|
|
|
|
GInputFunction function, void *data)
|
|
|
|
{
|
|
|
|
GIOChannel *source = g_io_channel_unix_new(fd);
|
|
|
|
int ret = g_input_add_full(source, priority, condition, function, data);
|
|
|
|
g_io_channel_unref(source);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2000-11-30 18:12:42 -05:00
|
|
|
int g_timeval_cmp(const GTimeVal *tv1, const GTimeVal *tv2)
|
|
|
|
{
|
|
|
|
if (tv1->tv_sec < tv2->tv_sec)
|
|
|
|
return -1;
|
|
|
|
if (tv1->tv_sec > tv2->tv_sec)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return tv1->tv_usec < tv2->tv_usec ? -1 :
|
|
|
|
tv1->tv_usec > tv2->tv_usec ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
long get_timeval_diff(const GTimeVal *tv1, const GTimeVal *tv2)
|
|
|
|
{
|
|
|
|
long secs, usecs;
|
|
|
|
|
|
|
|
secs = tv1->tv_sec - tv2->tv_sec;
|
|
|
|
usecs = tv1->tv_usec - tv2->tv_usec;
|
|
|
|
if (usecs < 0) {
|
|
|
|
usecs += 1000000;
|
|
|
|
secs--;
|
|
|
|
}
|
|
|
|
usecs = usecs/1000 + secs * 1000;
|
|
|
|
|
|
|
|
return usecs;
|
|
|
|
}
|
|
|
|
|
|
|
|
int find_substr(const char *list, const char *item)
|
|
|
|
{
|
|
|
|
const char *ptr;
|
|
|
|
|
|
|
|
g_return_val_if_fail(list != NULL, FALSE);
|
|
|
|
g_return_val_if_fail(item != NULL, FALSE);
|
|
|
|
|
|
|
|
if (*item == '\0')
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (;;) {
|
2002-01-27 15:45:59 -05:00
|
|
|
while (i_isspace(*list)) list++;
|
2000-04-26 04:03:38 -04:00
|
|
|
if (*list == '\0') break;
|
|
|
|
|
|
|
|
ptr = strchr(list, ' ');
|
|
|
|
if (ptr == NULL) ptr = list+strlen(list);
|
|
|
|
|
2014-06-10 12:06:19 -04:00
|
|
|
if (g_ascii_strncasecmp(list, item, ptr-list) == 0 &&
|
2000-07-16 16:18:05 -04:00
|
|
|
item[ptr-list] == '\0')
|
2000-04-26 04:03:38 -04:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
list = ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int strarray_length(char **array)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
g_return_val_if_fail(array != NULL, 0);
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
while (*array) {
|
|
|
|
len++;
|
|
|
|
array++;
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
int strarray_find(char **array, const char *item)
|
|
|
|
{
|
|
|
|
char **tmp;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
g_return_val_if_fail(array != NULL, 0);
|
|
|
|
g_return_val_if_fail(item != NULL, 0);
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
for (tmp = array; *tmp != NULL; tmp++, index++) {
|
2014-06-10 12:06:19 -04:00
|
|
|
if (g_ascii_strcasecmp(*tmp, item) == 0)
|
2000-04-26 04:03:38 -04:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
GSList *gslist_find_string(GSList *list, const char *key)
|
|
|
|
{
|
2014-07-07 16:26:04 -04:00
|
|
|
for (; list != NULL; list = list->next)
|
2015-04-07 21:39:05 -04:00
|
|
|
if (g_strcmp0(list->data, key) == 0) return list;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GSList *gslist_find_icase_string(GSList *list, const char *key)
|
|
|
|
{
|
2014-07-07 16:26:04 -04:00
|
|
|
for (; list != NULL; list = list->next)
|
2014-06-10 12:06:19 -04:00
|
|
|
if (g_ascii_strcasecmp(list->data, key) == 0) return list;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-08-26 11:39:44 -04:00
|
|
|
void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
while (list != NULL) {
|
2000-08-26 11:39:44 -04:00
|
|
|
ret = func(list->data, (void *) data);
|
2000-04-26 04:03:38 -04:00
|
|
|
if (ret != NULL) return ret;
|
|
|
|
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-06-17 21:18:12 -04:00
|
|
|
/* `list' contains pointer to structure with a char* to string. */
|
|
|
|
char *gslistptr_to_string(GSList *list, int offset, const char *delimiter)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
GString *str;
|
|
|
|
char **data, *ret;
|
|
|
|
|
|
|
|
str = g_string_new(NULL);
|
|
|
|
while (list != NULL) {
|
|
|
|
data = G_STRUCT_MEMBER_P(list->data, offset);
|
|
|
|
|
|
|
|
if (str->len != 0) g_string_append(str, delimiter);
|
|
|
|
g_string_append(str, *data);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = str->str;
|
|
|
|
g_string_free(str, FALSE);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2000-06-17 21:18:12 -04:00
|
|
|
/* `list' contains char* */
|
|
|
|
char *gslist_to_string(GSList *list, const char *delimiter)
|
|
|
|
{
|
|
|
|
GString *str;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
str = g_string_new(NULL);
|
|
|
|
while (list != NULL) {
|
|
|
|
if (str->len != 0) g_string_append(str, delimiter);
|
|
|
|
g_string_append(str, list->data);
|
|
|
|
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = str->str;
|
|
|
|
g_string_free(str, FALSE);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hash_save_key(char *key, void *value, GSList **list)
|
|
|
|
{
|
|
|
|
*list = g_slist_append(*list, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save all keys in hash table to linked list - you shouldn't remove any
|
|
|
|
items while using this list, use g_slist_free() after you're done with it */
|
|
|
|
GSList *hashtable_get_keys(GHashTable *hash)
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
list = NULL;
|
|
|
|
g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
GList *glist_find_string(GList *list, const char *key)
|
|
|
|
{
|
2014-07-07 16:26:04 -04:00
|
|
|
for (; list != NULL; list = list->next)
|
2015-04-07 21:39:05 -04:00
|
|
|
if (g_strcmp0(list->data, key) == 0) return list;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GList *glist_find_icase_string(GList *list, const char *key)
|
|
|
|
{
|
2014-07-07 16:26:04 -04:00
|
|
|
for (; list != NULL; list = list->next)
|
2014-06-10 12:06:19 -04:00
|
|
|
if (g_ascii_strcasecmp(list->data, key) == 0) return list;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *stristr(const char *data, const char *key)
|
|
|
|
{
|
2000-11-06 20:25:46 -05:00
|
|
|
const char *max;
|
|
|
|
int keylen, datalen, pos;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
keylen = strlen(key);
|
|
|
|
datalen = strlen(data);
|
|
|
|
|
2000-11-29 20:14:49 -05:00
|
|
|
if (keylen > datalen)
|
2000-04-26 04:03:38 -04:00
|
|
|
return NULL;
|
2000-11-29 20:14:49 -05:00
|
|
|
if (keylen == 0)
|
|
|
|
return (char *) data;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
max = data+datalen-keylen;
|
2000-11-06 20:25:46 -05:00
|
|
|
pos = 0;
|
|
|
|
while (data <= max) {
|
|
|
|
if (key[pos] == '\0')
|
|
|
|
return (char *) data;
|
|
|
|
|
2002-01-27 15:45:59 -05:00
|
|
|
if (i_toupper(data[pos]) == i_toupper(key[pos]))
|
2000-11-06 20:25:46 -05:00
|
|
|
pos++;
|
|
|
|
else {
|
|
|
|
data++;
|
|
|
|
pos = 0;
|
|
|
|
}
|
2000-07-10 19:00:56 -04:00
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define isbound(c) \
|
|
|
|
((unsigned char) (c) < 128 && \
|
2002-01-27 15:45:59 -05:00
|
|
|
(i_isspace(c) || i_ispunct(c)))
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2008-03-28 08:59:26 -04:00
|
|
|
static char *strstr_full_case(const char *data, const char *key, int icase)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-11-06 20:25:46 -05:00
|
|
|
const char *start, *max;
|
2001-03-03 12:34:35 -05:00
|
|
|
int keylen, datalen, pos, match;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
keylen = strlen(key);
|
|
|
|
datalen = strlen(data);
|
|
|
|
|
2000-11-29 20:14:49 -05:00
|
|
|
if (keylen > datalen)
|
2000-04-26 04:03:38 -04:00
|
|
|
return NULL;
|
2000-11-29 20:14:49 -05:00
|
|
|
if (keylen == 0)
|
|
|
|
return (char *) data;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
max = data+datalen-keylen;
|
2000-11-06 20:25:46 -05:00
|
|
|
start = data; pos = 0;
|
|
|
|
while (data <= max) {
|
|
|
|
if (key[pos] == '\0') {
|
|
|
|
if (data[pos] != '\0' && !isbound(data[pos])) {
|
|
|
|
data++;
|
|
|
|
pos = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return (char *) data;
|
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2002-01-27 15:45:59 -05:00
|
|
|
match = icase ? (i_toupper(data[pos]) == i_toupper(key[pos])) :
|
2001-03-03 12:34:35 -05:00
|
|
|
data[pos] == key[pos];
|
|
|
|
|
|
|
|
if (match && (pos != 0 || data == start || isbound(data[-1])))
|
2000-11-06 20:25:46 -05:00
|
|
|
pos++;
|
|
|
|
else {
|
|
|
|
data++;
|
|
|
|
pos = 0;
|
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-03-03 12:34:35 -05:00
|
|
|
char *strstr_full(const char *data, const char *key)
|
|
|
|
{
|
|
|
|
return strstr_full_case(data, key, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *stristr_full(const char *data, const char *key)
|
|
|
|
{
|
|
|
|
return strstr_full_case(data, key, TRUE);
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
int regexp_match(const char *str, const char *regexp)
|
|
|
|
{
|
2000-10-26 14:12:20 -04:00
|
|
|
#ifdef HAVE_REGEX_H
|
2000-04-26 04:03:38 -04:00
|
|
|
regex_t preg;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (regcomp(&preg, regexp, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = regexec(&preg, str, 0, NULL, 0);
|
|
|
|
regfree(&preg);
|
|
|
|
|
|
|
|
return ret == 0;
|
2000-10-26 14:12:20 -04:00
|
|
|
#else
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2000-08-12 11:50:50 -04:00
|
|
|
/* Create the directory and all it's parent directories */
|
|
|
|
int mkpath(const char *path, int mode)
|
|
|
|
{
|
|
|
|
struct stat statbuf;
|
2000-10-26 14:12:20 -04:00
|
|
|
const char *p;
|
2000-08-12 11:50:50 -04:00
|
|
|
char *dir;
|
|
|
|
|
|
|
|
g_return_val_if_fail(path != NULL, -1);
|
|
|
|
|
|
|
|
p = g_path_skip_root((char *) path);
|
2000-11-25 15:54:24 -05:00
|
|
|
if (p == NULL) {
|
|
|
|
/* not a full path, maybe not what we wanted
|
|
|
|
but continue anyway.. */
|
|
|
|
p = path;
|
|
|
|
}
|
2000-08-12 11:50:50 -04:00
|
|
|
for (;;) {
|
|
|
|
if (*p != G_DIR_SEPARATOR && *p != '\0') {
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dir = g_strndup(path, (int) (p-path));
|
|
|
|
if (stat(dir, &statbuf) != 0) {
|
2000-10-26 14:12:20 -04:00
|
|
|
#ifndef WIN32
|
2002-01-04 16:27:28 -05:00
|
|
|
if (mkdir(dir, mode) == -1)
|
2000-10-26 14:12:20 -04:00
|
|
|
#else
|
2002-01-04 16:27:28 -05:00
|
|
|
if (_mkdir(dir) == -1)
|
2000-10-26 14:12:20 -04:00
|
|
|
#endif
|
2002-01-04 16:27:28 -05:00
|
|
|
{
|
2000-08-12 11:50:50 -04:00
|
|
|
g_free(dir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_free(dir);
|
|
|
|
|
|
|
|
if (*p++ == '\0')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert ~/ to $HOME */
|
2000-04-26 04:03:38 -04:00
|
|
|
char *convert_home(const char *path)
|
|
|
|
{
|
2002-10-19 13:48:10 -04:00
|
|
|
const char *home;
|
|
|
|
|
|
|
|
if (*path == '~' && (*(path+1) == '/' || *(path+1) == '\0')) {
|
|
|
|
home = g_get_home_dir();
|
|
|
|
if (home == NULL)
|
|
|
|
home = ".";
|
|
|
|
|
|
|
|
return g_strconcat(home, path+1, NULL);
|
|
|
|
} else {
|
|
|
|
return g_strdup(path);
|
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int g_istr_equal(gconstpointer v, gconstpointer v2)
|
|
|
|
{
|
2014-06-10 12:06:19 -04:00
|
|
|
return g_ascii_strcasecmp((const char *) v, (const char *) v2) == 0;
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2000-06-17 09:16:42 -04:00
|
|
|
int g_istr_cmp(gconstpointer v, gconstpointer v2)
|
|
|
|
{
|
2014-06-10 12:06:19 -04:00
|
|
|
return g_ascii_strcasecmp((const char *) v, (const char *) v2);
|
2000-06-17 09:16:42 -04:00
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
/* a char* hash function from ASU */
|
|
|
|
unsigned int g_istr_hash(gconstpointer v)
|
|
|
|
{
|
2000-07-10 19:00:56 -04:00
|
|
|
const char *s = (const char *) v;
|
2000-04-26 04:03:38 -04:00
|
|
|
unsigned int h = 0, g;
|
|
|
|
|
|
|
|
while (*s != '\0') {
|
2002-01-27 15:45:59 -05:00
|
|
|
h = (h << 4) + i_toupper(*s);
|
2000-07-10 19:00:56 -04:00
|
|
|
if ((g = h & 0xf0000000UL)) {
|
2000-04-26 04:03:38 -04:00
|
|
|
h = h ^ (g >> 24);
|
|
|
|
h = h ^ g;
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return h /* % M */;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find `mask' from `data', you can use * and ? wildcards. */
|
|
|
|
int match_wildcards(const char *cmask, const char *data)
|
|
|
|
{
|
|
|
|
char *mask, *newmask, *p1, *p2;
|
|
|
|
int ret;
|
|
|
|
|
2000-05-09 07:42:42 -04:00
|
|
|
newmask = mask = g_strdup(cmask);
|
2000-04-26 04:03:38 -04:00
|
|
|
for (; *mask != '\0' && *data != '\0'; mask++) {
|
2000-06-01 13:17:45 -04:00
|
|
|
if (*mask != '*') {
|
2002-01-27 15:45:59 -05:00
|
|
|
if (*mask != '?' && i_toupper(*mask) != i_toupper(*data))
|
2000-06-01 13:17:45 -04:00
|
|
|
break;
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
data++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*mask == '?' || *mask == '*') mask++;
|
|
|
|
if (*mask == '\0') {
|
|
|
|
data += strlen(data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p1 = strchr(mask, '*');
|
|
|
|
p2 = strchr(mask, '?');
|
|
|
|
if (p1 == NULL || (p2 < p1 && p2 != NULL)) p1 = p2;
|
|
|
|
|
|
|
|
if (p1 != NULL) *p1 = '\0';
|
|
|
|
|
|
|
|
data = stristr(data, mask);
|
|
|
|
if (data == NULL) break;
|
|
|
|
|
|
|
|
data += strlen(mask);
|
|
|
|
mask += strlen(mask)-1;
|
|
|
|
|
|
|
|
if (p1 != NULL) *p1 = p1 == p2 ? '?' : '*';
|
|
|
|
}
|
|
|
|
|
2000-10-13 17:47:32 -04:00
|
|
|
while (*mask == '*') mask++;
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
ret = data != NULL && *data == '\0' && *mask == '\0';
|
2000-05-25 07:30:47 -04:00
|
|
|
g_free(newmask);
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return TRUE if all characters in `str' are numbers.
|
|
|
|
Stop when `end_char' is found from string. */
|
|
|
|
int is_numeric(const char *str, char end_char)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail(str != NULL, FALSE);
|
|
|
|
|
2000-07-23 07:54:54 -04:00
|
|
|
if (*str == '\0' || *str == end_char)
|
|
|
|
return FALSE;
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
while (*str != '\0' && *str != end_char) {
|
2002-01-27 15:45:59 -05:00
|
|
|
if (!i_isdigit(*str)) return FALSE;
|
2000-04-26 04:03:38 -04:00
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* replace all `from' chars in string to `to' chars. returns `str' */
|
|
|
|
char *replace_chars(char *str, char from, char to)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
for (p = str; *p != '\0'; p++) {
|
|
|
|
if (*p == from) *p = to;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
int octal2dec(int octal)
|
|
|
|
{
|
|
|
|
int dec, n;
|
|
|
|
|
|
|
|
dec = 0; n = 1;
|
|
|
|
while (octal != 0) {
|
|
|
|
dec += n*(octal%10);
|
|
|
|
octal /= 10; n *= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dec;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dec2octal(int decimal)
|
|
|
|
{
|
|
|
|
int octal, pos;
|
|
|
|
|
|
|
|
octal = 0; pos = 0;
|
|
|
|
while (decimal > 0) {
|
|
|
|
octal += (decimal & 7)*(pos == 0 ? 1 : pos);
|
|
|
|
decimal /= 8;
|
|
|
|
pos += 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
return octal;
|
|
|
|
}
|
2000-06-30 15:54:34 -04:00
|
|
|
|
2002-11-21 12:48:40 -05:00
|
|
|
/* string -> uoff_t */
|
|
|
|
uoff_t str_to_uofft(const char *str)
|
|
|
|
{
|
|
|
|
uoff_t ret;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
while (*str != '\0') {
|
|
|
|
ret = ret*10 + (*str - '0');
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2000-06-30 15:54:34 -04:00
|
|
|
/* convert all low-ascii (<32) to ^<A..> combinations */
|
2008-03-02 20:57:50 -05:00
|
|
|
char *show_lowascii(const char *str)
|
2000-06-30 15:54:34 -04:00
|
|
|
{
|
2008-03-02 20:57:50 -05:00
|
|
|
char *ret, *p;
|
2000-06-30 15:54:34 -04:00
|
|
|
|
2008-03-02 20:57:50 -05:00
|
|
|
ret = p = g_malloc(strlen(str)*2+1);
|
|
|
|
while (*str != '\0') {
|
|
|
|
if ((unsigned char) *str >= 32)
|
|
|
|
*p++ = *str;
|
2000-06-30 15:54:34 -04:00
|
|
|
else {
|
|
|
|
*p++ = '^';
|
2008-03-02 20:57:50 -05:00
|
|
|
*p++ = *str + 'A'-1;
|
2000-06-30 15:54:34 -04:00
|
|
|
}
|
2008-03-02 20:57:50 -05:00
|
|
|
str++;
|
2000-06-30 15:54:34 -04:00
|
|
|
}
|
|
|
|
*p = '\0';
|
|
|
|
|
2008-03-02 20:57:50 -05:00
|
|
|
return ret;
|
2000-06-30 15:54:34 -04:00
|
|
|
}
|
|
|
|
|
2001-01-14 13:16:39 -05:00
|
|
|
/* Get time in human readable form with localtime() + asctime() */
|
|
|
|
char *my_asctime(time_t t)
|
|
|
|
{
|
|
|
|
struct tm *tm;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
tm = localtime(&t);
|
|
|
|
str = g_strdup(asctime(tm));
|
|
|
|
|
|
|
|
len = strlen(str);
|
|
|
|
if (len > 0) str[len-1] = '\0';
|
|
|
|
return str;
|
|
|
|
}
|
2001-01-28 10:43:38 -05:00
|
|
|
|
|
|
|
/* Returns number of columns needed to print items.
|
|
|
|
save_column_widths is filled with length of each column. */
|
|
|
|
int get_max_column_count(GSList *items, COLUMN_LEN_FUNC len_func,
|
2001-02-09 23:54:09 -05:00
|
|
|
int max_width, int max_columns,
|
|
|
|
int item_extra, int item_min_size,
|
2001-01-28 10:43:38 -05:00
|
|
|
int **save_column_widths, int *rows)
|
|
|
|
{
|
2001-01-28 11:37:13 -05:00
|
|
|
GSList *tmp;
|
2001-01-28 10:43:38 -05:00
|
|
|
int **columns, *columns_width, *columns_rows;
|
|
|
|
int item_pos, items_count;
|
2001-05-21 19:46:48 -04:00
|
|
|
int ret, len, max_len, n, col;
|
2001-01-28 10:43:38 -05:00
|
|
|
|
|
|
|
items_count = g_slist_length(items);
|
2001-02-02 17:09:11 -05:00
|
|
|
if (items_count == 0) {
|
|
|
|
*save_column_widths = NULL;
|
|
|
|
*rows = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
2001-01-28 10:43:38 -05:00
|
|
|
|
2001-02-09 23:54:09 -05:00
|
|
|
len = max_width/(item_extra+item_min_size);
|
2001-03-03 16:01:18 -05:00
|
|
|
if (len <= 0) len = 1;
|
2001-02-09 23:54:09 -05:00
|
|
|
if (max_columns <= 0 || len < max_columns)
|
|
|
|
max_columns = len;
|
|
|
|
|
2001-01-28 10:43:38 -05:00
|
|
|
columns = g_new0(int *, max_columns);
|
|
|
|
columns_width = g_new0(int, max_columns);
|
|
|
|
columns_rows = g_new0(int, max_columns);
|
|
|
|
|
|
|
|
for (n = 1; n < max_columns; n++) {
|
|
|
|
columns[n] = g_new0(int, n+1);
|
2001-01-28 11:37:13 -05:00
|
|
|
columns_rows[n] = items_count <= n+1 ? 1 :
|
2001-01-28 10:43:38 -05:00
|
|
|
(items_count+n)/(n+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for each possible column count, save the column widths and
|
|
|
|
find the biggest column count that fits to screen. */
|
2001-05-21 19:46:48 -04:00
|
|
|
item_pos = 0; max_len = 0;
|
2001-01-28 11:37:13 -05:00
|
|
|
for (tmp = items; tmp != NULL; tmp = tmp->next) {
|
2001-05-21 19:46:48 -04:00
|
|
|
len = item_extra+len_func(tmp->data);
|
|
|
|
if (max_len < len)
|
|
|
|
max_len = len;
|
|
|
|
|
2001-01-28 10:43:38 -05:00
|
|
|
for (n = 1; n < max_columns; n++) {
|
|
|
|
if (columns_width[n] > max_width)
|
|
|
|
continue; /* too wide */
|
|
|
|
|
|
|
|
col = item_pos/columns_rows[n];
|
|
|
|
if (columns[n][col] < len) {
|
|
|
|
columns_width[n] += len-columns[n][col];
|
|
|
|
columns[n][col] = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
item_pos++;
|
|
|
|
}
|
|
|
|
|
2001-06-11 11:05:08 -04:00
|
|
|
for (n = max_columns-1; n >= 1; n--) {
|
2001-01-28 11:37:13 -05:00
|
|
|
if (columns_width[n] <= max_width &&
|
|
|
|
columns[n][n] > 0)
|
2001-01-28 10:43:38 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ret = n+1;
|
|
|
|
|
|
|
|
*save_column_widths = g_new(int, ret);
|
2001-01-28 11:37:13 -05:00
|
|
|
if (ret == 1) {
|
2001-05-21 19:46:48 -04:00
|
|
|
**save_column_widths = max_len;
|
2001-01-28 11:37:13 -05:00
|
|
|
*rows = 1;
|
|
|
|
} else {
|
|
|
|
memcpy(*save_column_widths, columns[ret-1], sizeof(int)*ret);
|
|
|
|
*rows = columns_rows[ret-1];
|
|
|
|
}
|
2001-01-28 10:43:38 -05:00
|
|
|
|
|
|
|
for (n = 1; n < max_columns; n++)
|
|
|
|
g_free(columns[n]);
|
|
|
|
g_free(columns_width);
|
|
|
|
g_free(columns_rows);
|
|
|
|
g_free(columns);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return a column sorted copy of a list. */
|
|
|
|
GSList *columns_sort_list(GSList *list, int rows)
|
|
|
|
{
|
|
|
|
GSList *tmp, *sorted;
|
|
|
|
int row, skip;
|
|
|
|
|
2001-02-02 17:09:11 -05:00
|
|
|
if (list == NULL || rows == 0)
|
|
|
|
return list;
|
|
|
|
|
2001-01-28 10:43:38 -05:00
|
|
|
sorted = NULL;
|
|
|
|
|
|
|
|
for (row = 0; row < rows; row++) {
|
|
|
|
tmp = g_slist_nth(list, row);
|
|
|
|
skip = 1;
|
|
|
|
for (; tmp != NULL; tmp = tmp->next) {
|
|
|
|
if (--skip == 0) {
|
|
|
|
skip = rows;
|
|
|
|
sorted = g_slist_append(sorted, tmp->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_fail(g_slist_length(sorted) ==
|
|
|
|
g_slist_length(list), sorted);
|
|
|
|
return sorted;
|
|
|
|
}
|
2001-08-08 16:00:25 -04:00
|
|
|
|
|
|
|
/* Expand escape string, the first character in data should be the
|
|
|
|
one after '\'. Returns the expanded character or -1 if error. */
|
|
|
|
int expand_escape(const char **data)
|
|
|
|
{
|
|
|
|
char digit[4];
|
|
|
|
|
|
|
|
switch (**data) {
|
|
|
|
case 't':
|
|
|
|
return '\t';
|
|
|
|
case 'r':
|
|
|
|
return '\r';
|
|
|
|
case 'n':
|
|
|
|
return '\n';
|
|
|
|
case 'e':
|
|
|
|
return 27; /* ESC */
|
|
|
|
|
|
|
|
case 'x':
|
|
|
|
/* hex digit */
|
2002-02-11 22:04:34 -05:00
|
|
|
if (!i_isxdigit((*data)[1]) || !i_isxdigit((*data)[2]))
|
2001-08-08 16:00:25 -04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
digit[0] = (*data)[1];
|
|
|
|
digit[1] = (*data)[2];
|
|
|
|
digit[2] = '\0';
|
|
|
|
*data += 2;
|
|
|
|
return strtol(digit, NULL, 16);
|
|
|
|
case 'c':
|
|
|
|
/* control character (\cA = ^A) */
|
|
|
|
(*data)++;
|
2002-01-27 15:45:59 -05:00
|
|
|
return i_toupper(**data) - 64;
|
2010-11-17 15:41:14 -05:00
|
|
|
case '0': case '1': case '2': case '3':
|
|
|
|
case '4': case '5': case '6': case '7':
|
2001-08-08 16:00:25 -04:00
|
|
|
/* octal */
|
2010-11-17 15:41:14 -05:00
|
|
|
digit[1] = digit[2] = digit[3] = '\0';
|
2001-08-08 16:00:25 -04:00
|
|
|
digit[0] = (*data)[0];
|
2010-11-17 15:41:14 -05:00
|
|
|
if ((*data)[1] >= '0' && (*data)[1] <= '7') {
|
|
|
|
++*data;
|
|
|
|
digit[1] = **data;
|
|
|
|
if ((*data)[1] >= '0' && (*data)[1] <= '7') {
|
|
|
|
++*data;
|
|
|
|
digit[2] = **data;
|
|
|
|
}
|
|
|
|
}
|
2001-08-08 16:00:25 -04:00
|
|
|
return strtol(digit, NULL, 8);
|
2010-11-17 15:41:14 -05:00
|
|
|
default:
|
|
|
|
return -1;
|
2001-08-08 16:00:25 -04:00
|
|
|
}
|
|
|
|
}
|
2002-07-16 12:20:10 -04:00
|
|
|
|
|
|
|
/* Escape all '"', "'" and '\' chars with '\' */
|
|
|
|
char *escape_string(const char *str)
|
|
|
|
{
|
|
|
|
char *ret, *p;
|
|
|
|
|
|
|
|
p = ret = g_malloc(strlen(str)*2+1);
|
|
|
|
while (*str != '\0') {
|
|
|
|
if (*str == '"' || *str == '\'' || *str == '\\')
|
|
|
|
*p++ = '\\';
|
|
|
|
*p++ = *str++;
|
|
|
|
}
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2002-12-28 09:20:24 -05:00
|
|
|
|
2004-03-23 17:07:55 -05:00
|
|
|
int strocpy(char *dest, const char *src, size_t dstsize)
|
|
|
|
{
|
|
|
|
if (dstsize == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while (*src != '\0' && dstsize > 1) {
|
|
|
|
*dest++ = *src++;
|
|
|
|
dstsize--;
|
|
|
|
}
|
|
|
|
|
|
|
|
*dest++ = '\0';
|
|
|
|
return *src == '\0' ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
2002-12-28 09:20:24 -05:00
|
|
|
int nearest_power(int num)
|
|
|
|
{
|
|
|
|
int n = 1;
|
|
|
|
|
|
|
|
while (n < num) n <<= 1;
|
|
|
|
return n;
|
|
|
|
}
|
2002-12-28 12:54:13 -05:00
|
|
|
|
|
|
|
int parse_time_interval(const char *time, int *msecs)
|
|
|
|
{
|
|
|
|
const char *desc;
|
2009-04-03 18:09:17 -04:00
|
|
|
int number, sign, len, ret, digits;
|
2002-12-28 12:54:13 -05:00
|
|
|
|
|
|
|
*msecs = 0;
|
|
|
|
|
2003-11-16 12:26:43 -05:00
|
|
|
/* max. return value is around 24 days */
|
2009-04-03 18:09:17 -04:00
|
|
|
number = 0; sign = 1; ret = TRUE; digits = FALSE;
|
|
|
|
while (i_isspace(*time))
|
|
|
|
time++;
|
|
|
|
if (*time == '-') {
|
|
|
|
sign = -sign;
|
|
|
|
time++;
|
|
|
|
while (i_isspace(*time))
|
2005-09-10 08:51:43 -04:00
|
|
|
time++;
|
2009-04-03 18:09:17 -04:00
|
|
|
}
|
|
|
|
for (;;) {
|
2002-12-28 12:54:13 -05:00
|
|
|
if (i_isdigit(*time)) {
|
|
|
|
number = number*10 + (*time - '0');
|
|
|
|
time++;
|
2009-04-03 18:09:17 -04:00
|
|
|
digits = TRUE;
|
2002-12-28 12:54:13 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-04-03 18:09:17 -04:00
|
|
|
if (!digits)
|
|
|
|
return FALSE;
|
|
|
|
|
2002-12-28 12:54:13 -05:00
|
|
|
/* skip punctuation */
|
2009-04-03 18:09:17 -04:00
|
|
|
while (*time != '\0' && i_ispunct(*time) && *time != '-')
|
2002-12-28 12:54:13 -05:00
|
|
|
time++;
|
|
|
|
|
|
|
|
/* get description */
|
|
|
|
for (len = 0, desc = time; i_isalpha(*time); time++)
|
|
|
|
len++;
|
|
|
|
|
2009-04-03 18:09:17 -04:00
|
|
|
while (i_isspace(*time))
|
|
|
|
time++;
|
|
|
|
|
2002-12-28 12:54:13 -05:00
|
|
|
if (len == 0) {
|
2009-04-03 18:09:17 -04:00
|
|
|
if (*time != '\0')
|
|
|
|
return FALSE;
|
2003-01-08 15:54:36 -05:00
|
|
|
*msecs += number * 1000; /* assume seconds */
|
2005-09-10 08:51:43 -04:00
|
|
|
*msecs *= sign;
|
2003-11-16 11:22:07 -05:00
|
|
|
return TRUE;
|
2002-12-28 12:54:13 -05:00
|
|
|
}
|
|
|
|
|
2008-03-09 08:17:55 -04:00
|
|
|
if (g_ascii_strncasecmp(desc, "days", len) == 0) {
|
2003-11-16 12:26:43 -05:00
|
|
|
if (number > 24) {
|
|
|
|
/* would overflow */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
*msecs += number * 1000*3600*24;
|
2008-03-09 08:17:55 -04:00
|
|
|
} else if (g_ascii_strncasecmp(desc, "hours", len) == 0)
|
2004-11-04 10:08:57 -05:00
|
|
|
*msecs += number * 1000*3600;
|
2008-03-09 08:17:55 -04:00
|
|
|
else if (g_ascii_strncasecmp(desc, "minutes", len) == 0 ||
|
|
|
|
g_ascii_strncasecmp(desc, "mins", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*msecs += number * 1000*60;
|
2008-03-09 08:17:55 -04:00
|
|
|
else if (g_ascii_strncasecmp(desc, "seconds", len) == 0 ||
|
|
|
|
g_ascii_strncasecmp(desc, "secs", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*msecs += number * 1000;
|
2008-03-09 08:17:55 -04:00
|
|
|
else if (g_ascii_strncasecmp(desc, "milliseconds", len) == 0 ||
|
|
|
|
g_ascii_strncasecmp(desc, "millisecs", len) == 0 ||
|
|
|
|
g_ascii_strncasecmp(desc, "mseconds", len) == 0 ||
|
|
|
|
g_ascii_strncasecmp(desc, "msecs", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*msecs += number;
|
2003-11-16 11:22:07 -05:00
|
|
|
else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
2002-12-28 12:54:13 -05:00
|
|
|
|
|
|
|
/* skip punctuation */
|
2009-04-03 18:09:17 -04:00
|
|
|
while (*time != '\0' && i_ispunct(*time) && *time != '-')
|
2002-12-28 12:54:13 -05:00
|
|
|
time++;
|
|
|
|
|
|
|
|
if (*time == '\0')
|
|
|
|
break;
|
|
|
|
|
|
|
|
number = 0;
|
2009-04-03 18:09:17 -04:00
|
|
|
digits = FALSE;
|
2002-12-28 12:54:13 -05:00
|
|
|
}
|
|
|
|
|
2005-09-10 08:51:43 -04:00
|
|
|
*msecs *= sign;
|
2003-11-16 11:22:07 -05:00
|
|
|
return ret;
|
2002-12-28 12:54:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int parse_size(const char *size, int *bytes)
|
|
|
|
{
|
|
|
|
const char *desc;
|
|
|
|
int number, len;
|
|
|
|
|
|
|
|
*bytes = 0;
|
|
|
|
|
|
|
|
/* max. return value is about 1.6 years */
|
|
|
|
number = 0;
|
|
|
|
while (*size != '\0') {
|
|
|
|
if (i_isdigit(*size)) {
|
|
|
|
number = number*10 + (*size - '0');
|
|
|
|
size++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip punctuation */
|
|
|
|
while (*size != '\0' && i_ispunct(*size))
|
|
|
|
size++;
|
|
|
|
|
|
|
|
/* get description */
|
|
|
|
for (len = 0, desc = size; i_isalpha(*size); size++)
|
|
|
|
len++;
|
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
if (number == 0) {
|
|
|
|
/* "0" - allow it */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bytes += number*1024; /* assume kilobytes */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-03-09 08:17:55 -04:00
|
|
|
if (g_ascii_strncasecmp(desc, "gbytes", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*bytes += number * 1024*1024*1024;
|
2008-03-09 08:17:55 -04:00
|
|
|
if (g_ascii_strncasecmp(desc, "mbytes", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*bytes += number * 1024*1024;
|
2008-03-09 08:17:55 -04:00
|
|
|
if (g_ascii_strncasecmp(desc, "kbytes", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*bytes += number * 1024;
|
2008-03-09 08:17:55 -04:00
|
|
|
if (g_ascii_strncasecmp(desc, "bytes", len) == 0)
|
2002-12-28 12:54:13 -05:00
|
|
|
*bytes += number;
|
|
|
|
|
|
|
|
/* skip punctuation */
|
|
|
|
while (*size != '\0' && i_ispunct(*size))
|
|
|
|
size++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2010-04-03 16:09:37 -04:00
|
|
|
|
|
|
|
char *ascii_strup(char *str)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
for (s = str; *s; s++)
|
|
|
|
*s = g_ascii_toupper (*s);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *ascii_strdown(char *str)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
for (s = str; *s; s++)
|
|
|
|
*s = g_ascii_tolower (*s);
|
|
|
|
return str;
|
|
|
|
}
|
2014-06-13 00:39:02 -04:00
|
|
|
|
2014-10-11 12:47:39 -04:00
|
|
|
char **strsplit_len(const char *str, int len, gboolean onspace)
|
|
|
|
{
|
|
|
|
char **ret = g_new(char *, 1);
|
|
|
|
int n;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
for (n = 0; *str != '\0'; n++, str += MIN(len - offset, strlen(str))) {
|
|
|
|
offset = 0;
|
|
|
|
if (onspace) {
|
|
|
|
/*
|
|
|
|
* Try to find a space to split on and leave
|
|
|
|
* the space on the previous line.
|
|
|
|
*/
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (str[len-1-i] == ' ') {
|
|
|
|
offset = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret[n] = g_strndup(str, len - offset);
|
|
|
|
ret = g_renew(char *, ret, n + 2);
|
|
|
|
}
|
2014-06-13 00:39:02 -04:00
|
|
|
ret[n] = NULL;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|