From 81dee1bb528a95f7bf2bc622948807150794a75e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 17 May 2011 12:13:23 -0400 Subject: [PATCH] Add "encoding" for sequence and array of integers Signed-off-by: Mathieu Desnoyers --- formats/ctf-text/types/array.c | 29 +++++++- formats/ctf-text/types/integer.c | 13 ++++ formats/ctf/ctf.c | 8 +-- .../metadata/ctf-visitor-generate-io-struct.c | 34 ++++++++- formats/ctf/types/array.c | 70 ++++++++++++++++++- formats/ctf/types/sequence.c | 66 ++++++++++++++++- include/babeltrace/ctf-text/types.h | 1 + include/babeltrace/ctf/types.h | 6 +- include/babeltrace/types.h | 18 +++-- types/array.c | 38 ++++++++-- types/float.c | 9 ++- types/integer.c | 4 +- types/sequence.c | 34 +++++++-- 13 files changed, 296 insertions(+), 34 deletions(-) diff --git a/formats/ctf-text/types/array.c b/formats/ctf-text/types/array.c index 9524ba16..db941426 100644 --- a/formats/ctf-text/types/array.c +++ b/formats/ctf-text/types/array.c @@ -22,8 +22,13 @@ 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) @@ -32,6 +37,28 @@ int ctf_text_array_write(struct stream_pos *ppos, struct definition *definition) 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++; } diff --git a/formats/ctf-text/types/integer.c b/formats/ctf-text/types/integer.c index 3d1c459f..1337eca3 100644 --- a/formats/ctf-text/types/integer.c +++ b/formats/ctf-text/types/integer.c @@ -40,6 +40,19 @@ int ctf_text_integer_write(struct stream_pos *ppos, struct definition *definitio 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: diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 13c87eae..1ba00a67 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -63,8 +63,8 @@ rw_dispatch read_dispatch_table[] = { [ 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 @@ -75,8 +75,8 @@ rw_dispatch write_dispatch_table[] = { [ 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 diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 9dffdcbf..29068563 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -325,7 +325,7 @@ struct declaration *ctf_type_declarator_visit(FILE *fd, int depth, */ 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; } } @@ -1076,6 +1076,7 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, 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) { @@ -1164,6 +1165,34 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, __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); @@ -1184,7 +1213,8 @@ struct declaration *ctf_declaration_integer_visit(FILE *fd, int depth, } } integer_declaration = integer_declaration_new(size, - byte_order, signedness, alignment, base); + byte_order, signedness, alignment, + base, encoding); return &integer_declaration->p; } diff --git a/formats/ctf/types/array.c b/formats/ctf/types/array.c index 3fd0ad42..71475014 100644 --- a/formats/ctf/types/array.c +++ b/formats/ctf/types/array.c @@ -18,7 +18,73 @@ #include -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); } diff --git a/formats/ctf/types/sequence.c b/formats/ctf/types/sequence.c index acd4c7c0..a14d5891 100644 --- a/formats/ctf/types/sequence.c +++ b/formats/ctf/types/sequence.c @@ -18,11 +18,71 @@ #include -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); } diff --git a/include/babeltrace/ctf-text/types.h b/include/babeltrace/ctf-text/types.h index 0670b3d6..7703e7b8 100644 --- a/include/babeltrace/ctf-text/types.h +++ b/include/babeltrace/ctf-text/types.h @@ -39,6 +39,7 @@ struct ctf_text_stream_pos { int dummy; /* disable output */ int print_names; /* print field names */ int field_nr; + GString *string; /* Current string */ }; static inline diff --git a/include/babeltrace/ctf/types.h b/include/babeltrace/ctf/types.h index 95c0d5e2..1ec2ad5a 100644 --- a/include/babeltrace/ctf/types.h +++ b/include/babeltrace/ctf/types.h @@ -76,8 +76,10 @@ int ctf_enum_read(struct stream_pos *pos, struct definition *definition); 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); diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 2aa45b8a..da9ca5c5 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -129,6 +129,13 @@ int generic_rw(struct stream_pos *pos, struct definition *definition) 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 @@ -140,6 +147,7 @@ struct declaration_integer { 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 { @@ -225,12 +233,6 @@ struct definition_enum { 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; @@ -297,6 +299,7 @@ struct definition_array { 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 { @@ -312,6 +315,7 @@ struct definition_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, @@ -381,7 +385,7 @@ void definition_unref(struct definition *definition); 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 diff --git a/types/array.c b/types/array.c index 0be26476..6c17299a 100644 --- a/types/array.c +++ b/types/array.c @@ -110,6 +110,25 @@ struct definition * 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++) { @@ -129,6 +148,7 @@ struct definition * if (!*field) goto error; } + return &array->p; error: @@ -152,13 +172,17 @@ void _array_definition_free(struct definition *definition) 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); @@ -166,11 +190,15 @@ void _array_definition_free(struct definition *definition) 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); diff --git a/types/float.c b/types/float.c index 5ae831ce..dab8d0da 100644 --- a/types/float.c +++ b/types/float.c @@ -58,11 +58,14 @@ struct declaration_float * 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; } diff --git a/types/integer.c b/types/integer.c index 940963a5..6a95b939 100644 --- a/types/integer.c +++ b/types/integer.c @@ -39,7 +39,8 @@ void _integer_declaration_free(struct declaration *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; @@ -54,6 +55,7 @@ struct declaration_integer * integer_declaration->byte_order = byte_order; integer_declaration->signedness = signedness; integer_declaration->base = base; + integer_declaration->encoding = encoding; return integer_declaration; } diff --git a/types/sequence.c b/types/sequence.c index 119522d7..676d9ef6 100644 --- a/types/sequence.c +++ b/types/sequence.c @@ -151,6 +151,26 @@ struct definition *_sequence_definition_new(struct declaration *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; @@ -169,11 +189,15 @@ void _sequence_definition_free(struct definition *definition) 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); @@ -189,6 +213,8 @@ uint64_t sequence_len(struct definition_sequence *sequence) 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); -- 2.34.1