mirror of https://github.com/getdnsapi/getdns.git
Pretty printing to ldns_buffer
This makes it much more readable
This commit is contained in:
parent
6adb49b8d5
commit
e0c28a6346
357
src/dict.c
357
src/dict.c
|
@ -29,10 +29,8 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <ldns/buffer.h>
|
||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
|
|
||||||
/*---------------------------------------- getdns_dict_find */
|
/*---------------------------------------- getdns_dict_find */
|
||||||
|
@ -246,7 +244,7 @@ getdns_dict_copy(struct getdns_dict *srcdict, struct getdns_dict **dstdict)
|
||||||
|
|
||||||
LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(srcdict->root))
|
LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(srcdict->root))
|
||||||
{
|
{
|
||||||
key = (const *)item->node.key;
|
key = (char *)item->node.key;
|
||||||
switch(item->dtype)
|
switch(item->dtype)
|
||||||
{
|
{
|
||||||
case t_bindata:
|
case t_bindata:
|
||||||
|
@ -429,117 +427,93 @@ getdns_dict_set_int(struct getdns_dict *dict, char *name, uint32_t child_uint32)
|
||||||
return retval;
|
return retval;
|
||||||
} /* getdns_dict_set_int */
|
} /* getdns_dict_set_int */
|
||||||
|
|
||||||
|
/*---------------------------------------- getdns_pp_dict */
|
||||||
|
/**
|
||||||
|
* private function to help with indenting.
|
||||||
|
* @param indent number of spaces to return
|
||||||
|
* @return a character string containing min(80, indent) spaces
|
||||||
|
*/
|
||||||
static const char *
|
static const char *
|
||||||
getdns_indent(size_t indent)
|
getdns_indent(size_t indent)
|
||||||
{
|
{
|
||||||
static const char *spaces = " "
|
static const char *spaces = " "
|
||||||
" ";
|
" ";
|
||||||
return spaces + 80 - (indent < 80 ? indent : 0);
|
return spaces + 80 - (indent < 80 ? indent : 0);
|
||||||
}
|
} /* getdns_indent */
|
||||||
|
|
||||||
static int
|
/*---------------------------------------- getdns_pp_bindata */
|
||||||
getdns_snprintf(char **str, size_t *size, int* total, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int written;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
written = vsnprintf(*str, *size, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if(written < 0) {
|
|
||||||
*total = written;
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
*total += written;
|
|
||||||
if(written <= *size) {
|
|
||||||
*str += written;
|
|
||||||
*size -= written;
|
|
||||||
} else {
|
|
||||||
*str += *size;
|
|
||||||
*size = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
getdns_snprint_item(char **str, size_t *size, int *total, size_t indent, getdns_data_type dtype, union getdns_item item);
|
|
||||||
|
|
||||||
/*---------------------------------------- getdns_snprint_dict */
|
|
||||||
/**
|
/**
|
||||||
* private function to pretty print dict to a buffer, moving the buffer pointer
|
* private function to pretty print bindata to a ldns_buffer
|
||||||
* forward in the process.
|
* @param buf buffer to write to
|
||||||
* @param str destination character buffer.
|
* @param indent number of spaces to append after newline
|
||||||
* str will be increased with the number of characters written
|
* @param bindata the bindata to print
|
||||||
* @param size bytes available in destination character buffer.
|
* @return on success the number of written characters
|
||||||
* the number of characters written will be substracted from size
|
* if an output error is encountered, a negative value
|
||||||
* @param total the number of characters written will be added to toal
|
|
||||||
* @param indent number of spaces to append after newline
|
|
||||||
* @param dict the dict to print
|
|
||||||
* @return zero on successi
|
|
||||||
* if an output error is encountered, a negative value is returned
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
getdns_snprint_dict(char **str, size_t *size, int *total, size_t indent, struct getdns_dict *dict)
|
getdns_pp_bindata(ldns_buffer *buf, size_t indent, struct getdns_bindata *bindata)
|
||||||
{
|
{
|
||||||
struct getdns_dict_item *item;
|
size_t i, p = ldns_buffer_position(buf);
|
||||||
size_t i, length;
|
uint8_t *dptr;
|
||||||
|
|
||||||
if(dict == NULL)
|
if(ldns_buffer_printf(buf, " <bindata ") < 0)
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
if(getdns_snprintf(str, size, total, "{"))
|
|
||||||
return *total;
|
|
||||||
|
|
||||||
|
/* Walk through all printable characters */
|
||||||
i = 0;
|
i = 0;
|
||||||
indent += 2;
|
if(bindata->size && bindata->data[bindata->size - 1] == 0)
|
||||||
LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(dict->root))
|
while(i < bindata->size - 1 && isprint(bindata->data[i]))
|
||||||
{
|
i++;
|
||||||
if(getdns_snprintf(str, size, total,
|
|
||||||
"%s\n%s\"%s\":", (i ? "," : ""),
|
|
||||||
getdns_indent(indent), item->node.key))
|
|
||||||
return *total;
|
|
||||||
|
|
||||||
do {
|
if(i >= bindata->size - 1) { /* all chars were printable */
|
||||||
if(item->dtype == t_list) {
|
if(ldns_buffer_printf(buf, "for \"%s\">", bindata->data) < 0)
|
||||||
if(getdns_list_get_length(item->data.list, &length) != GETDNS_RETURN_GOOD)
|
return -1;
|
||||||
|
} else {
|
||||||
|
if(ldns_buffer_printf(buf, "of 0x") < 0)
|
||||||
|
return -1;
|
||||||
|
for(dptr = bindata->data; dptr < bindata->data + bindata->size; dptr++) {
|
||||||
|
if(dptr - bindata->data >= 16) {
|
||||||
|
if(ldns_buffer_printf(buf, "...") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(length == 0) {
|
break;
|
||||||
if(getdns_snprintf(str, size, total, " []"))
|
|
||||||
return *total;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(item->dtype == t_dict || item->dtype == t_list)
|
if(ldns_buffer_printf(buf, "%.2x", *dptr) < 0)
|
||||||
if(getdns_snprintf(str, size, total, "\n%s", getdns_indent(indent)))
|
return -1;
|
||||||
return *total;
|
}
|
||||||
|
if(ldns_buffer_printf(buf, ">") < 0)
|
||||||
getdns_snprint_item(str, size, total, indent, item->dtype, item->data);
|
return -1;
|
||||||
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
indent -= 2;
|
return ldns_buffer_position(buf) - p;
|
||||||
if (getdns_snprintf(str, size, total, i ? "\n%s}" : "}",
|
} /* getdns_pp_bindata */
|
||||||
getdns_indent(indent)))
|
|
||||||
return *total;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* getdns_snprint_dict */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
getdns_snprint_list(char **str, size_t *size, int *total, size_t indent, struct getdns_list *list)
|
getdns_pp_dict(ldns_buffer *buf, size_t indent, struct getdns_dict *dict);
|
||||||
|
|
||||||
|
/*---------------------------------------- getdns_pp_list */
|
||||||
|
/**
|
||||||
|
* private function to pretty print list to a ldns_buffer
|
||||||
|
* @param buf buffer to write to
|
||||||
|
* @param indent number of spaces to append after newline
|
||||||
|
* @param list the to list print
|
||||||
|
* @return on success the number of written characters
|
||||||
|
* if an output error is encountered, a negative value
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getdns_pp_list(ldns_buffer *buf, size_t indent, struct getdns_list *list)
|
||||||
{
|
{
|
||||||
|
size_t i, length, p = ldns_buffer_position(buf);
|
||||||
getdns_data_type dtype;
|
getdns_data_type dtype;
|
||||||
union getdns_item data;
|
struct getdns_dict *dict_item;
|
||||||
size_t i, length;
|
struct getdns_list *list_item;
|
||||||
|
struct getdns_bindata *bindata_item;
|
||||||
|
uint32_t int_item;
|
||||||
|
|
||||||
if(list == NULL)
|
if(list == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(getdns_snprintf(str, size, total, "["))
|
if(ldns_buffer_printf(buf, "[") < 0)
|
||||||
return *total;
|
return -1;
|
||||||
|
|
||||||
if (getdns_list_get_length(list, &length) != GETDNS_RETURN_GOOD)
|
if (getdns_list_get_length(list, &length) != GETDNS_RETURN_GOOD)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -547,123 +521,156 @@ getdns_snprint_list(char **str, size_t *size, int *total, size_t indent, struct
|
||||||
indent += 2;
|
indent += 2;
|
||||||
for(i = 0; i < length; i++)
|
for(i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
if(getdns_snprintf(str, size, total,
|
if(ldns_buffer_printf(buf, "%s\n%s", (i ? "," : ""),
|
||||||
"%s\n%s", (i ? "," : ""), getdns_indent(indent)))
|
getdns_indent(indent)) < 0)
|
||||||
return *total;
|
return -1;
|
||||||
|
|
||||||
if(getdns_list_get_data_type(list, i, &dtype) != GETDNS_RETURN_GOOD)
|
if(getdns_list_get_data_type(list, i, &dtype) != GETDNS_RETURN_GOOD)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if((dtype == t_bindata &&
|
switch(dtype) {
|
||||||
getdns_list_get_bindata(list, i, &data.bindata) != GETDNS_RETURN_GOOD) ||
|
case t_int : if (getdns_list_get_int(list, i, &int_item) !=
|
||||||
(dtype == t_dict &&
|
GETDNS_RETURN_GOOD)
|
||||||
getdns_list_get_dict(list, i, &data.dict) != GETDNS_RETURN_GOOD) ||
|
if(ldns_buffer_printf(buf, " %d", (int)int_item) < 0)
|
||||||
(dtype == t_int &&
|
return -1;
|
||||||
getdns_list_get_int(list, i, &data.n) != GETDNS_RETURN_GOOD) ||
|
break;
|
||||||
(dtype == t_list &&
|
|
||||||
getdns_list_get_list(list, i, &data.list) != GETDNS_RETURN_GOOD))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(getdns_snprint_item(str, size, total, indent, dtype, data))
|
case t_bindata: if (getdns_list_get_bindata(list, i, &bindata_item) !=
|
||||||
return *total;
|
GETDNS_RETURN_GOOD)
|
||||||
|
return -1;
|
||||||
|
if (getdns_pp_bindata(buf, indent, bindata_item) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case t_list : if (getdns_list_get_list(list, i, &list_item) !=
|
||||||
|
GETDNS_RETURN_GOOD)
|
||||||
|
return -1;
|
||||||
|
if (getdns_pp_list(buf, indent, list_item) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case t_dict : if (getdns_list_get_dict(list, i, &dict_item) !=
|
||||||
|
GETDNS_RETURN_GOOD)
|
||||||
|
return -1;
|
||||||
|
if (getdns_pp_dict(buf, indent, dict_item) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case t_invalid:
|
||||||
|
default : if(ldns_buffer_printf(buf, " <invalid>") < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
indent -= 2;
|
indent -= 2;
|
||||||
if (getdns_snprintf(str, size, total, i ? "\n%s]" : "]",
|
if (ldns_buffer_printf(buf, i ? "\n%s]" : "]", getdns_indent(indent)) < 0)
|
||||||
getdns_indent(indent)))
|
return -1;
|
||||||
return *total;
|
|
||||||
|
|
||||||
return 0;
|
return ldns_buffer_position(buf) - p;
|
||||||
} /* getdns_snprint_dict */
|
} /* getdns_pp_list */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------- getdns_pp_dict */
|
||||||
|
/**
|
||||||
|
* private function to pretty print dict to a ldns_buffer
|
||||||
|
* @param buf buffer to write to
|
||||||
|
* @param indent number of spaces to append after newline
|
||||||
|
* @param dict the dict to print
|
||||||
|
* @return on success the number of written characters
|
||||||
|
* if an output error is encountered, a negative value
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
getdns_snprint_item(char **str, size_t *size, int *total, size_t indent, getdns_data_type dtype, union getdns_item item)
|
getdns_pp_dict(ldns_buffer *buf, size_t indent, struct getdns_dict *dict)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i, length, p = ldns_buffer_position(buf);
|
||||||
|
struct getdns_dict_item *item;
|
||||||
|
|
||||||
switch(dtype)
|
if(dict == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(ldns_buffer_printf(buf, "{") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
indent += 2;
|
||||||
|
LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(dict->root))
|
||||||
{
|
{
|
||||||
case t_bindata:
|
if(ldns_buffer_printf(buf, "%s\n%s\"%s\":", (i ? "," : "")
|
||||||
if(getdns_snprintf(str, size, total, " <bindata ", (int)item.bindata->size))
|
, getdns_indent(indent)
|
||||||
return *total;
|
, item->node.key) < 0)
|
||||||
i = 0;
|
return -1;
|
||||||
if(item.bindata->size && item.bindata->data[item.bindata->size - 1] == 0)
|
|
||||||
while(i < item.bindata->size - 1 && isprint(item.bindata->data[i]))
|
|
||||||
i++;
|
|
||||||
if(i >= item.bindata->size - 1) {
|
|
||||||
if(getdns_snprintf(str, size, total, "\"%s\">", item.bindata->data))
|
|
||||||
return *total;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for(i = 0; i < item.bindata->size; i++) {
|
|
||||||
if(i >= 16) {
|
|
||||||
if(getdns_snprintf(str, size, total, "..."))
|
|
||||||
return *total;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(getdns_snprintf(str, size, total, "%.2X", (int)item.bindata->data[i]))
|
|
||||||
return *total;
|
|
||||||
}
|
|
||||||
if(getdns_snprintf(str, size, total, ">"))
|
|
||||||
return *total;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case t_dict:
|
switch(item->dtype) {
|
||||||
if(getdns_snprint_dict(str, size, total, indent, item.dict))
|
case t_int : if(ldns_buffer_printf(buf, " %d", item->data.n) < 0)
|
||||||
return *total;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case t_int:
|
case t_bindata: if (getdns_pp_bindata(buf, indent,
|
||||||
if(getdns_snprintf(str, size, total, " %d", (int)item.n))
|
item->data.bindata) < 0)
|
||||||
return *total;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case t_list:
|
case t_list : /* Don't put empty lists on a new line */
|
||||||
if(getdns_snprint_list(str, size, total, indent, item.list))
|
|
||||||
return *total;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case t_invalid:
|
if(getdns_list_get_length(item->data.list,
|
||||||
default:
|
&length) != GETDNS_RETURN_GOOD)
|
||||||
if(getdns_snprintf(str, size, total, " <invalid>"))
|
return -1;
|
||||||
return *total;
|
if(length == 0) {
|
||||||
break;
|
if(ldns_buffer_printf(buf, " []") < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(ldns_buffer_printf(buf, "\n%s", getdns_indent(indent)) < 0)
|
||||||
|
return -1;
|
||||||
|
if(getdns_pp_list(buf, indent, item->data.list) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case t_dict : if(ldns_buffer_printf(buf, "\n%s", getdns_indent(indent)) < 0)
|
||||||
|
return -1;
|
||||||
|
if(getdns_pp_dict(buf, indent, item->data.dict) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case t_invalid:
|
||||||
|
default : if(ldns_buffer_printf(buf, " <invalid>") < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
return 0;
|
indent -= 2;
|
||||||
}
|
if (ldns_buffer_printf(buf, i ? "\n%s}" : "}", getdns_indent(indent)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ldns_buffer_position(buf) - p;
|
||||||
|
} /* getdns_pp_dict */
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------- getdns_pretty_print_dict */
|
/*---------------------------------------- getdns_pretty_print_dict */
|
||||||
|
/**
|
||||||
|
* Return a character string containing a "human readable" representation
|
||||||
|
* of dict.
|
||||||
|
* @param dict the dict to pretty print
|
||||||
|
* @return the "human readable" representation of dict
|
||||||
|
* or NULL on error
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
getdns_pretty_print_dict(struct getdns_dict *dict)
|
getdns_pretty_print_dict(struct getdns_dict *dict)
|
||||||
{
|
{
|
||||||
size_t size = 1024;
|
ldns_buffer *buf;
|
||||||
char buf[1024];
|
char *ret;
|
||||||
char *str, *newstr;
|
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
str = buf;
|
buf = ldns_buffer_new(100);
|
||||||
if(getdns_snprint_dict(&str, &size, &total, 0, dict))
|
if (! buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(total == 0)
|
if (getdns_pp_dict(buf, 0, dict) < 0) {
|
||||||
return strdup("");
|
ldns_buffer_free(buf);
|
||||||
|
|
||||||
if(total <= size)
|
|
||||||
return strdup(buf);
|
|
||||||
|
|
||||||
total += 1;
|
|
||||||
str = newstr = (char *)malloc((size_t) total * sizeof(char));
|
|
||||||
if(!str)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
size = total;
|
|
||||||
total = 0;
|
|
||||||
if (getdns_snprint_dict(&str, &size, &total, 0, dict)) {
|
|
||||||
free(newstr);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return newstr;
|
ret = (char *)ldns_buffer_export(buf);
|
||||||
|
ldns_buffer_free(buf);
|
||||||
|
return ret;
|
||||||
} /* getdns_pretty_print_dict */
|
} /* getdns_pretty_print_dict */
|
||||||
|
|
||||||
/* getdns_dict.c */
|
/* getdns_dict.c */
|
||||||
|
|
Loading…
Reference in New Issue