int ctf_text_array_write(struct stream_pos *ppos, struct definition *definition)
{
struct ctf_text_stream_pos *pos = ctf_text_pos(ppos);
+ struct definition_array *array_definition =
+ container_of(definition, struct definition_array, p);
+ struct declaration_array *array_declaration =
+ array_definition->declaration;
+ struct declaration *elem = array_declaration->elem;
int field_nr_saved;
- int ret;
+ int ret = 0;
if (!pos->dummy) {
if (pos->field_nr++ != 0)
if (pos->print_names)
fprintf(pos->fp, "%s = ",
g_quark_to_string(definition->name));
+ }
+
+ if (elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ if (!(integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT)) {
+ pos->string = array_definition->string;
+ g_string_assign(array_definition->string, "");
+ ret = array_rw(ppos, definition);
+ pos->string = NULL;
+ }
+ fprintf(pos->fp, "\"%s\"", array_definition->string->str);
+ return ret;
+ }
+ }
+
+ if (!pos->dummy) {
fprintf(pos->fp, "[");
pos->depth++;
}
fprintf(pos->fp, "%s = ",
g_quark_to_string(definition->name));
+ if (integer_declaration->encoding == CTF_STRING_ASCII
+ || integer_declaration->encoding == CTF_STRING_UTF8) {
+
+ if (!integer_declaration->signedness) {
+ g_string_append_c(pos->string,
+ (int) integer_definition->value._unsigned);
+ } else {
+ g_string_append_c(pos->string,
+ (int) integer_definition->value._signed);
+ }
+ return 0;
+ }
+
switch (integer_declaration->base) {
case 0: /* default */
case 10:
[ CTF_TYPE_STRING ] = ctf_string_read,
[ CTF_TYPE_STRUCT ] = ctf_struct_rw,
[ CTF_TYPE_VARIANT ] = ctf_variant_rw,
- [ CTF_TYPE_ARRAY ] = ctf_array_rw,
- [ CTF_TYPE_SEQUENCE ] = ctf_sequence_rw,
+ [ CTF_TYPE_ARRAY ] = ctf_array_read,
+ [ CTF_TYPE_SEQUENCE ] = ctf_sequence_read,
};
static
[ CTF_TYPE_STRING ] = ctf_string_write,
[ CTF_TYPE_STRUCT ] = ctf_struct_rw,
[ CTF_TYPE_VARIANT ] = ctf_variant_rw,
- [ CTF_TYPE_ARRAY ] = ctf_array_rw,
- [ CTF_TYPE_SEQUENCE ] = ctf_sequence_rw,
+ [ CTF_TYPE_ARRAY ] = ctf_array_write,
+ [ CTF_TYPE_SEQUENCE ] = ctf_sequence_write,
};
static
*/
integer_declaration = integer_declaration_new(integer_declaration->len,
integer_declaration->byte_order, integer_declaration->signedness,
- integer_declaration->p.alignment, 16);
+ integer_declaration->p.alignment, 16, integer_declaration->encoding);
nested_declaration = &integer_declaration->p;
}
}
int signedness = 0;
int has_alignment = 0, has_size = 0;
int base = 0;
+ enum ctf_string_encoding encoding = CTF_STRING_NONE;
struct declaration_integer *integer_declaration;
cds_list_for_each_entry(expression, expressions, siblings) {
__func__);
return NULL;
}
+ } else if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
+ char *s_right;
+
+ if (right->u.unary_expression.type != UNARY_STRING) {
+ fprintf(fd, "[error] %s: encoding: expecting unary string\n",
+ __func__);
+ return NULL;
+ }
+ s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
+ if (!s_right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for integer base\n", __func__);
+ g_free(s_right);
+ return NULL;
+ }
+ if (!strcmp(s_right, "UTF8")
+ || !strcmp(s_right, "utf8")
+ || !strcmp(s_right, "utf-8")
+ || !strcmp(s_right, "UTF-8"))
+ encoding = CTF_STRING_UTF8;
+ else if (!strcmp(s_right, "ASCII")
+ || !strcmp(s_right, "ascii"))
+ encoding = CTF_STRING_ASCII;
+ else {
+ fprintf(fd, "[error] %s: unknown string encoding \"%s\"\n", __func__, s_right);
+ g_free(s_right);
+ return NULL;
+ }
+ g_free(s_right);
} else {
fprintf(fd, "[error] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
}
}
integer_declaration = integer_declaration_new(size,
- byte_order, signedness, alignment, base);
+ byte_order, signedness, alignment,
+ base, encoding);
return &integer_declaration->p;
}
#include <babeltrace/ctf/types.h>
-int ctf_array_rw(struct stream_pos *pos, struct definition *definition)
+int ctf_array_read(struct stream_pos *ppos, struct definition *definition)
{
- return array_rw(pos, definition);
+ struct definition_array *array_definition =
+ container_of(definition, struct definition_array, p);
+ struct declaration_array *array_declaration =
+ array_definition->declaration;
+ struct declaration *elem = array_declaration->elem;
+ struct ctf_stream_pos *pos =
+ container_of(ppos, struct ctf_stream_pos, parent);
+
+ if (elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+
+ ctf_align_pos(pos, integer_declaration->p.alignment);
+ if (!ctf_pos_access_ok(pos, array_declaration->len * CHAR_BIT))
+ return -EFAULT;
+
+ g_string_assign(array_definition->string, "");
+ g_string_insert_len(array_definition->string,
+ 0, (char *) ctf_get_pos_addr(pos),
+ array_declaration->len);
+ ctf_move_pos(pos, array_declaration->len * CHAR_BIT);
+ return 0;
+ }
+ }
+ }
+ return array_rw(ppos, definition);
+}
+
+int ctf_array_write(struct stream_pos *ppos, struct definition *definition)
+{
+ struct definition_array *array_definition =
+ container_of(definition, struct definition_array, p);
+ struct declaration_array *array_declaration =
+ array_definition->declaration;
+ struct declaration *elem = array_declaration->elem;
+ struct ctf_stream_pos *pos =
+ container_of(ppos, struct ctf_stream_pos, parent);
+
+ if (elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+
+ ctf_align_pos(pos, integer_declaration->p.alignment);
+ if (!ctf_pos_access_ok(pos, array_declaration->len * CHAR_BIT))
+ return -EFAULT;
+
+ memcpy((char *) ctf_get_pos_addr(pos),
+ array_definition->string->str,
+ array_declaration->len);
+ ctf_move_pos(pos, array_declaration->len * CHAR_BIT);
+ return 0;
+ }
+ }
+ }
+ return array_rw(ppos, definition);
}
#include <babeltrace/ctf/types.h>
-int ctf_sequence_rw(struct stream_pos *ppos, struct definition *definition)
+int ctf_sequence_read(struct stream_pos *ppos, struct definition *definition)
{
- struct declaration *declaration = definition->declaration;
+ struct definition_sequence *sequence_definition =
+ container_of(definition, struct definition_sequence, p);
+ struct declaration_sequence *sequence_declaration =
+ sequence_definition->declaration;
+ struct declaration *elem = sequence_declaration->elem;
struct ctf_stream_pos *pos = ctf_pos(ppos);
- ctf_align_pos(pos, declaration->alignment);
+ if (elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+ uint64_t len = sequence_len(sequence_definition);
+
+ ctf_align_pos(pos, integer_declaration->p.alignment);
+ if (!ctf_pos_access_ok(pos, len * CHAR_BIT))
+ return -EFAULT;
+
+ g_string_assign(sequence_definition->string, "");
+ g_string_insert_len(sequence_definition->string,
+ 0, (char *) ctf_get_pos_addr(pos), len);
+ ctf_move_pos(pos, len * CHAR_BIT);
+ return 0;
+ }
+ }
+ }
+ return sequence_rw(ppos, definition);
+}
+
+int ctf_sequence_write(struct stream_pos *ppos, struct definition *definition)
+{
+ struct definition_sequence *sequence_definition =
+ container_of(definition, struct definition_sequence, p);
+ struct declaration_sequence *sequence_declaration =
+ sequence_definition->declaration;
+ struct declaration *elem = sequence_declaration->elem;
+ struct ctf_stream_pos *pos = ctf_pos(ppos);
+
+ if (elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+ uint64_t len = sequence_len(sequence_definition);
+
+ ctf_align_pos(pos, integer_declaration->p.alignment);
+ if (!ctf_pos_access_ok(pos, len * CHAR_BIT))
+ return -EFAULT;
+
+ memcpy((char *) ctf_get_pos_addr(pos),
+ sequence_definition->string->str, len);
+ ctf_move_pos(pos, len * CHAR_BIT);
+ return 0;
+ }
+ }
+ }
return sequence_rw(ppos, definition);
}
int dummy; /* disable output */
int print_names; /* print field names */
int field_nr;
+ GString *string; /* Current string */
};
static inline
int ctf_enum_write(struct stream_pos *pos, struct definition *definition);
int ctf_struct_rw(struct stream_pos *pos, struct definition *definition);
int ctf_variant_rw(struct stream_pos *pos, struct definition *definition);
-int ctf_array_rw(struct stream_pos *pos, struct definition *definition);
-int ctf_sequence_rw(struct stream_pos *pos, struct definition *definition);
+int ctf_array_read(struct stream_pos *pos, struct definition *definition);
+int ctf_array_write(struct stream_pos *pos, struct definition *definition);
+int ctf_sequence_read(struct stream_pos *pos, struct definition *definition);
+int ctf_sequence_write(struct stream_pos *pos, struct definition *definition);
void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence);
return call(pos, definition);
}
+enum ctf_string_encoding {
+ CTF_STRING_NONE = 0,
+ CTF_STRING_UTF8,
+ CTF_STRING_ASCII,
+ CTF_STRING_UNKNOWN,
+};
+
/*
* Because we address in bits, bitfields end up being exactly the same as
* integers, except that their read/write functions must be able to deal with
int byte_order; /* byte order */
int signedness;
int base; /* Base for pretty-printing: 2, 8, 10, 16 */
+ enum ctf_string_encoding encoding;
};
struct definition_integer {
GArray *value;
};
-enum ctf_string_encoding {
- CTF_STRING_UTF8 = 0,
- CTF_STRING_ASCII,
- CTF_STRING_UNKNOWN,
-};
-
struct declaration_string {
struct declaration p;
enum ctf_string_encoding encoding;
struct declaration_array *declaration;
struct definition_scope *scope;
GPtrArray *elems; /* Array of pointers to struct definition */
+ GString *string; /* String for encoded integer children */
};
struct declaration_sequence {
struct definition_scope *scope;
struct definition_integer *length;
GPtrArray *elems; /* Array of pointers to struct definition */
+ GString *string; /* String for encoded integer children */
};
int register_declaration(GQuark declaration_name,
struct declaration_integer *integer_declaration_new(size_t len, int byte_order,
int signedness, size_t alignment,
- int base);
+ int base, enum ctf_string_encoding encoding);
/*
* mantissa_len is the length of the number of bytes represented by the mantissa
ret = register_field_definition(field_name, &array->p,
parent_scope);
assert(!ret);
+ array->string = NULL;
+ array->elems = NULL;
+
+ if (array_declaration->elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(array_declaration->elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ array->string = g_string_new("");
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+ return &array->p;
+ }
+ }
+ }
+
array->elems = g_ptr_array_sized_new(array_declaration->len);
g_ptr_array_set_size(array->elems, array_declaration->len);
for (i = 0; i < array_declaration->len; i++) {
if (!*field)
goto error;
}
+
return &array->p;
error:
container_of(definition, struct definition_array, p);
uint64_t i;
- for (i = 0; i < array->elems->len; i++) {
- struct definition *field;
+ if (array->string)
+ (void) g_string_free(array->string, TRUE);
+ if (array->elems) {
+ for (i = 0; i < array->elems->len; i++) {
+ struct definition *field;
- field = g_ptr_array_index(array->elems, i);
- field->declaration->definition_free(field);
+ field = g_ptr_array_index(array->elems, i);
+ field->declaration->definition_free(field);
+ }
+ (void) g_ptr_array_free(array->elems, TRUE);
}
- (void) g_ptr_array_free(array->elems, TRUE);
free_definition_scope(array->scope);
declaration_unref(array->p.declaration);
g_free(array);
uint64_t array_len(struct definition_array *array)
{
+ if (!array->elems)
+ return array->string->len;
return array->elems->len;
}
struct definition *array_index(struct definition_array *array, uint64_t i)
{
+ if (!array->elems)
+ return NULL;
if (i >= array->elems->len)
return NULL;
return g_ptr_array_index(array->elems, i);
float_declaration->byte_order = byte_order;
float_declaration->sign = integer_declaration_new(1,
- byte_order, false, 1, 2);
+ byte_order, false, 1, 2,
+ CTF_STRING_NONE);
float_declaration->mantissa = integer_declaration_new(mantissa_len - 1,
- byte_order, false, 1, 10);
+ byte_order, false, 1, 10,
+ CTF_STRING_NONE);
float_declaration->exp = integer_declaration_new(exp_len,
- byte_order, true, 1, 10);
+ byte_order, true, 1, 10,
+ CTF_STRING_NONE);
return float_declaration;
}
struct declaration_integer *
integer_declaration_new(size_t len, int byte_order,
- int signedness, size_t alignment, int base)
+ int signedness, size_t alignment, int base,
+ enum ctf_string_encoding encoding)
{
struct declaration_integer *integer_declaration;
integer_declaration->byte_order = byte_order;
integer_declaration->signedness = signedness;
integer_declaration->base = base;
+ integer_declaration->encoding = encoding;
return integer_declaration;
}
goto error;
}
definition_ref(len_parent);
+
+ sequence->string = NULL;
+ sequence->elems = NULL;
+
+ if (sequence_declaration->elem->id == CTF_TYPE_INTEGER) {
+ struct declaration_integer *integer_declaration =
+ container_of(sequence_declaration->elem, struct declaration_integer, p);
+
+ if (integer_declaration->encoding == CTF_STRING_UTF8
+ || integer_declaration->encoding == CTF_STRING_ASCII) {
+
+ sequence->string = g_string_new("");
+
+ if (integer_declaration->len == CHAR_BIT
+ && integer_declaration->p.alignment == CHAR_BIT) {
+ return &sequence->p;
+ }
+ }
+ }
+
sequence->elems = g_ptr_array_new();
return &sequence->p;
struct definition *len_definition = &sequence->length->p;
uint64_t i;
- for (i = 0; i < sequence->elems->len; i++) {
- struct definition *field;
+ if (sequence->string)
+ (void) g_string_free(sequence->string, TRUE);
+ if (sequence->elems) {
+ for (i = 0; i < sequence->elems->len; i++) {
+ struct definition *field;
- field = g_ptr_array_index(sequence->elems, i);
- field->declaration->definition_free(field);
+ field = g_ptr_array_index(sequence->elems, i);
+ field->declaration->definition_free(field);
+ }
}
(void) g_ptr_array_free(sequence->elems, TRUE);
definition_unref(len_definition);
struct definition *sequence_index(struct definition_sequence *sequence, uint64_t i)
{
+ if (!sequence->elems)
+ return NULL;
if (i >= sequence->length->value._unsigned)
return NULL;
assert(i < sequence->elems->len);