degesch: move some code to common.c

This commit is contained in:
Přemysl Eric Janouch 2015-05-04 02:17:55 +02:00
parent 56a67d56e0
commit c9a02141f9
2 changed files with 164 additions and 164 deletions

164
common.c
View File

@ -487,6 +487,170 @@ split_str (const char *s, char delimiter, struct str_vector *out)
str_vector_add (out, begin);
}
static ssize_t
str_vector_find (const struct str_vector *v, const char *s)
{
for (size_t i = 0; i < v->len; i++)
if (!strcmp (v->vector[i], s))
return i;
return -1;
}
// --- CTCP decoding -----------------------------------------------------------
#define CTCP_M_QUOTE '\020'
#define CTCP_X_DELIM '\001'
#define CTCP_X_QUOTE '\\'
struct ctcp_chunk
{
LIST_HEADER (struct ctcp_chunk)
bool is_extended; ///< Is this a tagged extended message?
struct str tag; ///< The tag, if any
struct str text; ///< Message contents
};
static struct ctcp_chunk *
ctcp_chunk_new (void)
{
struct ctcp_chunk *self = xcalloc (1, sizeof *self);
str_init (&self->tag);
str_init (&self->text);
return self;
}
static void
ctcp_chunk_destroy (struct ctcp_chunk *self)
{
str_free (&self->tag);
str_free (&self->text);
free (self);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
ctcp_low_level_decode (const char *message, struct str *output)
{
bool escape = false;
for (const char *p = message; *p; p++)
{
if (escape)
{
switch (*p)
{
case '0': str_append_c (output, '\0'); break;
case 'r': str_append_c (output, '\r'); break;
case 'n': str_append_c (output, '\n'); break;
default: str_append_c (output, *p);
}
escape = false;
}
else if (*p == CTCP_M_QUOTE)
escape = true;
else
str_append_c (output, *p);
}
}
static void
ctcp_intra_decode (const char *chunk, size_t len, struct str *output)
{
bool escape = false;
for (size_t i = 0; i < len; i++)
{
char c = chunk[i];
if (escape)
{
if (c == 'a')
str_append_c (output, CTCP_X_DELIM);
else
str_append_c (output, c);
escape = false;
}
else if (c == CTCP_X_QUOTE)
escape = true;
else
str_append_c (output, c);
}
}
static void
ctcp_parse_tagged (const char *chunk, size_t len, struct ctcp_chunk *output)
{
// We may search for the space before doing the higher level decoding,
// as it doesn't concern space characters at all
size_t tag_end = len;
for (size_t i = 0; i < len; i++)
if (chunk[i] == ' ')
{
tag_end = i;
break;
}
output->is_extended = true;
ctcp_intra_decode (chunk, tag_end, &output->tag);
if (tag_end++ != len)
ctcp_intra_decode (chunk + tag_end, len - tag_end, &output->text);
}
static struct ctcp_chunk *
ctcp_parse (const char *message)
{
struct str m;
str_init (&m);
ctcp_low_level_decode (message, &m);
struct ctcp_chunk *result = NULL, *result_tail = NULL;
size_t start = 0;
bool in_ctcp = false;
for (size_t i = 0; i < m.len; i++)
{
char c = m.str[i];
if (c != CTCP_X_DELIM)
continue;
// Remember the current state
size_t my_start = start;
bool my_is_ctcp = in_ctcp;
start = i + 1;
in_ctcp = !in_ctcp;
// Skip empty chunks
if (my_start == i)
continue;
struct ctcp_chunk *chunk = ctcp_chunk_new ();
if (my_is_ctcp)
ctcp_parse_tagged (m.str + my_start, i - my_start, chunk);
else
ctcp_intra_decode (m.str + my_start, i - my_start, &chunk->text);
LIST_APPEND_WITH_TAIL (result, result_tail, chunk);
}
// Finish the last text part. We ignore unended tagged chunks.
// TODO: don't ignore them, e.g. a /me may get cut off
if (!in_ctcp && start != m.len)
{
struct ctcp_chunk *chunk = ctcp_chunk_new ();
ctcp_intra_decode (m.str + start, m.len - start, &chunk->text);
LIST_APPEND_WITH_TAIL (result, result_tail, chunk);
}
str_free (&m);
return result;
}
static void
ctcp_destroy (struct ctcp_chunk *list)
{
LIST_FOR_EACH (struct ctcp_chunk, iter, list)
ctcp_chunk_destroy (iter);
}
// --- Advanced configuration --------------------------------------------------
// This is a new configuration format, superseding the one currently present

164
degesch.c
View File

@ -2524,161 +2524,6 @@ init_readline (void)
return 0;
}
// --- CTCP decoding -----------------------------------------------------------
#define CTCP_M_QUOTE '\020'
#define CTCP_X_DELIM '\001'
#define CTCP_X_QUOTE '\\'
struct ctcp_chunk
{
LIST_HEADER (struct ctcp_chunk)
bool is_extended; ///< Is this a tagged extended message?
struct str tag; ///< The tag, if any
struct str text; ///< Message contents
};
static struct ctcp_chunk *
ctcp_chunk_new (void)
{
struct ctcp_chunk *self = xcalloc (1, sizeof *self);
str_init (&self->tag);
str_init (&self->text);
return self;
}
static void
ctcp_chunk_destroy (struct ctcp_chunk *self)
{
str_free (&self->tag);
str_free (&self->text);
free (self);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
ctcp_low_level_decode (const char *message, struct str *output)
{
bool escape = false;
for (const char *p = message; *p; p++)
{
if (escape)
{
switch (*p)
{
case '0': str_append_c (output, '\0'); break;
case 'r': str_append_c (output, '\r'); break;
case 'n': str_append_c (output, '\n'); break;
default: str_append_c (output, *p);
}
escape = false;
}
else if (*p == CTCP_M_QUOTE)
escape = true;
else
str_append_c (output, *p);
}
}
static void
ctcp_intra_decode (const char *chunk, size_t len, struct str *output)
{
bool escape = false;
for (size_t i = 0; i < len; i++)
{
char c = chunk[i];
if (escape)
{
if (c == 'a')
str_append_c (output, CTCP_X_DELIM);
else
str_append_c (output, c);
escape = false;
}
else if (c == CTCP_X_QUOTE)
escape = true;
else
str_append_c (output, c);
}
}
static void
ctcp_parse_tagged (const char *chunk, size_t len, struct ctcp_chunk *output)
{
// We may search for the space before doing the higher level decoding,
// as it doesn't concern space characters at all
size_t tag_end = len;
for (size_t i = 0; i < len; i++)
if (chunk[i] == ' ')
{
tag_end = i;
break;
}
output->is_extended = true;
ctcp_intra_decode (chunk, tag_end, &output->tag);
if (tag_end++ != len)
ctcp_intra_decode (chunk + tag_end, len - tag_end, &output->text);
}
static struct ctcp_chunk *
ctcp_parse (const char *message)
{
struct str m;
str_init (&m);
ctcp_low_level_decode (message, &m);
struct ctcp_chunk *result = NULL, *result_tail = NULL;
size_t start = 0;
bool in_ctcp = false;
for (size_t i = 0; i < m.len; i++)
{
char c = m.str[i];
if (c != CTCP_X_DELIM)
continue;
// Remember the current state
size_t my_start = start;
bool my_is_ctcp = in_ctcp;
start = i + 1;
in_ctcp = !in_ctcp;
// Skip empty chunks
if (my_start == i)
continue;
struct ctcp_chunk *chunk = ctcp_chunk_new ();
if (my_is_ctcp)
ctcp_parse_tagged (m.str + my_start, i - my_start, chunk);
else
ctcp_intra_decode (m.str + my_start, i - my_start, &chunk->text);
LIST_APPEND_WITH_TAIL (result, result_tail, chunk);
}
// Finish the last text part. We ignore unended tagged chunks.
// TODO: don't ignore them, e.g. a /me may get cut off
if (!in_ctcp && start != m.len)
{
struct ctcp_chunk *chunk = ctcp_chunk_new ();
ctcp_intra_decode (m.str + start, m.len - start, &chunk->text);
LIST_APPEND_WITH_TAIL (result, result_tail, chunk);
}
str_free (&m);
return result;
}
static void
ctcp_destroy (struct ctcp_chunk *list)
{
LIST_FOR_EACH (struct ctcp_chunk, iter, list)
ctcp_chunk_destroy (iter);
}
// --- Input handling ----------------------------------------------------------
// TODO: we will need a proper mode parser; to be shared with kike
@ -3863,15 +3708,6 @@ handle_command_buffer (struct app_context *ctx, char *arguments)
return true;
}
static ssize_t
str_vector_find (const struct str_vector *v, const char *s)
{
for (size_t i = 0; i < v->len; i++)
if (!strcmp (v->vector[i], s))
return i;
return -1;
}
static bool
replace_string_array
(struct config_item_ *item, struct str_vector *array, struct error **e)