[CRIU] [PATCH 1/6] protobuf: "pretty" show engine introduced
Kinsbursky Stanislav
skinsbursky at openvz.org
Fri Jul 27 10:06:27 EDT 2012
The idea is simple: pass array of pointers to show engine. Non-NULL function
pointer in the array indicates, that it's the pointer to corresponding custom
show function.
If the field is a nested message, then the pointer indicates another "pretty"
array for nested message.
Signed-off-by: Stanislav Kinsbursky <skinsbursky at openvz.org>
---
include/protobuf.h | 18 ++++++++++-
protobuf.c | 82 ++++++++++++++++++++++++++++++++++++----------------
2 files changed, 72 insertions(+), 28 deletions(-)
diff --git a/include/protobuf.h b/include/protobuf.h
index e13c3e4..f0262d5 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -24,10 +24,16 @@ typedef size_t (*pb_pack_t)(void *obj, void *where);
typedef void *(*pb_unpack_t)(void *allocator, size_t size, void *from);
typedef void (*pb_free_t)(void *obj, void *allocator);
+typedef void (*pb_pr_field_t)(void *obj, void *ctl);
+
extern int pb_read_object_with_header(int fd, void **pobj,
pb_unpack_t unpack,
bool eof);
+#ifdef CONFIG_X86_64
+#define PTR_TO_PRETTY_ARRAY(ptr) ((pb_pr_field_t)(((unsigned long)ptr) + (~LONG_MAX)))
+#endif
+
#define PB_UNPACK_TYPECHECK(__op, __fn) ({ if (0) *__op = __fn##__unpack(NULL, 0, NULL); (pb_unpack_t)&__fn##__unpack; })
#define PB_PACK_TYPECHECK(__o, __fn) ({ if (0) __fn##__pack(__o, NULL); (pb_pack_t)&__fn##__pack; })
#define PB_GPS_TYPECHECK(__o, __fn) ({ if (0) __fn##__get_packed_size(__o); (pb_getpksize_t)&__fn##__get_packed_size; })
@@ -61,14 +67,20 @@ extern int pb_write_object_with_header(int fd, void *obj,
extern void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *d,
pb_unpack_t unpack, pb_free_t free, int single_entry,
void (*payload_hadler)(int fd, void *obj, int flags),
- int flags);
+ int flags, pb_pr_field_t *pretty_array);
/* Don't have objects at hands to also do typechecking here */
#define pb_show_plain_payload(__fd, __proto_message_name, payload_hadler, flags) \
do_pb_show_plain(__fd, &__proto_message_name##__descriptor, \
(pb_unpack_t)__proto_message_name##__unpack, \
(pb_free_t)__proto_message_name##__free_unpacked, \
- 0, payload_hadler, flags)
+ 0, payload_hadler, flags, NULL)
+
+#define pb_show_plain_pretty(__fd, __proto_message_name, pretty_array) \
+ do_pb_show_plain(__fd, &__proto_message_name##__descriptor, \
+ (pb_unpack_t)__proto_message_name##__unpack, \
+ (pb_free_t)__proto_message_name##__free_unpacked, \
+ 0, NULL, 0, pretty_array)
#define pb_show_plain(__fd, __proto_message_name) \
pb_show_plain_payload(__fd, __proto_message_name, NULL, 0)
@@ -77,6 +89,6 @@ extern void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *d,
do_pb_show_plain(__fd, &__proto_message_name##__descriptor, \
(pb_unpack_t)__proto_message_name##__unpack, \
(pb_free_t)__proto_message_name##__free_unpacked, \
- 1, NULL, 0)
+ 1, NULL, 0, NULL)
#endif /* PROTOBUF_H__ */
diff --git a/protobuf.c b/protobuf.c
index 5970494..486e0f2 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -3,6 +3,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
+#include <limits.h>
#include <google/protobuf-c/protobuf-c.h>
@@ -20,33 +21,39 @@
*/
#define PB_PKOBJ_LOCAL_SIZE 1024
+#ifdef CONFIG_X86_64
+#define PRETTY_ARRAY_TO_PTR(ptr) ((void *)((unsigned long)ptr & LONG_MAX))
+#define IS_PRETTY_ARRAY(ptr) ((unsigned long)ptr & ~LONG_MAX)
+#endif
+
struct pb_pr_ctrl_s {
void *arg;
int single_entry;
int depth;
+ int field_nr;
+ const pb_pr_field_t *pretty_array;
};
typedef struct pb_pr_ctrl_s pb_pr_ctl_t;
-typedef void (pb_pr_field_t)(void *obj, pb_pr_ctl_t *ctl);
-static void pb_msg_int32x(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_int32x(void *obj, void *ctl)
{
pr_msg("0x%08x", *(int *)obj);
}
-static void pb_msg_int64x(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_int64x(void *obj, void *ctl)
{
pr_msg("0x%016lx", *(long *)obj);
}
-static void pb_msg_string(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_string(void *obj, void *ctl)
{
pr_msg("\"%s\"", *(char **)obj);
}
-static void pb_msg_unk(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_unk(void *obj, void *ctl)
{
- pr_msg("unknown object %p\n", obj);
+ pr_msg("unknown object %p", obj);
}
static inline void print_tabs(pb_pr_ctl_t *ctl)
@@ -62,6 +69,8 @@ static inline void print_tabs(pb_pr_ctl_t *ctl)
static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
{
+ if (ctl->pretty_array)
+ return;
if (right_brace)
print_tabs(ctl);
pr_msg("%s%s", (right_brace) ? "}" : "{", (ctl->single_entry) ? "\n" : " ");
@@ -69,17 +78,27 @@ static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl);
-static void show_nested_message(void *msg, pb_pr_ctl_t *ctl)
+static void show_nested_message(void *msg, void *arg)
{
- print_nested_message_braces(ctl, 0);
- ctl->depth++;
- pb_show_msg(msg, ctl);
- ctl->depth--;
- print_nested_message_braces(ctl, 1);
+ pb_pr_ctl_t *pctl = arg;
+ pb_pr_ctl_t ctl = {
+ .arg = pctl->arg,
+ .single_entry = pctl->single_entry,
+ .depth = pctl->depth + 1,
+ .field_nr = 0,
+ };
+
+ if (pctl->pretty_array)
+ ctl.pretty_array = PRETTY_ARRAY_TO_PTR(pctl->pretty_array[pctl->field_nr]);
+
+ print_nested_message_braces(&ctl, 0);
+ pb_show_msg(msg, &ctl);
+ print_nested_message_braces(&ctl, 1);
}
-static void show_enum(void *msg, pb_pr_ctl_t *ctl)
+static void show_enum(void *msg, void *arg)
{
+ pb_pr_ctl_t *ctl = arg;
ProtobufCEnumDescriptor *d = ctl->arg;
const char *val_name = NULL;
int val, i;
@@ -129,13 +148,13 @@ static size_t get_field_size(int type)
static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
unsigned long nr_fields, pb_pr_ctl_t *ctl)
{
- pb_pr_field_t *show;
+ pb_pr_field_t show;
unsigned long counter;
size_t fsize = get_field_size(fd->type);
- print_tabs(ctl);
+ pb_pr_field_t pretty = NULL;
- pr_msg("%s: ", fd->name);
+ BUG_ON(fsize == 0);
switch (fd->type) {
case PROTOBUF_C_TYPE_INT32:
@@ -174,6 +193,15 @@ static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
break;
}
+ if (ctl->pretty_array) {
+ pretty = ctl->pretty_array[ctl->field_nr];
+ if (pretty && !IS_PRETTY_ARRAY(pretty))
+ show = pretty;
+ } else {
+ print_tabs(ctl);
+ pr_msg("%s: ", fd->name);
+ }
+
show(where, ctl);
where += fsize;
@@ -182,10 +210,12 @@ static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
show(where, ctl);
}
- if (ctl->single_entry)
- pr_msg("\n");
- else
- pr_msg(" ");
+ if (!pretty) {
+ if (ctl->single_entry)
+ pr_msg("\n");
+ else
+ pr_msg(" ");
+ }
}
static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
@@ -208,13 +238,12 @@ static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl)
{
- int i;
const ProtobufCMessageDescriptor *md = ctl->arg;
BUG_ON(md == NULL);
- for (i = 0; i < md->n_fields; i++) {
- const ProtobufCFieldDescriptor fd = md->fields[i];
+ for (ctl->field_nr = 0; ctl->field_nr < md->n_fields; ctl->field_nr++) {
+ const ProtobufCFieldDescriptor fd = md->fields[ctl->field_nr];
unsigned long *data;
size_t nr_fields;
@@ -240,9 +269,12 @@ static inline void pb_no_payload(int fd, void *obj, int flags) { }
void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *md,
pb_unpack_t unpack, pb_free_t free, int single_entry,
void (*payload_hadler)(int fd, void *obj, int flags),
- int flags)
+ int flags, pb_pr_field_t *pretty_array)
{
- pb_pr_ctl_t ctl = {NULL, single_entry, 0};
+ pb_pr_ctl_t ctl = {
+ .single_entry = single_entry,
+ .pretty_array = pretty_array,
+ };
void (*handle_payload)(int fd, void *obj, int flags);
handle_payload = (payload_hadler) ? : pb_no_payload;
More information about the CRIU
mailing list