summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@src.gnome.org>2005-03-07 03:58:04 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2005-03-07 03:58:04 +0000
commitd07d2452286997728f72fa4e8886b009d9e6eaa6 (patch)
tree649d49a6957d84f7e6079579e0a995211b6b8e90
parentbff84b87c070c093af481fb974b561bf01cea2a1 (diff)
CSun Mar 6 22:56:21 2005 Soeren Sandmann <sandmann@redhat.com>
* sfile.c: Generate id's for objects and pointers.
-rw-r--r--ChangeLog4
-rw-r--r--sfile.c220
-rw-r--r--sfile.h18
-rw-r--r--sysprof.c5
4 files changed, 209 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index e9da881..e3a5e9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Sun Mar 6 22:56:21 2005 Soeren Sandmann <sandmann@redhat.com>
+
+ * sfile.c: Generate id's for objects and pointers.
+
Sat Mar 5 01:09:33 2005 Soeren Sandmann <sandmann@redhat.com>
* sfile.c: Bug fixes. Add actual generation.
diff --git a/sfile.c b/sfile.c
index f559ac3..760eeb9 100644
--- a/sfile.c
+++ b/sfile.c
@@ -473,7 +473,7 @@ struct Instruction
{
struct
{
- int n_instructions;
+ int n_elements;
int id;
Instruction *end_instruction;
} begin;
@@ -488,8 +488,8 @@ struct Instruction
{
int target_id;
Instruction *target_instruction;
+ gpointer target_object;
gpointer *location;
- gpointer object;
} pointer;
struct
@@ -573,7 +573,7 @@ sfile_begin_get_list (SFileInput *file,
g_return_val_if_fail (strcmp (instruction->name, name) == 0, 0);
g_return_val_if_fail (is_list_type (instruction->type), 0);
- return instruction->u.begin.n_instructions;
+ return instruction->u.begin.n_elements;
}
void
@@ -712,6 +712,7 @@ handle_begin_element (GMarkupParseContext *parse_context,
build->state = state_transition_begin (build->state, element_name, &instruction.type, err);
instruction.name = g_strdup (element_name);
+ instruction.kind = BEGIN;
g_array_append_val (build->instructions, instruction);
}
@@ -728,6 +729,7 @@ handle_end_element (GMarkupParseContext *context,
build->state = state_transition_end (build->state, element_name, &instruction.type, err);
instruction.name = g_strdup (element_name);
+ instruction.kind = END;
g_array_append_val (build->instructions, instruction);
}
@@ -762,7 +764,8 @@ handle_text (GMarkupParseContext *context,
build->state = state_transition_text (build->state, &instruction.type, err);
instruction.name = NULL;
-
+ instruction.kind = VALUE;
+
switch (instruction.type)
{
case TYPE_POINTER:
@@ -824,13 +827,13 @@ static Instruction *
post_process_instructions_recurse (Instruction *first, GHashTable *instructions_by_id, GError **err)
{
Instruction *instruction;
- int n_instructions;
+ int n_elements;
g_assert (first->kind == BEGIN);
instruction = first + 1;
- n_instructions = 0;
+ n_elements = 0;
while (instruction->kind != END)
{
if (instruction->kind == BEGIN)
@@ -841,28 +844,52 @@ post_process_instructions_recurse (Instruction *first, GHashTable *instructions_
}
else
{
- if (instruction->type == TYPE_POINTER)
- {
- int target_id = instruction->u.pointer.target_id;
- Instruction *target = g_hash_table_lookup (instructions_by_id, GINT_TO_POINTER (target_id));
+ instruction++;
+ }
+
+ n_elements++;
+ }
- if (!target)
- {
- set_invalid_content_error (err, "Id %d doesn't reference any record or list\n",
- instruction->u.pointer.target_id);
- return NULL;
- }
+ first->u.begin.n_elements = n_elements;
+ first->u.begin.end_instruction = instruction;
- instruction->u.pointer.target_instruction = target;
- }
-
+ instruction->u.end.begin_instruction = first;
+
+ return instruction + 1;
+}
+
+/* This functions makes end instructions point to the corresponding
+ * begin instructions, and counts the number of instructions
+ * contained in a begin/end pair
+ */
+static Instruction *
+process_instruction_pairs (Instruction *first)
+{
+ Instruction *instruction;
+ int n_elements;
+
+ g_assert (first->kind == BEGIN);
+
+ instruction = first + 1;
+
+ n_elements = 0;
+ while (instruction->kind != END)
+ {
+ if (instruction->kind == BEGIN)
+ {
+ instruction = process_instruction_pairs (instruction);
+ if (!instruction)
+ return NULL;
+ }
+ else
+ {
instruction++;
}
- n_instructions++;
+ n_elements++;
}
- first->u.begin.n_instructions = n_instructions;
+ first->u.begin.n_elements = n_elements;
first->u.begin.end_instruction = instruction;
instruction->u.end.begin_instruction = first;
@@ -877,6 +904,9 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
GHashTable *instructions_by_id;
int i;
+ /* count list instructions, check pointers */
+ process_instruction_pairs (instructions);
+
/* Build id->instruction map */
instructions_by_id = g_hash_table_new (g_direct_hash, g_direct_equal);
for (i = 0; i < n_instructions; ++i)
@@ -892,9 +922,27 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
}
}
- /* count list instructions, check pointers */
- if (!post_process_instructions_recurse (instructions, instructions_by_id, err))
- retval = FALSE;
+ /* Make pointer instructions point to the corresponding element */
+ for (i = 0; i < n_instructions; ++i)
+ {
+ Instruction *instruction = &(instructions[i]);
+
+ if (instruction->type == TYPE_POINTER)
+ {
+ int target_id = instruction->u.pointer.target_id;
+
+ Instruction *target = g_hash_table_lookup (instructions_by_id,
+ GINT_TO_POINTER (target_id));
+
+ if (!target)
+ {
+ set_invalid_content_error (err, "Id %d doesn't reference any record or list\n",
+ instruction->u.pointer.target_id);
+ retval = FALSE;
+ break;
+ }
+ }
+ }
g_hash_table_destroy (instructions_by_id);
@@ -934,7 +982,8 @@ build_instructions (const char *contents, SFormat *format, int *n_instructions,
return NULL;
}
- if (!post_process_read_instructions ((Instruction *)build.instructions->data, build.instructions->len, err))
+ if (!post_process_read_instructions ((Instruction *)build.instructions->data,
+ build.instructions->len, err))
{
free_instructions ((Instruction *)build.instructions->data, build.instructions->len);
return NULL;
@@ -977,10 +1026,10 @@ struct SFileOutput
{
SFormat *format;
GArray *instructions;
+ GHashTable *objects;
const State *state;
};
-
SFileOutput *
sfile_output_new (SFormat *format)
{
@@ -989,6 +1038,7 @@ sfile_output_new (SFormat *format)
output->format = format;
output->instructions = g_array_new (TRUE, TRUE, sizeof (Instruction));
output->state = sformat_get_start_state (format);
+ output->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
return output;
}
@@ -1036,16 +1086,29 @@ sfile_end_add (SFileOutput *file,
{
Instruction instruction;
+ if (object && g_hash_table_lookup (file->objects, object))
+ {
+ g_warning ("Adding the same object (%p) twice", object);
+ return;
+ }
+
file->state = state_transition_end (
file->state, name, &instruction.type, NULL);
- g_return_if_fail (file->state);
+ if (!file->state)
+ {
+ g_warning ("invalid call of sfile_end_add()");
+ return;
+ }
instruction.kind = END;
instruction.name = g_strdup (name);
instruction.u.end.object = object;
g_array_append_val (file->instructions, instruction);
+
+ if (object)
+ g_hash_table_insert (file->objects, object, object);
}
static void
@@ -1113,12 +1176,81 @@ sfile_add_pointer (SFileOutput *file,
instruction.kind = VALUE;
instruction.type = TYPE_POINTER;
instruction.name = g_strdup (name);
- instruction.u.pointer.object = pointer;
+ instruction.u.pointer.target_object = pointer;
g_array_append_val (file->instructions, instruction);
}
static void
+post_process_write_instructions (SFileOutput *sfile)
+{
+ int i;
+ Instruction *instructions = (Instruction *)sfile->instructions->data;
+ int n_instructions = sfile->instructions->len;
+ int id;
+ GHashTable *instructions_by_object;
+
+ process_instruction_pairs (instructions);
+
+ /* Set all id's to -1 and create map from objects to instructions */
+
+ instructions_by_object = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (i = 0; i < n_instructions; ++i)
+ {
+ Instruction *instruction = &(instructions[i]);
+
+ if (instruction->kind == BEGIN)
+ {
+ instruction->u.begin.id = -1;
+ }
+ else if (instruction->kind == END && instruction->u.end.object)
+ {
+ g_hash_table_insert (instructions_by_object,
+ instruction->u.end.object, instruction);
+ }
+ }
+
+ /* Assign an id to all pointed-to instructions */
+ id = 1;
+ for (i = 0; i < n_instructions; ++i)
+ {
+ Instruction *instruction = &(instructions[i]);
+
+ if (instruction->type == TYPE_POINTER)
+ {
+ if (instruction->u.pointer.target_object)
+ {
+ Instruction *target;
+
+ target =
+ g_hash_table_lookup (instructions_by_object,
+ instruction->u.pointer.target_object);
+
+ if (!target)
+ {
+ g_warning ("pointer has unknown target\n");
+ return;
+ }
+
+ g_assert (target->kind == END);
+
+ if (target->u.end.begin_instruction->u.begin.id == -1)
+ target->u.end.begin_instruction->u.begin.id = id++;
+
+ instruction->u.pointer.target_id =
+ target->u.end.begin_instruction->u.begin.id;
+ }
+ else
+ {
+ instruction->u.pointer.target_id = 0;
+ }
+ }
+ }
+
+}
+
+static void
add_indent (GString *output, int indent)
{
int i;
@@ -1140,10 +1272,14 @@ add_string (GString *output, const char *str)
}
static void
-add_begin_tag (GString *output, int indent, const char *name)
+add_begin_tag (GString *output, int indent, const char *name, int id)
{
add_indent (output, indent);
- g_string_append_printf (output, "<%s>", name);
+
+ if (id != -1)
+ g_string_append_printf (output, "<%s id=\"%d\">", name, id);
+ else
+ g_string_append_printf (output, "<%s>", name);
}
static void
@@ -1168,11 +1304,14 @@ sfile_output_save (SFileOutput *sfile,
Instruction *instructions;
GString *output;
int indent;
+ gboolean retval;
g_return_val_if_fail (sfile != NULL, FALSE);
instructions = (Instruction *)sfile->instructions->data;
+ post_process_write_instructions (sfile);
+
indent = 0;
output = g_string_new ("");
for (i = 0; i < sfile->instructions->len; ++i)
@@ -1182,7 +1321,8 @@ sfile_output_save (SFileOutput *sfile,
switch (instruction->kind)
{
case BEGIN:
- add_begin_tag (output, indent, instruction->name);
+ add_begin_tag (output, indent, instruction->name,
+ instruction->u.begin.id);
add_nl (output);
indent += 4;
break;
@@ -1194,7 +1334,7 @@ sfile_output_save (SFileOutput *sfile,
break;
case VALUE:
- add_begin_tag (output, indent, instruction->name);
+ add_begin_tag (output, indent, instruction->name, -1);
switch (instruction->type)
{
case TYPE_INTEGER:
@@ -1215,12 +1355,20 @@ sfile_output_save (SFileOutput *sfile,
}
}
- /* FIXME: write to disk */
+ /* FIXME: don't dump this to stdout */
g_print (output->str);
-
- g_string_free (output, TRUE);
- return TRUE; /* FIXME */
+#if 0
+ /* FIXME, cut-and-paste the g_file_write() implementation
+ * as long as it isn't in glib
+ */
+ retval = g_file_write (filename, output->str, - 1, err);
+#endif
+ retval = TRUE;
+
+ g_string_free (output, TRUE);
+
+ return retval;
}
diff --git a/sfile.h b/sfile.h
index 88a3ca0..6a6e936 100644
--- a/sfile.h
+++ b/sfile.h
@@ -3,6 +3,24 @@ typedef struct SFileInput SFileInput;
typedef struct SFileOutput SFileOutput;
typedef guint SType;
+
+/* A possibly better API/naming scheme
+ *
+ * Serializer *serializer_new (SerializerFormat *format);
+ *
+ * SerializerReadContext *serializer_begin_read (serializer *serialize,
+ * const char *filename,
+ * GError *err);
+ * serializer_get_blah (SerializerReadContext *);
+ * void serialzier_end_read (...);
+ *
+ * SerializerWritecontext *...;
+ * serializer_begin_write (context);
+ * serializer_write_int ();
+ * serializer_end_write (..., GError **err);
+ *
+ */
+
/* - Describing Types - */
SFormat *sformat_new (gpointer f);
gpointer sformat_new_record (const char *name,
diff --git a/sysprof.c b/sysprof.c
index b45a4e0..d387cad 100644
--- a/sysprof.c
+++ b/sysprof.c
@@ -465,13 +465,14 @@ on_reset_clicked (gpointer widget, gpointer data)
static void
on_save_as_clicked (gpointer widget, gpointer data)
{
+ GError *err = NULL;
Application *app = data;
ensure_profile (app);
/* FIXME */
- if (!profile_save (app->profile, "name.profile", NULL))
- sorry (NULL, "Couldn't save\n");
+ if (!profile_save (app->profile, "name.profile", &err))
+ sorry (NULL, "Couldn't save: %s\n", err->message);
#if 0
sorry (NULL, "Saving profiles is not yet implemented.");