New array type, cleanupts and rename logfilegroup log_store
This commit is contained in:
parent
4b723ca479
commit
d3ef106c4f
10
src/bip.c
10
src/bip.c
@ -1900,7 +1900,7 @@ void adm_on_connect_send(struct link_client *ic, struct line *line,
|
||||
return;
|
||||
}
|
||||
|
||||
if (irc_line_include(line, 2))
|
||||
if (irc_line_includes(line, 2))
|
||||
return;
|
||||
|
||||
for (i = privmsg + 2; i < irc_line_count(line); i++) {
|
||||
@ -2096,7 +2096,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
|
||||
free(linestr);
|
||||
}
|
||||
|
||||
if (!irc_line_include(line, privmsg + 1))
|
||||
if (!irc_line_includes(line, privmsg + 1))
|
||||
return OK_FORGET;
|
||||
|
||||
mylog(LOG_INFO, "/BIP %s from %s", irc_line_elem(line, privmsg + 1),
|
||||
@ -2134,7 +2134,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
|
||||
bip_notify(ic, "-- Invalid LIST request");
|
||||
}
|
||||
} else if (strcasecmp(irc_line_elem(line, privmsg + 1), "INFO") == 0) {
|
||||
if (!irc_line_include(line, privmsg + 2)) {
|
||||
if (!irc_line_includes(line, privmsg + 2)) {
|
||||
bip_notify(ic, "-- INFO command needs at least one "
|
||||
"argument");
|
||||
return OK_FORGET;
|
||||
@ -2163,7 +2163,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
|
||||
}
|
||||
bip_notify(ic, "-- Jumping to next server");
|
||||
} else if (irc_line_elem_case_equals(line, privmsg + 1, "BLRESET")) {
|
||||
if (line->elemc == privmsg + 3 &&
|
||||
if (irc_line_count(line) == privmsg + 3 &&
|
||||
irc_line_elem_equals(line, privmsg + 2, "-q")) {
|
||||
log_reinit_all(LINK(ic)->log);
|
||||
} else {
|
||||
@ -2197,7 +2197,7 @@ int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
|
||||
"ON_CONNECT_SEND")) {
|
||||
if (irc_line_count(line) == privmsg + 2) {
|
||||
adm_on_connect_send(ic, NULL, 0);
|
||||
} else if (irc_line_include(line, privmsg + 2)) {
|
||||
} else if (irc_line_includes(line, privmsg + 2)) {
|
||||
adm_on_connect_send(ic, line, privmsg);
|
||||
} else {
|
||||
bip_notify(ic, "-- ON_CONNECT_SEND command needs at "
|
||||
|
60
src/irc.c
60
src/irc.c
@ -271,7 +271,7 @@ static void irc_server_connected(struct link_server *server)
|
||||
static int irc_352(struct link_server *server, struct line *line)
|
||||
{
|
||||
(void)server;
|
||||
if (!irc_line_include(line, 6))
|
||||
if (!irc_line_includes(line, 6))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
#if 0
|
||||
@ -359,11 +359,11 @@ int irc_dispatch_server(bip_t *bip, struct link_server *server,
|
||||
/* shut gcc up */
|
||||
(void)bip;
|
||||
|
||||
if (!irc_line_include(line, 0))
|
||||
if (!irc_line_includes(line, 0))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
if (irc_line_elem_equals(line, 0, "PING")) {
|
||||
if (!irc_line_include(line, 1))
|
||||
if (!irc_line_includes(line, 1))
|
||||
return ERR_PROTOCOL;
|
||||
struct line *resp = irc_line_new();
|
||||
char *resps;
|
||||
@ -867,7 +867,7 @@ static int irc_cli_quit(struct link_client *ic, struct line *line)
|
||||
static int irc_cli_privmsg(bip_t *bip, struct link_client *ic,
|
||||
struct line *line)
|
||||
{
|
||||
if (!irc_line_include(line, 2))
|
||||
if (!irc_line_includes(line, 2))
|
||||
return OK_FORGET;
|
||||
|
||||
log_cli_privmsg(LINK(ic)->log, LINK(ic)->l_server->nick,
|
||||
@ -882,7 +882,7 @@ static int irc_cli_privmsg(bip_t *bip, struct link_client *ic,
|
||||
|
||||
static int irc_cli_notice(struct link_client *ic, struct line *line)
|
||||
{
|
||||
if (!irc_line_include(line, 2))
|
||||
if (!irc_line_includes(line, 2))
|
||||
return OK_FORGET;
|
||||
log_cli_notice(LINK(ic)->log, LINK(ic)->l_server->nick,
|
||||
irc_line_elem(line, 1), irc_line_elem(line, 2));
|
||||
@ -1055,7 +1055,7 @@ static int irc_cli_part(struct link_client *irc, struct line *line)
|
||||
static int irc_dispatch_trust_client(struct link_client *ic, struct line *line)
|
||||
{
|
||||
int r = OK_COPY;
|
||||
if (!irc_line_include(line, 1))
|
||||
if (!irc_line_includes(line, 1))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
if (strcasecmp(irc_line_elem(line, 0), "BIP") == 0 &&
|
||||
@ -1074,7 +1074,7 @@ static int irc_dispatch_client(bip_t *bip, struct link_client *ic,
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
if (irc_line_elem_equals(line, 0, "PING")) {
|
||||
if (!irc_line_include(line, 1))
|
||||
if (!irc_line_includes(line, 1))
|
||||
return ERR_PROTOCOL;
|
||||
WRITE_LINE1(CONN(ic), LINK(ic)->name, "PONG",
|
||||
irc_line_elem(line, 1));
|
||||
@ -1137,7 +1137,7 @@ static void irc_copy_cli(struct link_client *src, struct link_client *dest,
|
||||
if (src == dest)
|
||||
return;
|
||||
|
||||
if (!irc_line_include(line, 1) ||
|
||||
if (!irc_line_includes(line, 1) ||
|
||||
!irc_line_elem_equals(line, 0, "PRIVMSG")) {
|
||||
str = irc_line_to_string(line);
|
||||
write_line(CONN(dest), str);
|
||||
@ -1306,7 +1306,7 @@ static int irc_332(struct link_server *server, struct line *line)
|
||||
static int irc_333(struct link_server *server, struct line *line)
|
||||
{
|
||||
struct channel *channel;
|
||||
if (!irc_line_include(line, 2))
|
||||
if (!irc_line_includes(line, 2))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
channel = hash_get(&server->channels, irc_line_elem(line, 2));
|
||||
@ -1580,20 +1580,21 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
int add = 1;
|
||||
unsigned cur_arg = 0;
|
||||
struct nick *nick;
|
||||
char **elemv;
|
||||
int elemc;
|
||||
array_t *mode_args = NULL;
|
||||
|
||||
|
||||
if (!irc_line_include(line, 2))
|
||||
if (!irc_line_includes(line, 2))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
/* nick mode change */
|
||||
if (irc_line_elem_equals(line, 1, server->nick)) {
|
||||
irc_line_extract_args(line, 3, &elemv, &elemc);
|
||||
if (irc_line_includes(line, 3))
|
||||
mode_args = array_extract(&line->words, 3, -1);
|
||||
log_mode(LINK(server)->log, line->origin,
|
||||
irc_line_elem(line, 1),
|
||||
irc_line_elem(line, 2), elemv, elemc);
|
||||
irc_line_free_args(elemv, elemc);
|
||||
irc_line_elem(line, 1), irc_line_elem(line, 2),
|
||||
mode_args);
|
||||
if (mode_args)
|
||||
array_free(mode_args);
|
||||
irc_user_mode(server, line);
|
||||
return OK_COPY;
|
||||
}
|
||||
@ -1607,10 +1608,13 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
if (!channel)
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
irc_line_extract_args(line, 3, &elemv, &elemc);
|
||||
mode_args = NULL;
|
||||
if (irc_line_includes(line, 3))
|
||||
mode_args = array_extract(&line->words, 3, -1);
|
||||
log_mode(LINK(server)->log, line->origin, irc_line_elem(line, 1),
|
||||
irc_line_elem(line, 2), elemv, elemc);
|
||||
irc_line_free_args(elemv, elemc);
|
||||
irc_line_elem(line, 2), mode_args);
|
||||
if (mode_args)
|
||||
array_free(mode_args);
|
||||
|
||||
/*
|
||||
* MODE -a+b.. #channel args
|
||||
@ -1626,12 +1630,12 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
add = 1;
|
||||
break;
|
||||
case 'b':
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
cur_arg++;
|
||||
break;
|
||||
case 'o':
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
nick = hash_get(&channel->nicks,
|
||||
@ -1645,7 +1649,7 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
cur_arg++;
|
||||
break;
|
||||
case 'h':
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
nick = hash_get(&channel->nicks,
|
||||
@ -1659,7 +1663,7 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
cur_arg++;
|
||||
break;
|
||||
case 'v':
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
nick = hash_get(&channel->nicks,
|
||||
@ -1674,7 +1678,7 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
break;
|
||||
case 'k':
|
||||
if (add) {
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
|
||||
channel->key = bip_strdup(
|
||||
@ -1695,7 +1699,7 @@ static int irc_mode(struct link_server *server, struct line *line)
|
||||
case 'e':
|
||||
case 'q':
|
||||
case 'I':
|
||||
if (!irc_line_include(line, cur_arg + 3))
|
||||
if (!irc_line_includes(line, cur_arg + 3))
|
||||
return ERR_PROTOCOL;
|
||||
cur_arg++;
|
||||
break;
|
||||
@ -1804,7 +1808,7 @@ static void irc_privmsg_check_ctcp(struct link_server *server,
|
||||
|
||||
static int irc_privmsg(struct link_server *server, struct line *line)
|
||||
{
|
||||
if (!irc_line_include(line, 2))
|
||||
if (!irc_line_includes(line, 2))
|
||||
return ERR_PROTOCOL;
|
||||
if (LINK(server)->s_state == IRCS_CONNECTED) {
|
||||
log_privmsg(LINK(server)->log, line->origin,
|
||||
@ -1896,7 +1900,7 @@ static int irc_generic_quit(struct link_server *server, struct line *line)
|
||||
nick_free(nick);
|
||||
|
||||
log_quit(LINK(server)->log, line->origin, channel->name,
|
||||
irc_line_include(line, 1) ? irc_line_elem(line, 1) : NULL);
|
||||
irc_line_includes(line, 1) ? irc_line_elem(line, 1) : NULL);
|
||||
}
|
||||
free(s_nick);
|
||||
return OK_COPY;
|
||||
@ -2439,7 +2443,7 @@ void bip_on_event(bip_t *bip, connection_t *conn)
|
||||
continue;
|
||||
}
|
||||
|
||||
line = irc_line(line_s);
|
||||
line = irc_line_new_from_string(line_s);
|
||||
if (!line) {
|
||||
mylog(LOG_ERROR, "Error in protocol, closing...");
|
||||
free(line_s);
|
||||
|
94
src/line.c
94
src/line.c
@ -13,20 +13,23 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "line.h"
|
||||
#include "util.h"
|
||||
|
||||
void irc_line_init(struct line *l)
|
||||
{
|
||||
memset(l, 0, sizeof(struct line));
|
||||
array_init(&l->words);
|
||||
}
|
||||
|
||||
void _irc_line_deinit(struct line *l)
|
||||
{
|
||||
free(l->elemv);
|
||||
array_deinit(&l->words);
|
||||
}
|
||||
|
||||
struct line *irc_line_new()
|
||||
{
|
||||
struct line *l;
|
||||
|
||||
l = bip_malloc(sizeof(struct line));
|
||||
irc_line_init(l);
|
||||
return l;
|
||||
@ -43,32 +46,23 @@ struct line *irc_line_dup(struct line *line)
|
||||
{
|
||||
int i;
|
||||
struct line *nl = irc_line_new();
|
||||
char *ptr;
|
||||
|
||||
nl->origin = line->origin ? bip_strdup(line->origin) : NULL;
|
||||
nl->elemc = line->elemc;
|
||||
nl->elemv = bip_malloc(sizeof(char *) * line->elemc);
|
||||
for (i = 0; i < line->elemc; i++)
|
||||
nl->elemv[i] = bip_strdup(line->elemv[i]);
|
||||
array_each(&line->words, i, ptr)
|
||||
array_set(&nl->words, i, bip_strdup(ptr));
|
||||
nl->colon = line->colon;
|
||||
return nl;
|
||||
}
|
||||
|
||||
char *irc_line_pop(struct line *l)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (irc_line_count(l) == 0)
|
||||
return NULL;
|
||||
ret = (char *)l->elemv[l->elemc - 1];
|
||||
l->elemc--;
|
||||
|
||||
return ret;
|
||||
return (char *)array_pop(&l->words);
|
||||
}
|
||||
|
||||
void _irc_line_append(struct line *l, const char *s)
|
||||
{
|
||||
l->elemc++;
|
||||
l->elemv = bip_realloc(l->elemv, l->elemc * sizeof(char *));
|
||||
l->elemv[l->elemc - 1] = (char *)s;
|
||||
array_push(&l->words, (char *)s);
|
||||
}
|
||||
|
||||
void irc_line_append(struct line *l, const char *s)
|
||||
@ -84,8 +78,8 @@ char *irc_line_to_string(struct line *l)
|
||||
|
||||
if (l->origin)
|
||||
len = strlen(l->origin) + 2;
|
||||
for (i = 0; i < l->elemc; i++)
|
||||
len += strlen(l->elemv[i]) + 1;
|
||||
for (i = 0; i < array_count(&l->words); i++)
|
||||
len += strlen(array_get(&l->words, i)) + 1;
|
||||
len += 1; /* remove one trailing space and add \r\n */
|
||||
len++; /* last args ":" */
|
||||
ret = bip_malloc(len + 1);
|
||||
@ -96,14 +90,14 @@ char *irc_line_to_string(struct line *l)
|
||||
strcat(ret, l->origin);
|
||||
strcat(ret, " ");
|
||||
}
|
||||
for (i = 0; i < l->elemc - 1; i++) {
|
||||
strcat(ret, l->elemv[i]);
|
||||
for (i = 0; i < array_count(&l->words) - 1; i++) {
|
||||
strcat(ret, array_get(&l->words, i));
|
||||
strcat(ret, " ");
|
||||
}
|
||||
if (strchr(l->elemv[i], ' ') || l->colon)
|
||||
if (strchr(array_get(&l->words, i), ' ') || l->colon)
|
||||
strcat(ret, ":");
|
||||
|
||||
strcat(ret, l->elemv[i]);
|
||||
strcat(ret, array_get(&l->words, i));
|
||||
strcat(ret, "\r\n");
|
||||
return ret;
|
||||
}
|
||||
@ -114,30 +108,26 @@ char *irc_line_to_string_to(struct line *line, char *nick)
|
||||
char *l;
|
||||
|
||||
tmp = (char *)irc_line_elem(line, 1);
|
||||
line->elemv[1] = nick;
|
||||
array_set(&line->words, 1, nick);
|
||||
l = irc_line_to_string(line);
|
||||
line->elemv[1] = tmp;
|
||||
array_set(&line->words, 1, tmp);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int irc_line_count(struct line *line)
|
||||
{
|
||||
return line->elemc;
|
||||
return array_count(&line->words);
|
||||
}
|
||||
|
||||
int irc_line_include(struct line *line, int elem)
|
||||
int irc_line_includes(struct line *line, int elem)
|
||||
{
|
||||
if (elem < 0)
|
||||
fatal("internal error: irc_line_elem got negative elem");
|
||||
return elem < line->elemc;
|
||||
return array_includes(&line->words, elem);
|
||||
}
|
||||
|
||||
const char *irc_line_elem(struct line *line, int elem)
|
||||
{
|
||||
if (!irc_line_include(line, elem))
|
||||
fatal("internal error: irc_line_elem got too large elem");
|
||||
return line->elemv[elem];
|
||||
return array_get(&line->words, elem);
|
||||
}
|
||||
|
||||
int irc_line_elem_equals(struct line *line, int elem, const char *cmp)
|
||||
@ -153,21 +143,22 @@ int irc_line_elem_case_equals(struct line *line, int elem, const char *cmp)
|
||||
/*
|
||||
* takes a null terminated string as input w/o \r\n
|
||||
*/
|
||||
struct line *irc_line(char *str)
|
||||
struct line *irc_line_new_from_string(char *str)
|
||||
{
|
||||
struct line *line;
|
||||
char *space;
|
||||
size_t len;
|
||||
int curelem = 0;
|
||||
|
||||
line = bip_calloc(sizeof(struct line), 1);
|
||||
line = irc_line_new();
|
||||
if (str[0] == ':') {
|
||||
space = str + 1;
|
||||
|
||||
while (*space && *space != ' ')
|
||||
space++;
|
||||
if (!*space)
|
||||
if (!*space) {
|
||||
irc_line_free(line);
|
||||
return NULL;
|
||||
}
|
||||
len = space - str - 1; /* leading ':' */
|
||||
line->origin = bip_malloc(len + 1);
|
||||
memcpy(line->origin, str + 1, len);
|
||||
@ -181,10 +172,6 @@ struct line *irc_line(char *str)
|
||||
while (*str) {
|
||||
char *tmp;
|
||||
|
||||
line->elemc++;
|
||||
line->elemv = bip_realloc(line->elemv,
|
||||
line->elemc * sizeof(char *));
|
||||
|
||||
space = str;
|
||||
if (*space == ':') {
|
||||
line->colon = 1;
|
||||
@ -199,11 +186,9 @@ struct line *irc_line(char *str)
|
||||
tmp = bip_malloc(len + 1);
|
||||
memcpy(tmp, str, len);
|
||||
tmp[len] = 0;
|
||||
if (curelem == 0)
|
||||
if (array_count(&line->words) == 0)
|
||||
strucase(tmp);
|
||||
line->elemv[curelem] = (const char *)tmp;
|
||||
|
||||
curelem++;
|
||||
array_push(&line->words, tmp);
|
||||
|
||||
str = space;
|
||||
while (*str == ' ')
|
||||
@ -216,29 +201,14 @@ void irc_line_free(struct line *l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l->elemc; i++)
|
||||
free((char *)l->elemv[i]);
|
||||
free(l->elemv);
|
||||
for (i = 0; i < array_count(&l->words); i++)
|
||||
free(array_get(&l->words, i));
|
||||
array_deinit(&l->words);
|
||||
if (l->origin)
|
||||
free(l->origin);
|
||||
free(l);
|
||||
}
|
||||
|
||||
void irc_line_extract_args(struct line *line, int from,
|
||||
char ***elemv, int *elemc)
|
||||
{
|
||||
int i;
|
||||
|
||||
*elemc = irc_line_count(line) - from;
|
||||
if (*elemc == 0) {
|
||||
*elemv = NULL;
|
||||
return;
|
||||
}
|
||||
*elemv = bip_malloc(*elemc * sizeof(char *));
|
||||
for (i = 0; i < *elemc; i++)
|
||||
*elemv[i] = bip_strdup(irc_line_elem(line, i + from));
|
||||
}
|
||||
|
||||
void irc_line_free_args(char **elemv, int elemc)
|
||||
{
|
||||
int i;
|
||||
|
@ -78,8 +78,7 @@
|
||||
|
||||
struct line {
|
||||
char *origin;
|
||||
int elemc;
|
||||
const char **elemv;
|
||||
array_t words;
|
||||
int colon;
|
||||
};
|
||||
|
||||
@ -88,20 +87,18 @@ void _irc_line_deinit(struct line *l);
|
||||
struct line *irc_line_new();
|
||||
void irc_line_write(struct line *l, connection_t *c);
|
||||
void irc_line_append(struct line *l, const char *s);
|
||||
struct line *irc_line(char *str);
|
||||
struct line *irc_line_new_from_string(char *str);
|
||||
char *irc_line_to_string(struct line *l);
|
||||
char *irc_line_to_string_to(struct line *line, char *nick);
|
||||
void irc_line_free(struct line *l);
|
||||
struct line *irc_line_dup(struct line *line);
|
||||
void _irc_line_append(struct line *l, const char *s);
|
||||
int irc_line_include(struct line *line, int elem);
|
||||
int irc_line_includes(struct line *line, int elem);
|
||||
const char *irc_line_elem(struct line *line, int elem);
|
||||
int irc_line_count(struct line *line);
|
||||
char *irc_line_pop(struct line *l);
|
||||
int irc_line_elem_equals(struct line *line, int elem, const char *cmp);
|
||||
int irc_line_elem_case_equals(struct line *line, int elem, const char *cmp);
|
||||
void irc_line_extract_args(struct line *line, int from,
|
||||
char ***elemv, int *elemc);
|
||||
void irc_line_free_args(char **elemv, int elemc);
|
||||
|
||||
#endif
|
||||
|
213
src/log.c
213
src/log.c
@ -24,7 +24,7 @@ extern int conf_log;
|
||||
|
||||
extern FILE *conf_global_log_file;
|
||||
|
||||
static int _log_write(log_t *logdata, logfilegroup_t *lf, const char *d,
|
||||
static int _log_write(log_t *logdata, logstore_t *lf, const char *d,
|
||||
const char *str);
|
||||
void logfile_free(logfile_t *lf);
|
||||
static char *_log_wrap(const char *dest, const char *line);
|
||||
@ -178,21 +178,21 @@ void log_updatelast(logfile_t *lf)
|
||||
localtime_r(&t, &lf->last_log);
|
||||
}
|
||||
|
||||
void log_reset(logfilegroup_t *lfg)
|
||||
void log_reset(logstore_t *store)
|
||||
{
|
||||
logfile_t *olf;
|
||||
lfg->skip_advance = 0;
|
||||
store->skip_advance = 0;
|
||||
|
||||
if (lfg->memlog) {
|
||||
while (!list_is_empty(lfg->memlog))
|
||||
free(list_remove_first(lfg->memlog));
|
||||
if (store->memlog) {
|
||||
while (!list_is_empty(store->memlog))
|
||||
free(list_remove_first(store->memlog));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((olf = list_get_first(&lfg->file_group)) !=
|
||||
list_get_last(&lfg->file_group)) {
|
||||
while ((olf = list_get_first(&store->file_group)) !=
|
||||
list_get_last(&store->file_group)) {
|
||||
logfile_free(olf);
|
||||
list_remove_first(&lfg->file_group);
|
||||
list_remove_first(&store->file_group);
|
||||
}
|
||||
if (!olf)
|
||||
return;
|
||||
@ -204,18 +204,19 @@ void log_reset(logfilegroup_t *lfg)
|
||||
olf->backlog_offset = olf->len;
|
||||
}
|
||||
|
||||
void log_reinit(logfilegroup_t *lfg)
|
||||
void log_reinit(logstore_t *store)
|
||||
{
|
||||
mylog(LOG_ERROR, "%s is inconsistant, droping backlog info",
|
||||
lfg->name);
|
||||
log_reset(lfg);
|
||||
store->name);
|
||||
log_reset(store);
|
||||
}
|
||||
|
||||
static int log_add_file(log_t *logdata, const char *destination, const char *filename)
|
||||
static int log_add_file(log_t *logdata, const char *destination,
|
||||
const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
logfile_t *lf = NULL;
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
|
||||
if (conf_log) {
|
||||
f = fopen(filename, "a+");
|
||||
@ -237,23 +238,23 @@ static int log_add_file(log_t *logdata, const char *destination, const char *fil
|
||||
log_updatelast(lf);
|
||||
}
|
||||
|
||||
lfg = hash_get(&logdata->logfgs, destination);
|
||||
store = hash_get(&logdata->logfgs, destination);
|
||||
|
||||
if (!lfg) {
|
||||
lfg = bip_calloc(sizeof(logfilegroup_t), 1);
|
||||
list_init(&lfg->file_group, NULL);
|
||||
lfg->name = bip_strdup(destination);
|
||||
lfg->skip_advance = 0;
|
||||
hash_insert(&logdata->logfgs, destination, lfg);
|
||||
if (!store) {
|
||||
store = bip_calloc(sizeof(logstore_t), 1);
|
||||
list_init(&store->file_group, NULL);
|
||||
store->name = bip_strdup(destination);
|
||||
store->skip_advance = 0;
|
||||
hash_insert(&logdata->logfgs, destination, store);
|
||||
}
|
||||
|
||||
if (!conf_log && logdata->user->backlog) {
|
||||
if (!lfg->memlog)
|
||||
lfg->memlog = list_new(NULL);
|
||||
if (!store->memlog)
|
||||
store->memlog = list_new(NULL);
|
||||
}
|
||||
|
||||
if (lf)
|
||||
list_add_last(&lfg->file_group, lf);
|
||||
list_add_last(&store->file_group, lf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -271,21 +272,21 @@ void logfile_free(logfile_t *lf)
|
||||
free(lf);
|
||||
}
|
||||
|
||||
logfilegroup_t *log_find_file(log_t *logdata, const char *destination)
|
||||
logstore_t *log_find_file(log_t *logdata, const char *destination)
|
||||
{
|
||||
logfile_t *lf;
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
char *filename = NULL;
|
||||
time_t t;
|
||||
struct tm *ltime;
|
||||
struct link *l;
|
||||
|
||||
lfg = hash_get(&logdata->logfgs, destination);
|
||||
store = hash_get(&logdata->logfgs, destination);
|
||||
|
||||
if (lfg && !conf_log)
|
||||
return lfg;
|
||||
if (store && !conf_log)
|
||||
return store;
|
||||
|
||||
if (!lfg) {
|
||||
if (!store) {
|
||||
if (conf_log) {
|
||||
filename = log_build_filename(logdata, destination);
|
||||
if (!filename)
|
||||
@ -297,11 +298,11 @@ logfilegroup_t *log_find_file(log_t *logdata, const char *destination)
|
||||
free(filename);
|
||||
return NULL;
|
||||
}
|
||||
lfg = hash_get(&logdata->logfgs, destination);
|
||||
if (!lfg)
|
||||
store = hash_get(&logdata->logfgs, destination);
|
||||
if (!store)
|
||||
fatal("internal log_find_file");
|
||||
/* ok we are allocating a new lfg now, let's set it up for
|
||||
* backlogging if applicable */
|
||||
/* ok we are allocating a new store now, let's set it up for
|
||||
* backlogging if applicable */
|
||||
if (!logdata->user)
|
||||
fatal("log_find_file: no user associated to logdata");
|
||||
if (!logdata->network)
|
||||
@ -313,20 +314,20 @@ logfilegroup_t *log_find_file(log_t *logdata, const char *destination)
|
||||
"logdata");
|
||||
struct chan_info *ci = hash_get(&l->chan_infos, destination);
|
||||
if (ci && !ci->backlog) {
|
||||
lfg->track_backlog = 0;
|
||||
store->track_backlog = 0;
|
||||
} else {
|
||||
lfg->track_backlog = 1;
|
||||
store->track_backlog = 1;
|
||||
}
|
||||
|
||||
if (filename)
|
||||
free(filename);
|
||||
return lfg;
|
||||
return store;
|
||||
}
|
||||
|
||||
/* This is reached if lfg already exists */
|
||||
/* This is reached if store already exists */
|
||||
time(&t);
|
||||
ltime = localtime(&t);
|
||||
lf = list_get_last(&lfg->file_group);
|
||||
lf = list_get_last(&store->file_group);
|
||||
if (ltime->tm_mday != lf->last_log.tm_mday) {
|
||||
logfile_t *oldlf;
|
||||
|
||||
@ -338,12 +339,12 @@ logfilegroup_t *log_find_file(log_t *logdata, const char *destination)
|
||||
if (strcmp(lf->filename, filename) == 0) {
|
||||
/* finally we don't */
|
||||
free(filename);
|
||||
return lfg;
|
||||
return store;
|
||||
}
|
||||
|
||||
/* we do want do rotate logfiles */
|
||||
mylog(LOG_DEBUG, "Rotating logfile for %s from", destination);
|
||||
oldlf = list_get_last(&lfg->file_group);
|
||||
oldlf = list_get_last(&store->file_group);
|
||||
if (!log_add_file(logdata, destination, filename)) {
|
||||
free(filename);
|
||||
return NULL;
|
||||
@ -352,18 +353,18 @@ logfilegroup_t *log_find_file(log_t *logdata, const char *destination)
|
||||
|
||||
if (!logdata->user->backlog) {
|
||||
/* remove oldlf from file_group */
|
||||
if (list_remove_first(&lfg->file_group) != oldlf)
|
||||
if (list_remove_first(&store->file_group) != oldlf)
|
||||
fatal("internal log_find_file 2");
|
||||
logfile_free(oldlf);
|
||||
if (list_get_first(&lfg->file_group)
|
||||
!= list_get_last(&lfg->file_group))
|
||||
if (list_get_first(&store->file_group)
|
||||
!= list_get_last(&store->file_group))
|
||||
fatal("internal log_find_file 3");
|
||||
} else {
|
||||
fclose(oldlf->file);
|
||||
oldlf->file = NULL;
|
||||
}
|
||||
}
|
||||
return lfg;
|
||||
return store;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -549,7 +550,7 @@ void log_init_topic_time(log_t *logdata, const char *channel, const char *who,
|
||||
}
|
||||
|
||||
void log_mode(log_t *logdata, const char *ircmask, const char *channel,
|
||||
const char *modes, char **modargv, int modargc)
|
||||
const char *modes, array_t *mode_args)
|
||||
{
|
||||
int i;
|
||||
char *tmpbuf = bip_malloc(LOGLINE_MAXLEN + 1);
|
||||
@ -558,8 +559,9 @@ void log_mode(log_t *logdata, const char *ircmask, const char *channel,
|
||||
|
||||
snprintf(tmpbuf, LOGLINE_MAXLEN, "%s -!- mode/%s [%s", timestamp(),
|
||||
channel, modes);
|
||||
for (i = 0; i < modargc; i++) {
|
||||
snprintf(tmpbuf2, LOGLINE_MAXLEN, "%s %s", tmpbuf, modargv[i]);
|
||||
for (i = 0; i < array_count(mode_args); i++) {
|
||||
snprintf(tmpbuf2, LOGLINE_MAXLEN, "%s %s", tmpbuf,
|
||||
array_get(mode_args, i));
|
||||
tmp = tmpbuf;
|
||||
tmpbuf = tmpbuf2;
|
||||
tmpbuf2 = tmp;
|
||||
@ -575,14 +577,14 @@ void log_mode(log_t *logdata, const char *ircmask, const char *channel,
|
||||
|
||||
void log_disconnected(log_t *logdata)
|
||||
{
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
hash_iterator_t hi;
|
||||
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s -!- Disconnected"
|
||||
" from server...", timestamp());
|
||||
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
||||
hash_it_next(&hi)) {
|
||||
lfg = hash_it_item(&hi);
|
||||
_log_write(logdata, lfg, hash_it_key(&hi), logdata->buffer);
|
||||
store = hash_it_item(&hi);
|
||||
_log_write(logdata, store, hash_it_key(&hi), logdata->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,14 +603,15 @@ void log_ping_timeout(log_t *logdata)
|
||||
|
||||
void log_connected(log_t *logdata)
|
||||
{
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
hash_iterator_t hi;
|
||||
|
||||
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s -!- Connected to"
|
||||
" server...", timestamp());
|
||||
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
||||
hash_it_next(&hi)) {
|
||||
lfg = hash_it_item(&hi);
|
||||
_log_write(logdata, lfg, hash_it_key(&hi), logdata->buffer);
|
||||
store = hash_it_item(&hi);
|
||||
_log_write(logdata, store, hash_it_key(&hi), logdata->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -620,13 +623,13 @@ void log_client_disconnected(log_t *logdata)
|
||||
|
||||
void log_reinit_all(log_t *logdata)
|
||||
{
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
hash_iterator_t hi;
|
||||
|
||||
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
||||
hash_it_next(&hi)) {
|
||||
lfg = hash_it_item(&hi);
|
||||
log_reset(lfg);
|
||||
store = hash_it_item(&hi);
|
||||
log_reset(store);
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,34 +649,34 @@ void log_client_connected(log_t *logdata)
|
||||
logdata->connected = 1;
|
||||
}
|
||||
|
||||
void log_advance_backlogs(log_t* ld, logfilegroup_t *lfg)
|
||||
void log_advance_backlogs(log_t* ld, logstore_t *store)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (!lfg->track_backlog)
|
||||
if (!store->track_backlog)
|
||||
return;
|
||||
|
||||
if (!ld->user->backlog || ld->user->backlog_lines == 0)
|
||||
return;
|
||||
|
||||
if (lfg->skip_advance < ld->user->backlog_lines) {
|
||||
lfg->skip_advance++;
|
||||
if (store->skip_advance < ld->user->backlog_lines) {
|
||||
store->skip_advance++;
|
||||
return;
|
||||
}
|
||||
|
||||
logfile_t *lf;
|
||||
while ((lf = list_get_first(&lfg->file_group))) {
|
||||
while ((lf = list_get_first(&store->file_group))) {
|
||||
if (!lf->file) {
|
||||
lf->file = fopen(lf->filename, "r");
|
||||
if (!lf->file) {
|
||||
mylog(LOG_ERROR, "Can't open %s for reading",
|
||||
lf->filename);
|
||||
log_reinit(lfg);
|
||||
log_reinit(store);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
||||
log_reinit(lfg);
|
||||
log_reinit(store);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -682,31 +685,31 @@ void log_advance_backlogs(log_t* ld, logfilegroup_t *lfg)
|
||||
if (c == '\n')
|
||||
return;
|
||||
}
|
||||
if (lf == list_get_last(&lfg->file_group))
|
||||
if (lf == list_get_last(&store->file_group))
|
||||
return;
|
||||
fclose(lf->file);
|
||||
lf->file = NULL;
|
||||
list_remove_first(&lfg->file_group);
|
||||
list_remove_first(&store->file_group);
|
||||
logfile_free(lf);
|
||||
}
|
||||
}
|
||||
|
||||
int log_has_backlog(log_t *logdata, const char *destination)
|
||||
{
|
||||
logfilegroup_t *lfg = hash_get(&logdata->logfgs, destination);
|
||||
logstore_t *store = hash_get(&logdata->logfgs, destination);
|
||||
|
||||
if (!lfg)
|
||||
if (!store)
|
||||
return 0;
|
||||
|
||||
if (lfg->memlog)
|
||||
return !list_is_empty(lfg->memlog);
|
||||
if (store->memlog)
|
||||
return !list_is_empty(store->memlog);
|
||||
|
||||
if (!lfg->track_backlog)
|
||||
if (!store->track_backlog)
|
||||
return 0;
|
||||
|
||||
logfile_t *lf;
|
||||
lf = list_get_first(&lfg->file_group);
|
||||
if (lf != list_get_last(&lfg->file_group))
|
||||
lf = list_get_first(&store->file_group);
|
||||
if (lf != list_get_last(&store->file_group))
|
||||
return 1;
|
||||
|
||||
return lf->backlog_offset != lf->len;
|
||||
@ -888,7 +891,7 @@ char *log_backread(log_t *logdata, const char *destination, int *skip)
|
||||
char *buf;
|
||||
size_t pos = 0;
|
||||
logfile_t *lf;
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
int c;
|
||||
char *ret;
|
||||
|
||||
@ -897,30 +900,30 @@ char *log_backread(log_t *logdata, const char *destination, int *skip)
|
||||
if (!logdata->user->always_backlog && logdata->connected)
|
||||
return NULL;
|
||||
|
||||
lfg = hash_get(&logdata->logfgs, destination);
|
||||
if (!lfg)
|
||||
store = hash_get(&logdata->logfgs, destination);
|
||||
if (!store)
|
||||
return NULL;
|
||||
|
||||
if (!lfg->track_backlog)
|
||||
if (!store->track_backlog)
|
||||
return NULL;
|
||||
|
||||
if (!logdata->backlogging) {
|
||||
logdata->backlogging = 1;
|
||||
mylog(LOG_DEBUG, "backlogging!");
|
||||
if (lfg->memlog)
|
||||
list_it_init(lfg->memlog, &lfg->backlog_it);
|
||||
if (store->memlog)
|
||||
list_it_init(store->memlog, &store->backlog_it);
|
||||
else
|
||||
list_it_init(&lfg->file_group, &logdata->file_it);
|
||||
list_it_init(&store->file_group, &logdata->file_it);
|
||||
}
|
||||
|
||||
if (lfg->memlog) {
|
||||
if (store->memlog) {
|
||||
char *ptr;
|
||||
ptr = list_it_item(&lfg->backlog_it);
|
||||
ptr = list_it_item(&store->backlog_it);
|
||||
if (!ptr) {
|
||||
logdata->backlogging = 0;
|
||||
return NULL;
|
||||
}
|
||||
list_it_next(&lfg->backlog_it);
|
||||
list_it_next(&store->backlog_it);
|
||||
return bip_strdup(ptr);
|
||||
}
|
||||
|
||||
@ -934,7 +937,7 @@ char *log_backread(log_t *logdata, const char *destination, int *skip)
|
||||
next_file:
|
||||
/* check the files containing data to backlog */
|
||||
lf = list_it_item(&logdata->file_it);
|
||||
if (lf != list_get_last(&lfg->file_group)) {
|
||||
if (lf != list_get_last(&store->file_group)) {
|
||||
mylog(LOG_DEBUGVERB, "%s not last file!", lf->filename);
|
||||
/* if the file is not the current open for logging
|
||||
* (it is an old file that has been rotated)
|
||||
@ -945,7 +948,7 @@ next_file:
|
||||
if (!lf->file) {
|
||||
mylog(LOG_ERROR, "Can't open %s for reading",
|
||||
lf->filename);
|
||||
log_reinit(lfg);
|
||||
log_reinit(store);
|
||||
free(buf);
|
||||
return _log_wrap("Error reading logfile",
|
||||
destination);
|
||||
@ -953,7 +956,7 @@ next_file:
|
||||
mylog(LOG_DEBUGVERB, "seeking: %d!",
|
||||
lf->backlog_offset);
|
||||
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
||||
log_reinit(lfg);
|
||||
log_reinit(store);
|
||||
free(buf);
|
||||
return _log_wrap(destination,
|
||||
"Error reading in logfile");
|
||||
@ -977,7 +980,7 @@ next_file:
|
||||
list_it_next(&logdata->file_it);
|
||||
if (!logdata->user->always_backlog) {
|
||||
list_remove_first(
|
||||
&lfg->file_group);
|
||||
&store->file_group);
|
||||
logfile_free(lf);
|
||||
} else {
|
||||
fclose(lf->file);
|
||||
@ -1007,7 +1010,7 @@ next_file:
|
||||
/* the logfile to read is the one open for writing */
|
||||
if (!logdata->lastfile_seeked) {
|
||||
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
||||
log_reinit(lfg);
|
||||
log_reinit(store);
|
||||
return _log_wrap(destination,
|
||||
"Error reading in logfile");
|
||||
}
|
||||
@ -1084,7 +1087,7 @@ static char *_log_wrap(const char *dest, const char *line)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int _log_write(log_t *logdata, logfilegroup_t *lfg,
|
||||
static int _log_write(log_t *logdata, logstore_t *store,
|
||||
const char *destination, const char *str)
|
||||
{
|
||||
size_t nbwrite;
|
||||
@ -1094,21 +1097,21 @@ static int _log_write(log_t *logdata, logfilegroup_t *lfg,
|
||||
strncpy(tmpstr, str, LOGLINE_MAXLEN);
|
||||
tmpstr[LOGLINE_MAXLEN] = 0;
|
||||
|
||||
if (lfg->memlog) {
|
||||
if (store->memlog) {
|
||||
char *r = log_beautify(logdata, tmpstr, destination);
|
||||
if (r != NULL) {
|
||||
list_add_last(lfg->memlog, r);
|
||||
if (lfg->memc == logdata->user->backlog_lines)
|
||||
free(list_remove_first(lfg->memlog));
|
||||
list_add_last(store->memlog, r);
|
||||
if (store->memc == logdata->user->backlog_lines)
|
||||
free(list_remove_first(store->memlog));
|
||||
else
|
||||
lfg->memc++;
|
||||
store->memc++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conf_log)
|
||||
return 0;
|
||||
|
||||
logfile_t *lf = list_get_last(&lfg->file_group);
|
||||
logfile_t *lf = list_get_last(&store->file_group);
|
||||
|
||||
len = strlen(tmpstr);
|
||||
nbwrite = fwrite(tmpstr, sizeof(char), len, lf->file);
|
||||
@ -1118,20 +1121,20 @@ static int _log_write(log_t *logdata, logfilegroup_t *lfg,
|
||||
mylog(LOG_ERROR, "Error writing to %s logfile", lf->filename);
|
||||
lf->len += nbwrite;
|
||||
if (!logdata->connected || logdata->user->always_backlog)
|
||||
log_advance_backlogs(logdata, lfg);
|
||||
log_advance_backlogs(logdata, store);
|
||||
return nbwrite;
|
||||
}
|
||||
|
||||
void log_write(log_t *logdata, const char *destination, const char *str)
|
||||
{
|
||||
logfilegroup_t *lfg = log_find_file(logdata, destination);
|
||||
logstore_t *store = log_find_file(logdata, destination);
|
||||
|
||||
if (!lfg) {
|
||||
if (!store) {
|
||||
mylog(LOG_ERROR, "Unable to find/create logfile for '%s'",
|
||||
destination);
|
||||
return;
|
||||
}
|
||||
_log_write(logdata, lfg, destination, str);
|
||||
_log_write(logdata, store, destination, str);
|
||||
}
|
||||
|
||||
static list_t *log_all_logs = NULL;
|
||||
@ -1149,9 +1152,9 @@ void log_flush_all(void)
|
||||
hash_iterator_t hi;
|
||||
for (hash_it_init(&log->logfgs, &hi); hash_it_item(&hi);
|
||||
hash_it_next(&hi)) {
|
||||
logfilegroup_t *lfg = hash_it_item(&hi);
|
||||
logstore_t *store = hash_it_item(&hi);
|
||||
list_iterator_t lj;
|
||||
for (list_it_init(&lfg->file_group, &lj);
|
||||
for (list_it_init(&store->file_group, &lj);
|
||||
list_it_item(&lj); list_it_next(&lj)) {
|
||||
logfile_t *lf = list_it_item(&lj);
|
||||
if (lf->file)
|
||||
@ -1182,7 +1185,7 @@ log_t *log_new(struct user *user, const char *network)
|
||||
void log_free(log_t *log)
|
||||
{
|
||||
hash_iterator_t it;
|
||||
logfilegroup_t *lfg;
|
||||
logstore_t *store;
|
||||
logfile_t *lf;
|
||||
|
||||
list_remove(log_all_logs, log);
|
||||
@ -1190,10 +1193,10 @@ void log_free(log_t *log)
|
||||
free(log->network);
|
||||
free(log->buffer);
|
||||
|
||||
for (hash_it_init(&log->logfgs, &it); (lfg = hash_it_item(&it));
|
||||
for (hash_it_init(&log->logfgs, &it); (store = hash_it_item(&it));
|
||||
hash_it_next(&it)) {
|
||||
log_reset(lfg);
|
||||
if ((lf = list_remove_first(&lfg->file_group)))
|
||||
log_reset(store);
|
||||
if ((lf = list_remove_first(&store->file_group)))
|
||||
logfile_free(lf);
|
||||
}
|
||||
hash_clean(&log->logfgs);
|
||||
|
@ -37,7 +37,7 @@ typedef struct logfile {
|
||||
size_t len;
|
||||
} logfile_t;
|
||||
|
||||
typedef struct logfilegroup
|
||||
typedef struct logstore
|
||||
{
|
||||
char *name;
|
||||
list_t file_group;
|
||||
@ -47,7 +47,7 @@ typedef struct logfilegroup
|
||||
int memc;
|
||||
list_iterator_t backlog_it;
|
||||
int track_backlog;
|
||||
} logfilegroup_t;
|
||||
} logstore_t;
|
||||
|
||||
typedef struct log {
|
||||
hash_t logfgs;
|
||||
@ -83,7 +83,7 @@ void log_cli_notice(log_t *logdata, const char *ircmask, const char *channel,
|
||||
const char *message);
|
||||
void log_write(log_t *logdata, const char *str, const char *destination);
|
||||
void log_mode(log_t *logdata, const char *ircmask, const char *channel,
|
||||
const char *modes, char **modargv, int modargc);
|
||||
const char *modes, array_t *mode_args);
|
||||
void log_topic(log_t *logdata, const char *ircmask, const char *channel,
|
||||
const char *message);
|
||||
void log_init_topic(log_t *logdata, const char *channel, const char *message);
|
||||
@ -98,7 +98,7 @@ char *log_backread(log_t *logdata, const char *destination, int *skip);
|
||||
int log_has_backlog(log_t *logdata, const char *destination);
|
||||
void log_flush_all(void);
|
||||
void log_client_none_connected(log_t *logdata);
|
||||
void log_reset(logfilegroup_t *);
|
||||
void log_reset(logstore_t *);
|
||||
void log_reinit_all(log_t *logdata);
|
||||
void log_free(log_t *log);
|
||||
int check_dir(char *filename, int is_fatal);
|
||||
|
99
src/util.c
99
src/util.c
@ -686,3 +686,102 @@ int ischannel(char p)
|
||||
{
|
||||
return (p == '#' || p == '&' || p == '+' || p == '!');
|
||||
}
|
||||
|
||||
void array_init(array_t *a)
|
||||
{
|
||||
memset(a, 0, sizeof(array_t));
|
||||
}
|
||||
|
||||
array_t *array_new(void)
|
||||
{
|
||||
array_t *a;
|
||||
|
||||
a = bip_malloc(sizeof(array_t));
|
||||
array_init(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
int array_includes(array_t *a, int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
return a->elemc > index;
|
||||
}
|
||||
|
||||
void array_ensure(array_t *a, int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
|
||||
if (array_includes(a, index))
|
||||
return;
|
||||
a->elemv = bip_realloc(a->elemv, sizeof(void *) * (index + 1));
|
||||
memset(a->elemv + a->elemc, 0, sizeof(void *) * (index + 1 - a->elemc));
|
||||
a->elemc = index + 1;
|
||||
}
|
||||
|
||||
void array_set(array_t *a, int index, void *ptr)
|
||||
{
|
||||
array_ensure(a, index);
|
||||
a->elemv[index] = ptr;
|
||||
}
|
||||
|
||||
void *array_get(array_t *a, int index)
|
||||
{
|
||||
assert(array_includes(a, index));
|
||||
return a->elemv[index];
|
||||
}
|
||||
|
||||
array_t *array_extract(array_t *a, int index, int upto)
|
||||
{
|
||||
array_t *ret;
|
||||
int i;
|
||||
|
||||
assert(array_includes(a, index));
|
||||
if (upto == -1)
|
||||
upto = a->elemc;
|
||||
assert((index == 0 && upto == 0) || array_includes(a, upto - 1));
|
||||
assert(index <= upto);
|
||||
|
||||
ret = array_new();
|
||||
if (index == upto)
|
||||
return ret;
|
||||
|
||||
/* here we have index < upto */
|
||||
array_ensure(ret, upto - index - 1);
|
||||
for (i = index; i < upto; i++)
|
||||
ret->elemv[i] = a->elemv[i + index];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void array_push(array_t *a, void *ptr)
|
||||
{
|
||||
array_ensure(a, a->elemc + 1);
|
||||
a->elemv[a->elemc - 1] = ptr;
|
||||
}
|
||||
|
||||
void *array_pop(array_t *a)
|
||||
{
|
||||
if (a->elemc == 0)
|
||||
return NULL;
|
||||
if (a->elemc == 1) {
|
||||
void *ptr = a->elemv[0];
|
||||
free(a->elemv);
|
||||
a->elemv = NULL;
|
||||
a->elemc = 0;
|
||||
return ptr;
|
||||
}
|
||||
return a->elemv[--a->elemc];
|
||||
}
|
||||
|
||||
void array_deinit(array_t *a)
|
||||
{
|
||||
if (a->elemv)
|
||||
free(a->elemv);
|
||||
array_init(a);
|
||||
}
|
||||
|
||||
void array_free(array_t *a)
|
||||
{
|
||||
if (a->elemv)
|
||||
free(a->elemv);
|
||||
free(a);
|
||||
}
|
||||
|
36
src/util.h
36
src/util.h
@ -59,6 +59,11 @@ typedef struct hash_iterator {
|
||||
hash_t *hash;
|
||||
} hash_iterator_t;
|
||||
|
||||
typedef struct array {
|
||||
int elemc;
|
||||
void **elemv;
|
||||
} array_t;
|
||||
|
||||
#define MOVE_STRING(dest, src) do {\
|
||||
if (dest)\
|
||||
free(dest);\
|
||||
@ -75,6 +80,19 @@ typedef struct hash_iterator {
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define assert(condition) \
|
||||
do { \
|
||||
if (!(condition)) \
|
||||
fatal("Failed assetion in " __FILE__ "(%d): " \
|
||||
#condition, __LINE__); \
|
||||
} while(0)
|
||||
|
||||
#define assert_msg(condition, msg) \
|
||||
do { \
|
||||
if (!(condition)) \
|
||||
fatal(msg); \
|
||||
} while(0)
|
||||
|
||||
void list_init(list_t *list, int (*cmp)(const void*, const void*));
|
||||
int list_ptr_cmp(const void *a, const void *b);
|
||||
list_t *list_new(int (*cmp)(const void *, const void *));
|
||||
@ -129,5 +147,23 @@ void *bip_malloc(size_t size);
|
||||
void *bip_calloc(size_t nmemb, size_t size);
|
||||
void *bip_realloc(void *ptr, size_t size);
|
||||
char *bip_strdup(const char *str);
|
||||
#define array_each(a, idx, ptr) for ((idx) = 0; \
|
||||
(idx) < (a)->elemc && (((ptr) = array_get((a), (idx))) || 1); \
|
||||
(idx)++)
|
||||
|
||||
void array_init(array_t *a);
|
||||
array_t *array_new(void);
|
||||
int array_includes(array_t *a, int index);
|
||||
void array_ensure(array_t *a, int index);
|
||||
void array_set(array_t *a, int index, void *ptr);
|
||||
void *array_get(array_t *a, int index);
|
||||
array_t *array_extract(array_t *a, int index, int upto);
|
||||
void array_push(array_t *a, void *ptr);
|
||||
void *array_pop(array_t *a);
|
||||
void array_deinit(array_t *a);
|
||||
void array_free(array_t *a);
|
||||
static inline int array_count(array_t *a)
|
||||
{
|
||||
return a->elemc;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user