gpgme-tool: Use membuf functions to build up strings.
* src/gpgme-tool.c (clear_membuf, init_membuf, put_membuf) (put_membuf_str, get_membuf, peek_membuf): Add membuf functions. Take from GnuPG master's common/membuf.[ch] and patch for our use. (result_xml_escape): Rewrite using new functions. -- First counting, then allocating, and finally copying data is prone to errors. We better use the membuf functions which make it much easier.
This commit is contained in:
parent
aa30b47aa0
commit
e11e7fc558
187
src/gpgme-tool.c
187
src/gpgme-tool.c
@ -474,6 +474,148 @@ argp_parse (const struct argp *argp, int argc,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* MEMBUF */
|
||||
|
||||
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
||||
create a buffer, put_membuf to append bytes and get_membuf to
|
||||
release and return the buffer. Allocation errors are detected but
|
||||
only returned at the final get_membuf(), this helps not to clutter
|
||||
the code with out-of-core checks. */
|
||||
|
||||
/* The definition of the structure is private, we only need it here,
|
||||
so it can be allocated on the stack. */
|
||||
struct private_membuf_s
|
||||
{
|
||||
size_t len;
|
||||
size_t size;
|
||||
char *buf;
|
||||
int out_of_core;
|
||||
};
|
||||
|
||||
typedef struct private_membuf_s membuf_t;
|
||||
|
||||
/* Return the current length of the membuf. */
|
||||
#define get_membuf_len(a) ((a)->len)
|
||||
#define is_membuf_ready(a) ((a)->buf || (a)->out_of_core)
|
||||
#define MEMBUF_ZERO { 0, 0, NULL, 0}
|
||||
|
||||
|
||||
static void
|
||||
init_membuf (membuf_t *mb, int initiallen)
|
||||
{
|
||||
mb->len = 0;
|
||||
mb->size = initiallen;
|
||||
mb->out_of_core = 0;
|
||||
mb->buf = malloc (initiallen);
|
||||
if (!mb->buf)
|
||||
mb->out_of_core = errno;
|
||||
}
|
||||
|
||||
|
||||
/* Shift the the content of the membuf MB by AMOUNT bytes. The next
|
||||
operation will then behave as if AMOUNT bytes had not been put into
|
||||
the buffer. If AMOUNT is greater than the actual accumulated
|
||||
bytes, the membuf is basically reset to its initial state. */
|
||||
#if 0 /* Not yet used. */
|
||||
static void
|
||||
clear_membuf (membuf_t *mb, size_t amount)
|
||||
{
|
||||
/* No need to clear if we are already out of core. */
|
||||
if (mb->out_of_core)
|
||||
return;
|
||||
if (amount >= mb->len)
|
||||
mb->len = 0;
|
||||
else
|
||||
{
|
||||
mb->len -= amount;
|
||||
memmove (mb->buf, mb->buf+amount, mb->len);
|
||||
}
|
||||
}
|
||||
#endif /* unused */
|
||||
|
||||
static void
|
||||
put_membuf (membuf_t *mb, const void *buf, size_t len)
|
||||
{
|
||||
if (mb->out_of_core || !len)
|
||||
return;
|
||||
|
||||
if (mb->len + len >= mb->size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
mb->size += len + 1024;
|
||||
p = realloc (mb->buf, mb->size);
|
||||
if (!p)
|
||||
{
|
||||
mb->out_of_core = errno ? errno : ENOMEM;
|
||||
return;
|
||||
}
|
||||
mb->buf = p;
|
||||
}
|
||||
memcpy (mb->buf + mb->len, buf, len);
|
||||
mb->len += len;
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* Not yet used. */
|
||||
static void
|
||||
put_membuf_str (membuf_t *mb, const char *string)
|
||||
{
|
||||
put_membuf (mb, string, strlen (string));
|
||||
}
|
||||
#endif /* unused */
|
||||
|
||||
|
||||
static void *
|
||||
get_membuf (membuf_t *mb, size_t *len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (mb->out_of_core)
|
||||
{
|
||||
if (mb->buf)
|
||||
{
|
||||
free (mb->buf);
|
||||
mb->buf = NULL;
|
||||
}
|
||||
gpg_err_set_errno (mb->out_of_core);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = mb->buf;
|
||||
if (len)
|
||||
*len = mb->len;
|
||||
mb->buf = NULL;
|
||||
mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Peek at the membuf MB. On success a pointer to the buffer is
|
||||
returned which is valid until the next operation on MB. If LEN is
|
||||
not NULL the current LEN of the buffer is stored there. On error
|
||||
NULL is returned and ERRNO is set. */
|
||||
#if 0 /* Not yet used. */
|
||||
static const void *
|
||||
peek_membuf (membuf_t *mb, size_t *len)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if (mb->out_of_core)
|
||||
{
|
||||
gpg_err_set_errno (mb->out_of_core);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = mb->buf;
|
||||
if (len)
|
||||
*len = mb->len;
|
||||
return p;
|
||||
}
|
||||
#endif /* unused */
|
||||
|
||||
|
||||
|
||||
/* SUPPORT. */
|
||||
FILE *log_stream;
|
||||
@ -658,7 +800,8 @@ result_xml_tag_start (struct result_xml_state *state, char *name, ...)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
/* Return a constant string with an XML entity for C. */
|
||||
static const char *
|
||||
result_xml_escape_replacement(char c)
|
||||
{
|
||||
switch (c)
|
||||
@ -674,47 +817,31 @@ result_xml_escape_replacement(char c)
|
||||
}
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
/* Escape DATA by replacing certain characters with their XML
|
||||
entities. The result is stored in a newly allocated buffer which
|
||||
address will be stored at BUF. Returns 0 on success. */
|
||||
static gpg_error_t
|
||||
result_xml_escape (const char *data, char **buf)
|
||||
{
|
||||
int data_len, i, j = 1;
|
||||
int data_len, i;
|
||||
const char *r;
|
||||
char *b;
|
||||
membuf_t mb;
|
||||
|
||||
init_membuf (&mb, 128);
|
||||
data_len = strlen (data);
|
||||
for (i = 0; i < data_len; i++)
|
||||
{
|
||||
r = result_xml_escape_replacement (data[i]);
|
||||
if (r)
|
||||
j += strlen (r);
|
||||
put_membuf (&mb, r, strlen (r));
|
||||
else
|
||||
j += 1;
|
||||
put_membuf (&mb, data+i, 1);
|
||||
}
|
||||
put_membuf (&mb, "", 1);
|
||||
*buf = get_membuf (&mb, NULL);
|
||||
return *buf? 0 : gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
b = (char *) malloc (j);
|
||||
if (! b)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < data_len; i++)
|
||||
{
|
||||
r = result_xml_escape_replacement(data[i]);
|
||||
if (r)
|
||||
{
|
||||
strcpy (b + j, r);
|
||||
j += strlen (r);
|
||||
}
|
||||
else
|
||||
{
|
||||
b[j] = data[i];
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
b[j] = 0;
|
||||
*buf = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
result_xml_tag_data (struct result_xml_state *state, const char *data)
|
||||
|
Loading…
Reference in New Issue
Block a user