feat(573file): add support for prop-valued arrays

This commit is contained in:
decafcode
2023-11-19 22:18:03 -05:00
committed by decafcode
parent f8550538ac
commit b9db39926f
6 changed files with 109 additions and 33 deletions

View File

@@ -391,7 +391,7 @@ static int prop_binary_slice_value(struct prop_binary_parser *bp, uint8_t type,
orig_nbytes = prop_type_to_size(type);
if (orig_nbytes < 0) {
if (orig_nbytes < 0 || prop_type_is_array(type)) {
is_variable = true;
r = iobuf_read_be32(&bp->body, &nbytes);

View File

@@ -22,7 +22,13 @@ static const int prop_type_sizes[64] = {
[PROP_ATTR] = -1, [PROP_BOOL] = 1,
};
bool prop_type_is_array(enum prop_type type) {
return (type & PROP_ARRAY_FLAG) != 0;
}
bool prop_type_is_valid(enum prop_type type) {
type &= ~PROP_ARRAY_FLAG;
if (type < 0 || type >= lengthof(prop_type_names)) {
return false;
}
@@ -33,11 +39,11 @@ bool prop_type_is_valid(enum prop_type type) {
const char *prop_type_to_string(enum prop_type type) {
assert(prop_type_is_valid(type));
return prop_type_names[type];
return prop_type_names[type & ~PROP_ARRAY_FLAG];
}
int prop_type_to_size(enum prop_type type) {
assert(type == PROP_ATTR /* hack */ || prop_type_is_valid(type));
return prop_type_sizes[type];
return prop_type_sizes[type & ~PROP_ARRAY_FLAG];
}

View File

@@ -23,6 +23,7 @@ enum prop_type {
PROP_ARRAY_FLAG = 0x40
};
bool prop_type_is_array(enum prop_type type);
bool prop_type_is_valid(enum prop_type type);
const char *prop_type_to_string(enum prop_type type);
int prop_type_to_size(enum prop_type type);

View File

@@ -1,5 +1,6 @@
#include <assert.h>
#include "573file/prop-type.h"
#include "573file/prop-xml-writer.h"
#include "573file/prop.h"
@@ -26,6 +27,10 @@ static void prop_xml_write_void(struct strbuf *dest, const struct prop *p,
unsigned int indent);
static void prop_xml_write_text(struct strbuf *dest, const struct prop *p,
enum prop_xml_escape ctx);
static void prop_xml_write_text_element(struct strbuf *dest,
enum prop_type type,
struct const_iobuf *src,
enum prop_xml_escape ctx);
static void prop_xml_write_text_s8(struct strbuf *dest,
struct const_iobuf *src);
static void prop_xml_write_text_s16(struct strbuf *dest,
@@ -154,6 +159,10 @@ static void prop_xml_write_nonvoid(struct strbuf *dest, const struct prop *p,
prop_xml_write_indent(dest, indent);
strbuf_printf(dest, "<%s __type=\"%s\"", name, type_str);
if (prop_type_is_array(type)) {
strbuf_printf(dest, " __count=\"%lu\"", (unsigned long)prop_get_count(p));
}
first_child = prop_get_first_child_const(p);
if (first_child != NULL) {
@@ -275,91 +284,124 @@ static void prop_xml_write_indent(struct strbuf *dest, unsigned int indent) {
static void prop_xml_write_text(struct strbuf *dest, const struct prop *p,
enum prop_xml_escape ctx) {
struct const_iobuf src;
struct const_iobuf value;
struct const_iobuf item;
enum prop_type type;
uint32_t count;
uint32_t i;
int item_size;
int r;
type = prop_get_type(p);
prop_borrow_value(p, &src);
prop_borrow_value(p, &value);
if (prop_type_is_array(type)) {
item_size = prop_type_to_size(type);
count = prop_get_count(p);
assert(item_size > 0);
for (i = 0; i < count; i++) {
if (i > 0) {
strbuf_putc(dest, ' ');
}
r = iobuf_slice(&item, &value, item_size);
assert(r >= 0);
prop_xml_write_text_element(dest, type, &item, ctx);
}
} else {
prop_xml_write_text_element(dest, type, &value, ctx);
}
}
static void prop_xml_write_text_element(struct strbuf *dest,
enum prop_type type,
struct const_iobuf *src,
enum prop_xml_escape ctx) {
type &= ~PROP_ARRAY_FLAG;
switch (type) {
case PROP_S8:
prop_xml_write_text_s8(dest, &src);
prop_xml_write_text_s8(dest, src);
break;
case PROP_S16:
prop_xml_write_text_s16(dest, &src);
prop_xml_write_text_s16(dest, src);
break;
case PROP_S32:
prop_xml_write_text_s32(dest, &src);
prop_xml_write_text_s32(dest, src);
break;
case PROP_S64:
prop_xml_write_text_s64(dest, &src);
prop_xml_write_text_s64(dest, src);
break;
case PROP_U8:
prop_xml_write_text_u8(dest, &src);
prop_xml_write_text_u8(dest, src);
break;
case PROP_U16:
prop_xml_write_text_u16(dest, &src);
prop_xml_write_text_u16(dest, src);
break;
case PROP_U32:
prop_xml_write_text_u32(dest, &src);
prop_xml_write_text_u32(dest, src);
break;
case PROP_U64:
prop_xml_write_text_u64(dest, &src);
prop_xml_write_text_u64(dest, src);
break;
case PROP_BIN:
prop_xml_write_text_bin(dest, &src);
prop_xml_write_text_bin(dest, src);
break;
case PROP_STR:
prop_xml_write_text_str(dest, &src, ctx);
prop_xml_write_text_str(dest, src, ctx);
break;
case PROP_IP4:
prop_xml_write_text_ip4(dest, &src);
prop_xml_write_text_ip4(dest, src);
break;
case PROP_TIME:
/* Reuse the u32 writer for timestamps */
prop_xml_write_text_u32(dest, &src);
prop_xml_write_text_u32(dest, src);
break;
case PROP_2U16:
prop_xml_write_text_u16_tuple(dest, &src, 2);
prop_xml_write_text_u16_tuple(dest, src, 2);
break;
case PROP_3S32:
prop_xml_write_text_s32_tuple(dest, &src, 3);
prop_xml_write_text_s32_tuple(dest, src, 3);
break;
case PROP_4U16:
prop_xml_write_text_u16_tuple(dest, &src, 4);
prop_xml_write_text_u16_tuple(dest, src, 4);
break;
case PROP_BOOL:
prop_xml_write_text_bool(dest, &src);
prop_xml_write_text_bool(dest, src);
break;

View File

@@ -37,13 +37,8 @@ static int prop_validate(const char *name, enum prop_type type,
static int prop_validate(const char *name, enum prop_type type,
const void *bytes, uint32_t nbytes) {
const char *chars;
int expected_nbytes;
if (type & PROP_ARRAY_FLAG) {
log_write("\"%s\": Arrays are not currently supported", name);
return -ENOTSUP;
}
const char *type_str;
int item_size;
if (!prop_type_is_valid(type)) {
log_write("\"%s\": Unsupported type code %#x", name, type);
@@ -51,13 +46,30 @@ static int prop_validate(const char *name, enum prop_type type,
return -ENOTSUP;
}
expected_nbytes = prop_type_to_size(type);
item_size = prop_type_to_size(type);
type_str = prop_type_to_string(type);
if (expected_nbytes >= 0 && nbytes != expected_nbytes) {
log_write("\"%s\": Incorrect size %#x for type %s (expected %#x)", name,
nbytes, prop_type_to_string(type), expected_nbytes);
if (prop_type_is_array(type)) {
if (item_size <= 0) {
log_write("\"%s\": Nonsensical array type %#x", name, type);
return -EINVAL;
return -EINVAL;
}
if (nbytes % item_size != 0) {
log_write(
"\"%s\": %s item size %i does not divide value length %#x evenly",
name, type_str, item_size, nbytes);
return -EINVAL;
}
} else {
if (item_size >= 0 && nbytes != item_size) {
log_write("\"%s\": Incorrect size %#x for type %s (expected %#x)", name,
nbytes, type_str, item_size);
return -EINVAL;
}
}
if (type == PROP_STR) {
@@ -194,6 +206,20 @@ const char *prop_get_attr(const struct prop *p, const char *key) {
return NULL;
}
uint32_t prop_get_count(const struct prop *p) {
int item_size;
assert(p != NULL);
assert(prop_type_is_array(p->type));
item_size = prop_type_to_size(p->type);
assert(item_size > 0);
assert(p->nbytes % item_size == 0);
return p->nbytes / item_size;
}
const struct attr *prop_get_first_attr(const struct prop *p) {
struct list_node *attr;

View File

@@ -15,6 +15,7 @@ void prop_free(struct prop *p);
void prop_append(struct prop *p, struct prop *child);
void prop_borrow_value(const struct prop *p, struct const_iobuf *out);
const char *prop_get_attr(const struct prop *p, const char *key);
uint32_t prop_get_count(const struct prop *p);
const struct attr *prop_get_first_attr(const struct prop *p);
struct prop *prop_get_first_child(struct prop *p);
const struct prop *prop_get_first_child_const(const struct prop *p);