1 /*
2 * Copyright (C) 2010 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License
6 * version 3.0 as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License version 3.0 for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library. If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 * Authored by:
18 * Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
19 */
20
21 /**
22 * SECTION:dee-serializable-model
23 * @short_description: Abstract base class for easing implementations of
24 * #DeeModel<!-- -->s providing a unique version number
25 * for each row
26 * @include: dee.h
27 *
28 * #DeeSerializableModel is an abstract base class to ease implementation of
29 * #DeeModel<!-- -->s providing rows versioned by a
30 * <emphasis>sequence number</emphasis>.
31 *
32 */
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <memory.h>
38 #include <time.h>
39 #include <unistd.h>
40
41 #include "dee-model.h"
42 #include "dee-serializable-model.h"
43 #include "dee-serializable.h"
44 #include "dee-marshal.h"
45 #include "trace-log.h"
46
47 static void dee_serializable_model_model_iface_init (DeeModelIface *iface);
48 static void dee_serializable_model_serializable_iface_init (DeeSerializableIface *iface);
49 static GObject* dee_serializable_model_parse_serialized (GVariant *data);
50
51 #define MODEL_VARIANT_TYPE_1_0 G_VARIANT_TYPE ("(asaav(tt))")
52 #define MODEL_VARIANT_TYPE G_VARIANT_TYPE ("(asaav(tt)a{sv})")
53
54 /**
55 * DeeSerializableModelPrivate:
56 *
57 * Ignore this structure.
58 */
59 struct _DeeSerializableModelPrivate
60 {
61 /* Seqnum tracking */
62 guint64 seqnum;
63
64 /* Column type info */
65 guint n_columns;
66 gchar **column_schemas; // NULL terminated
67 gchar **column_names; // NULL terminated
68 guint32 *column_name_hashes;
69 GHashTable *field_schemas;
70 gboolean inside_changeset;
71 };
72
73 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (DeeSerializableModel,
74 dee_serializable_model,
75 G_TYPE_OBJECT,
76 G_ADD_PRIVATE(DeeSerializableModel)
77 G_IMPLEMENT_INTERFACE (DEE_TYPE_MODEL,
78 dee_serializable_model_model_iface_init)
79 G_IMPLEMENT_INTERFACE (DEE_TYPE_SERIALIZABLE,
80 dee_serializable_model_serializable_iface_init));
81
82 typedef struct _FieldSchemaInfo FieldSchemaInfo;
83
84 struct _FieldSchemaInfo
85 {
86 gint ref_count; // thread unsafe refcount
87 gchar *schema;
88 guint column;
89 };
90
91 /*
92 * Public overridable DeeSerializableModel methods
93 */
94 static guint64 dee_serializable_model_get_seqnum_real (DeeModel *self);
95
96 static void dee_serializable_model_set_seqnum_real (DeeModel *self,
97 guint64 seqnum);
98
99 static guint64 dee_serializable_model_inc_seqnum_real (DeeModel *self);
100
101 /*
102 * DeeModel forward declarations
103 */
104 static const gchar* const* dee_serializable_model_get_schema (DeeModel *self,
105 guint *num_columns);
106
107 static const gchar* dee_serializable_model_get_column_schema (DeeModel *self,
108 guint column);
109
110 static const gchar* dee_serializable_model_get_field_schema (DeeModel *self,
111 const gchar *field_name,
112 guint *out_column);
113
114 static gint dee_serializable_model_get_column_index (DeeModel *self,
115 const gchar *column_name);
116
117 static void dee_serializable_model_set_schema_full (DeeModel *self,
118 const gchar* const *column_schemas,
119 guint num_columns);
120
121 static void dee_serializable_model_set_column_names_full (DeeModel *self,
122 const gchar **column_names,
123 guint num_columns);
124
125 static const gchar** dee_serializable_model_get_column_names (DeeModel *self,
126 guint *num_columns);
127
128 static void dee_serializable_model_register_vardict_schema (DeeModel *self,
129 guint column,
130 GHashTable *schema);
131
132 static GHashTable* dee_serializable_model_get_vardict_schema (DeeModel *self,
133 guint column);
134
135 static guint dee_serializable_model_get_n_columns (DeeModel *self);
136
137 static guint dee_serializable_model_get_n_rows (DeeModel *self);
138
139 static void dee_serializable_model_clear (DeeModel *self);
140
141 static DeeModelIter* dee_serializable_model_append_row (DeeModel *self,
142 GVariant **row_members);
143
144 static DeeModelIter* dee_serializable_model_prepend_row (DeeModel *self,
145 GVariant **row_members);
146
147 static DeeModelIter* dee_serializable_model_insert_row (DeeModel *self,
148 guint pos,
149 GVariant **row_members);
150
151 static DeeModelIter* dee_serializable_model_insert_row_before (DeeModel *self,
152 DeeModelIter *iter,
153 GVariant **row_members);
154
155 static DeeModelIter* dee_serializable_model_insert_row_sorted (DeeModel *self,
156 GVariant **row_members,
157 DeeCompareRowFunc cmp_func,
158 gpointer user_data);
159
160 static DeeModelIter* dee_serializable_model_find_row_sorted (DeeModel *self,
161 GVariant **row_spec,
162 DeeCompareRowFunc cmp_func,
163 gpointer user_data,
164 gboolean *out_was_found);
165
166 static void dee_serializable_model_remove (DeeModel *self,
167 DeeModelIter *iter);
168
169 static void dee_serializable_model_set_value (DeeModel *self,
170 DeeModelIter *iter,
171 guint column,
172 GVariant *value);
173
174 static void dee_serializable_model_set_row (DeeModel *self,
175 DeeModelIter *iter,
176 GVariant **row_members);
177
178 static GVariant* dee_serializable_model_get_value (DeeModel *self,
179 DeeModelIter *iter,
180 guint column);
181
182 static GVariant* dee_serializable_model_get_value_by_name (DeeModel *self,
183 DeeModelIter *iter,
184 const gchar *column_name);
185
186 static GVariant** dee_serializable_model_get_row (DeeModel *self,
187 DeeModelIter *iter,
188 GVariant **out_row_members);
189
190 static DeeModelIter* dee_serializable_model_get_first_iter (DeeModel *self);
191
192 static DeeModelIter* dee_serializable_model_get_last_iter (DeeModel *self);
193
194 static DeeModelIter* dee_serializable_model_get_iter_at_row (DeeModel *self,
195 guint row);
196
197 static gboolean dee_serializable_model_get_bool (DeeModel *self,
198 DeeModelIter *iter,
199 guint column);
200
201 static guchar dee_serializable_model_get_uchar (DeeModel *self,
202 DeeModelIter *iter,
203 guint column);
204
205 static gint32 dee_serializable_model_get_int32 (DeeModel *self,
206 DeeModelIter *iter,
207 guint column);
208
209 static guint32 dee_serializable_model_get_uint32 (DeeModel *self,
210 DeeModelIter *iter,
211 guint column);
212
213 static gint64 dee_serializable_model_get_int64 (DeeModel *self,
214 DeeModelIter *iter,
215 guint column);
216
217 static guint64 dee_serializable_model_get_uint64 (DeeModel *self,
218 DeeModelIter *iter,
219 guint column);
220
221 static gdouble dee_serializable_model_get_double (DeeModel *self,
222 DeeModelIter *iter,
223 guint column);
224
225 static const gchar* dee_serializable_model_get_string (DeeModel *self,
226 DeeModelIter *iter,
227 guint column);
228
229 static DeeModelIter* dee_serializable_model_next (DeeModel *self,
230 DeeModelIter *iter);
231
232 static DeeModelIter* dee_serializable_model_prev (DeeModel *self,
233 DeeModelIter *iter);
234
235 static gboolean dee_serializable_model_is_first (DeeModel *self,
236 DeeModelIter *iter);
237
238 static gboolean dee_serializable_model_is_last (DeeModel *self,
239 DeeModelIter *iter);
240
241 static void dee_serializable_model_begin_changeset (DeeModel *self);
242
243 static void dee_serializable_model_end_changeset (DeeModel *self);
244
245 static guint sigid_changeset_started = 0;
246 static guint sigid_changeset_finished = 0;
247
248 /* FieldSchemaInfo methods */
249 static FieldSchemaInfo*
field_schema_info_new(const gchar * schema,guint column)250 field_schema_info_new (const gchar *schema, guint column)
251 {
252 FieldSchemaInfo *info;
253
254 info = g_slice_new (FieldSchemaInfo);
255 info->ref_count = 1;
256 info->schema = g_strdup (schema);
257 info->column = column;
258
259 return info;
260 }
261
262 static FieldSchemaInfo*
field_schema_info_ref(FieldSchemaInfo * info)263 field_schema_info_ref (FieldSchemaInfo *info)
264 {
265 g_return_val_if_fail (info, NULL);
266
267 info->ref_count++;
268
269 return info;
270 }
271
272 static void
field_schema_info_unref(FieldSchemaInfo * info)273 field_schema_info_unref (FieldSchemaInfo *info)
274 {
275 g_return_if_fail (info);
276 g_return_if_fail (info->ref_count > 0);
277
278 if (--info->ref_count <= 0)
279 {
280 g_free (info->schema);
281 g_slice_free (FieldSchemaInfo, info);
282 }
283 }
284
285 /* GObject Init */
286 static void
dee_serializable_model_finalize(GObject * object)287 dee_serializable_model_finalize (GObject *object)
288 {
289 DeeSerializableModelPrivate *priv = DEE_SERIALIZABLE_MODEL (object)->priv;
290
291 priv->n_columns = 0;
292 priv->seqnum = 0;
293
294 if (priv->column_schemas != NULL)
295 {
296 g_strfreev (priv->column_schemas);
297 priv->column_schemas = NULL;
298 }
299
300 if (priv->column_names != NULL)
301 {
302 g_strfreev (priv->column_names);
303 priv->column_names = NULL;
304 }
305
306 if (priv->column_name_hashes != NULL)
307 {
308 g_free (priv->column_name_hashes);
309 priv->column_name_hashes = NULL;
310 }
311
312 if (priv->field_schemas != NULL)
313 {
314 g_hash_table_unref (priv->field_schemas);
315 priv->field_schemas = NULL;
316 }
317
318 G_OBJECT_CLASS (dee_serializable_model_parent_class)->finalize (object);
319 }
320
321 static void
dee_serializable_model_set_property(GObject * object,guint id,const GValue * value,GParamSpec * pspec)322 dee_serializable_model_set_property (GObject *object,
323 guint id,
324 const GValue *value,
325 GParamSpec *pspec)
326 {
327 switch (id)
328 {
329 default:
330 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
331 break;
332 }
333 }
334
335 static void
dee_serializable_model_get_property(GObject * object,guint id,GValue * value,GParamSpec * pspec)336 dee_serializable_model_get_property (GObject *object,
337 guint id,
338 GValue *value,
339 GParamSpec *pspec)
340 {
341 switch (id)
342 {
343 default:
344 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
345 break;
346 }
347 }
348
349 static void
dee_serializable_model_class_init(DeeSerializableModelClass * klass)350 dee_serializable_model_class_init (DeeSerializableModelClass *klass)
351 {
352 GObjectClass *obj_class = G_OBJECT_CLASS (klass);
353
354 obj_class->finalize = dee_serializable_model_finalize;
355 obj_class->set_property = dee_serializable_model_set_property;
356 obj_class->get_property = dee_serializable_model_get_property;
357
358 klass->get_seqnum = dee_serializable_model_get_seqnum_real;
359 klass->set_seqnum = dee_serializable_model_set_seqnum_real;
360 klass->inc_seqnum = dee_serializable_model_inc_seqnum_real;
361
362 sigid_changeset_started = g_signal_lookup ("changeset-started", DEE_TYPE_MODEL);
363 sigid_changeset_finished = g_signal_lookup ("changeset-finished", DEE_TYPE_MODEL);
364 }
365
366 static void
dee_serializable_model_init(DeeSerializableModel * model)367 dee_serializable_model_init (DeeSerializableModel *model)
368 {
369 DeeSerializableModelPrivate *priv;
370
371 priv = model->priv = dee_serializable_model_get_instance_private (model);
372
373 priv->seqnum = 0;
374
375 priv->n_columns = 0;
376 priv->column_schemas = NULL;
377
378
379 }
380
381 static guint64
dee_serializable_model_get_seqnum_real(DeeModel * self)382 dee_serializable_model_get_seqnum_real (DeeModel *self)
383 {
384 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
385
386 return DEE_SERIALIZABLE_MODEL (self)->priv->seqnum;
387 }
388
389
390 /**
391 * dee_serializable_model_get_seqnum:
392 *
393 * @self: (type DeeSerializableModel): A #DeeSerializableModel instance
394 *
395 * Return value: Sequence number of this #DeeSerializableModel.
396 */
397 guint64
dee_serializable_model_get_seqnum(DeeModel * self)398 dee_serializable_model_get_seqnum (DeeModel *self)
399 {
400 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
401
402 return DEE_SERIALIZABLE_MODEL_GET_CLASS (self)->get_seqnum (self);
403 }
404
405 static void
dee_serializable_model_set_seqnum_real(DeeModel * self,guint64 seqnum)406 dee_serializable_model_set_seqnum_real (DeeModel *self,
407 guint64 seqnum)
408 {
409 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
410
411 DEE_SERIALIZABLE_MODEL (self)->priv->seqnum = seqnum;
412 }
413
414 /**
415 * dee_serializable_model_set_seqnum:
416 *
417 * @self: (type DeeSerializableModel): A #DeeSerializableModel instance
418 * @seqnum: Sequence number
419 *
420 * Sets sequence number of this #DeeSerializableModel.
421 */
422 void
dee_serializable_model_set_seqnum(DeeModel * self,guint64 seqnum)423 dee_serializable_model_set_seqnum (DeeModel *self,
424 guint64 seqnum)
425 {
426 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
427
428 DEE_SERIALIZABLE_MODEL_GET_CLASS (self)->set_seqnum (self, seqnum);
429 }
430
431 static guint64
dee_serializable_model_inc_seqnum_real(DeeModel * self)432 dee_serializable_model_inc_seqnum_real (DeeModel *self)
433 {
434 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
435
436 return ++DEE_SERIALIZABLE_MODEL (self)->priv->seqnum;
437 }
438
439 /**
440 * dee_serializable_model_inc_seqnum:
441 *
442 * @self: (type DeeSerializableModel): A #DeeSerializableModel instance
443 *
444 * Increments sequence number of this #DeeSerializableModel.
445 */
446 guint64
dee_serializable_model_inc_seqnum(DeeModel * self)447 dee_serializable_model_inc_seqnum (DeeModel *self)
448 {
449 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
450
451 return DEE_SERIALIZABLE_MODEL_GET_CLASS (self)->inc_seqnum (self);
452 }
453
454 /*
455 * DeeModel API
456 */
457
458 static void
dee_serializable_model_set_schema_full(DeeModel * self,const gchar * const * column_schemas,guint num_columns)459 dee_serializable_model_set_schema_full (DeeModel *self,
460 const gchar* const *column_schemas,
461 guint num_columns)
462 {
463 DeeSerializableModelPrivate *priv;
464 gchar **column_schemas_copy;
465 guint i;
466
467 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
468 g_return_if_fail (column_schemas != NULL);
469
470 priv = DEE_SERIALIZABLE_MODEL (self)->priv;
471
472 if (priv->column_schemas != NULL)
473 {
474 g_critical ("The DeeModel %p already has a schema", self);
475 return;
476 }
477
478 /* Allocate space to store the column schemas. We NULL terminate it
479 * in order to play well with g_strfreev() */
480 column_schemas_copy = g_new0 (gchar*, num_columns + 1);
481
482 /* Validate the type strings and copy the schema for our selves */
483 for (i = 0; i < num_columns; i++)
484 {
485 if (!g_variant_type_string_is_valid (column_schemas[i]))
486 {
487 g_critical ("When setting schema for DeeModel %p: '%s' is not a "
488 "valid type string", self, column_schemas[i]);
489 return;
490 }
491 column_schemas_copy[i] = g_strdup (column_schemas[i]);
492 }
493
494 /* Register the validated types as our column types */
495 priv->column_schemas = column_schemas_copy; // steal
496 priv->n_columns = num_columns;
497
498 #ifdef ENABLE_TRACE_LOG
499 gchar* schema = g_strjoinv (", ", priv->column_schemas);
500 trace_object (self, "Set schema: (%s)", schema);
501 g_free (schema);
502 #endif
503 }
504
505 static void
dee_serializable_model_set_column_names_full(DeeModel * self,const gchar ** column_names,guint num_columns)506 dee_serializable_model_set_column_names_full (DeeModel *self,
507 const gchar **column_names,
508 guint num_columns)
509 {
510 DeeSerializableModelPrivate *priv;
511 guint i, j;
512 gboolean any_name_null;
513
514 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
515
516 priv = DEE_SERIALIZABLE_MODEL (self)->priv;
517
518 any_name_null = FALSE;
519 for (i = 0; i < num_columns; i++)
520 any_name_null |= column_names[i] == NULL;
521
522 if (num_columns < priv->n_columns || any_name_null)
523 {
524 g_critical ("All column names have to be set!");
525 return;
526 }
527
528 if (priv->column_names) g_strfreev (priv->column_names);
529 if (priv->column_name_hashes) g_free (priv->column_name_hashes);
530
531 priv->column_names = g_new0 (gchar*, priv->n_columns + 1);
532 priv->column_name_hashes = g_new0 (guint32, priv->n_columns);
533
534 for (i = 0; i < num_columns; i++)
535 {
536 priv->column_names[i] = g_strdup (column_names[i]);
537
538 // hash for fast compares
539 priv->column_name_hashes[i] = column_names[i] != NULL ?
540 g_str_hash (column_names[i]) : 0;
541 }
542
543 // check for uniqueness
544 for (i = 0; i < num_columns; i++)
545 {
546 for (j = i+1; j < num_columns; j++)
547 {
548 if (g_strcmp0 (priv->column_names[i], priv->column_names[j]) == 0)
549 {
550 g_warning ("Column names for columns %u and %u are the same!",
551 i, j);
552 }
553 }
554 }
555 }
556
557 static const gchar**
dee_serializable_model_get_column_names(DeeModel * self,guint * n_columns)558 dee_serializable_model_get_column_names (DeeModel *self,
559 guint *n_columns)
560 {
561 DeeSerializableModelPrivate *priv;
562
563 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
564
565 priv = ((DeeSerializableModel*) self)->priv;
566
567 if (n_columns != NULL)
568 *n_columns = priv->n_columns;
569
570 return (const gchar**) priv->column_names;
571 }
572
573 static void
dee_serializable_model_register_vardict_schema(DeeModel * self,guint column,GHashTable * schema)574 dee_serializable_model_register_vardict_schema (DeeModel *self,
575 guint column,
576 GHashTable *schema)
577 {
578 DeeSerializableModelPrivate *priv;
579 GHashTableIter iter;
580 gpointer key, value;
581
582 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
583 g_return_if_fail (schema);
584
585 priv = ((DeeSerializableModel*) self)->priv;
586 g_return_if_fail (priv->column_schemas);
587 g_return_if_fail (column < priv->n_columns);
588 g_return_if_fail (g_variant_type_is_subtype_of (G_VARIANT_TYPE (priv->column_schemas[column]),
589 G_VARIANT_TYPE_VARDICT));
590
591 if (priv->column_names == NULL || priv->column_names[column] == NULL)
592 {
593 g_critical ("Column name for column %u has to be set before calling "
594 "dee_model_register_vardict_schema", column);
595 return;
596 }
597
598 if (priv->field_schemas == NULL)
599 priv->field_schemas = g_hash_table_new_full (g_str_hash, g_str_equal,
600 g_free,
601 (GDestroyNotify) field_schema_info_unref);
602
603 g_hash_table_iter_init (&iter, schema);
604 while (g_hash_table_iter_next (&iter, &key, &value))
605 {
606 FieldSchemaInfo *info;
607 const gchar *field_schema;
608 gchar *full_name;
609 guint registered_column;
610
611 field_schema = dee_model_get_field_schema (self, key, ®istered_column);
612 if (field_schema && registered_column != column)
613 {
614 g_warning ("Field '%s' is already registered for column %u! Please "
615 "use fully qualified names to refer to it ('%s::%s' and "
616 "'%s::%s')",
617 (gchar*) key, registered_column,
618 priv->column_names[registered_column], (gchar*) key,
619 priv->column_names[column], (gchar*) key);
620 }
621 else if (field_schema && !g_str_equal (field_schema, value))
622 {
623 g_warning ("Field '%s' was already registered with schema '%s'! "
624 "Overwriting with schema '%s'",
625 (gchar*) key, field_schema, (gchar*) value);
626 }
627
628 info = field_schema_info_new (value, column);
629 g_hash_table_insert (priv->field_schemas, g_strdup (key), info);
630 full_name = g_strdup_printf ("%s::%s", priv->column_names[column],
631 (gchar*) key);
632 /* transfering ownership of full_name to hashtable */
633 g_hash_table_insert (priv->field_schemas, full_name,
634 field_schema_info_ref (info));
635 }
636 }
637
638 static GHashTable*
dee_serializable_model_get_vardict_schema(DeeModel * self,guint column)639 dee_serializable_model_get_vardict_schema (DeeModel *self,
640 guint column)
641 {
642 DeeSerializableModelPrivate *priv;
643 GHashTable *result;
644 GHashTableIter iter;
645 gpointer key, value;
646
647 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
648
649 priv = ((DeeSerializableModel*) self)->priv;
650 g_return_val_if_fail (priv->column_schemas, NULL);
651 g_return_val_if_fail (column < priv->n_columns, NULL);
652 g_return_val_if_fail (g_variant_type_is_subtype_of (G_VARIANT_TYPE (priv->column_schemas[column]),
653 G_VARIANT_TYPE_VARDICT), NULL);
654
655 if (priv->field_schemas == NULL) return NULL;
656
657 result = g_hash_table_new (g_str_hash, g_str_equal);
658 g_hash_table_iter_init (&iter, priv->field_schemas);
659 while (g_hash_table_iter_next (&iter, &key, &value))
660 {
661 gchar *field, *field_name;
662 FieldSchemaInfo *info;
663
664 field = (gchar*) key;
665 info = (FieldSchemaInfo*) value;
666 if (info->column != column) continue;
667
668 field_name = strstr (field, "::");
669 field_name = field_name != NULL ? field_name + 2 : field;
670
671 g_hash_table_insert (result, field_name, info->schema);
672 }
673
674 return result;
675 }
676
677 static const gchar* const*
dee_serializable_model_get_schema(DeeModel * self,guint * n_columns)678 dee_serializable_model_get_schema (DeeModel *self,
679 guint *n_columns)
680 {
681 DeeSerializableModelPrivate *priv;
682
683 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
684
685 priv = ((DeeSerializableModel*) self)->priv;
686
687 if (n_columns != NULL)
688 *n_columns = priv->n_columns;
689
690 return (const gchar**) priv->column_schemas;
691 }
692
693 static const gchar*
dee_serializable_model_get_column_schema(DeeModel * self,guint column)694 dee_serializable_model_get_column_schema (DeeModel *self,
695 guint column)
696 {
697 DeeSerializableModelPrivate *priv;
698
699 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
700
701 priv = ((DeeSerializableModel*) self)->priv;
702 g_return_val_if_fail (column < priv->n_columns, NULL);
703
704 return priv->column_schemas[column];
705 }
706
707 static const gchar*
dee_serializable_model_get_field_schema(DeeModel * self,const gchar * field_name,guint * out_column)708 dee_serializable_model_get_field_schema (DeeModel *self,
709 const gchar *field_name,
710 guint *out_column)
711 {
712 DeeSerializableModelPrivate *priv;
713 FieldSchemaInfo *info;
714
715 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
716 g_return_val_if_fail (field_name, NULL);
717
718 priv = ((DeeSerializableModel*) self)->priv;
719
720 if (priv->field_schemas == NULL) return NULL;
721
722 info = g_hash_table_lookup (priv->field_schemas, field_name);
723 if (info == NULL) return NULL;
724
725 if (out_column) *out_column = info->column;
726
727 return info->schema;
728 }
729
730 static gint
dee_serializable_model_get_column_index(DeeModel * self,const gchar * column_name)731 dee_serializable_model_get_column_index (DeeModel *self,
732 const gchar *column_name)
733 {
734 gint i;
735 guint hash;
736 DeeSerializableModelPrivate *priv;
737
738 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), -1);
739
740 priv = ((DeeSerializableModel*) self)->priv;
741
742 if (priv->column_names == NULL || column_name == NULL) return -1;
743
744 hash = g_str_hash (column_name);
745
746 // FIXME: use a hashtable instead?
747 for (i = 0; i < priv->n_columns; i++)
748 {
749 if (priv->column_name_hashes[i] == hash &&
750 g_str_equal (priv->column_names[i], column_name)) return i;
751 }
752
753 return -1;
754 }
755
756 static guint
dee_serializable_model_get_n_columns(DeeModel * self)757 dee_serializable_model_get_n_columns (DeeModel *self)
758 {
759 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
760
761 return ((DeeSerializableModel*) self)->priv->n_columns;
762 }
763
764 static guint
dee_serializable_model_get_n_rows(DeeModel * self)765 dee_serializable_model_get_n_rows (DeeModel *self)
766 {
767 DeeModelIter *iter, *end;
768 guint count;
769
770 count = 0;
771 end = dee_model_get_last_iter (self);
772 iter = dee_model_get_first_iter (self);
773 while (iter != end)
774 {
775 iter = dee_model_next (self, iter);
776 count++;
777 }
778
779 return count;
780 }
781
782 static void
dee_serializable_model_clear(DeeModel * self)783 dee_serializable_model_clear (DeeModel *self)
784 {
785 DeeModelIter *iter, *end;
786
787 g_return_if_fail (DEE_IS_SERIALIZABLE_MODEL (self));
788
789 iter = dee_model_get_first_iter (self);
790 end = dee_model_get_last_iter (self);
791
792 while (iter != end)
793 {
794 dee_model_remove (self, iter);
795 iter = dee_model_get_first_iter (self);
796 }
797 }
798
799 static DeeModelIter*
dee_serializable_model_prepend_row(DeeModel * self,GVariant ** row_members)800 dee_serializable_model_prepend_row (DeeModel *self,
801 GVariant **row_members)
802 {
803 DeeModelIter *iter;
804
805 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
806
807 iter = dee_model_get_first_iter (self);
808 return dee_model_insert_row_before (self, iter, row_members);
809 }
810
811 static DeeModelIter*
dee_serializable_model_append_row(DeeModel * self,GVariant ** row_members)812 dee_serializable_model_append_row (DeeModel *self,
813 GVariant **row_members)
814 {
815 DeeModelIter *iter;
816
817 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
818
819 iter = dee_model_get_last_iter (self);
820 return dee_model_insert_row_before (self, iter, row_members);
821 }
822
823 static DeeModelIter*
dee_serializable_model_insert_row(DeeModel * self,guint pos,GVariant ** row_members)824 dee_serializable_model_insert_row (DeeModel *self,
825 guint pos,
826 GVariant **row_members)
827 {
828 DeeModelIter *iter;
829
830 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
831
832 if (pos > 0)
833 {
834 iter = dee_model_get_iter_at_row (self, pos);
835 return dee_model_insert_row_before (self, iter, row_members);
836 }
837 else if (pos == 0)
838 return dee_model_prepend_row (self, row_members);
839 else
840 return dee_model_append_row (self, row_members);
841 }
842
843 static DeeModelIter*
dee_serializable_model_insert_row_before(DeeModel * self,DeeModelIter * iter,GVariant ** row_members)844 dee_serializable_model_insert_row_before (DeeModel *self,
845 DeeModelIter *iter,
846 GVariant **row_members)
847 {
848 g_critical ("%s not implemented", G_STRFUNC);
849 return NULL;
850 }
851
852 static DeeModelIter*
dee_serializable_model_insert_row_sorted(DeeModel * self,GVariant ** row_members,DeeCompareRowFunc cmp_func,gpointer user_data)853 dee_serializable_model_insert_row_sorted (DeeModel *self,
854 GVariant **row_members,
855 DeeCompareRowFunc cmp_func,
856 gpointer user_data)
857 {
858 DeeModelIter *iter;
859 gboolean was_found;
860
861 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
862 g_return_val_if_fail (row_members != NULL, NULL);
863 g_return_val_if_fail (cmp_func != NULL, NULL);
864
865 iter = dee_model_find_row_sorted (self, row_members, cmp_func,
866 user_data, &was_found);
867 if (was_found)
868 iter = dee_model_next (self, iter);
869
870 return dee_model_insert_row_before (self, iter, row_members);
871 }
872
873 static DeeModelIter*
dee_serializable_model_find_row_sorted(DeeModel * self,GVariant ** row_spec,DeeCompareRowFunc cmp_func,gpointer user_data,gboolean * out_was_found)874 dee_serializable_model_find_row_sorted (DeeModel *self,
875 GVariant **row_spec,
876 DeeCompareRowFunc cmp_func,
877 gpointer user_data,
878 gboolean *out_was_found)
879 {
880 DeeModelIter *iter, *end, *last_matching;
881 GVariant **row_buf;
882 gint cmp_result;
883 guint n_cols, i;
884
885 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
886 g_return_val_if_fail (row_spec != NULL, NULL);
887 g_return_val_if_fail (cmp_func != NULL, NULL);
888
889 last_matching = NULL;
890 if (out_was_found != NULL) *out_was_found = FALSE;
891 n_cols = dee_model_get_n_columns (self);
892
893 /* Stack allocate the buffer for speed, and so we don't have to free */
894 row_buf = g_alloca (n_cols * sizeof (gpointer));
895
896 iter = dee_model_get_first_iter (self);
897 end = dee_model_get_last_iter (self);
898 while (iter != end)
899 {
900 dee_model_get_row (self, iter, row_buf);
901 cmp_result = cmp_func (row_buf, row_spec, user_data);
902 /* we're returning last matching row to make ordering
903 * of insert_row_sorted stable and fast */
904 while (cmp_result == 0)
905 {
906 last_matching = iter;
907 iter = dee_model_next (self, iter);
908 if (iter == end)
909 {
910 iter = last_matching;
911 break;
912 }
913 for (i = 0; i < n_cols; i++) g_variant_unref (row_buf[i]);
914 dee_model_get_row (self, iter, row_buf);
915 cmp_result = cmp_func (row_buf, row_spec, user_data);
916 }
917
918 for (i = 0; i < n_cols; i++) g_variant_unref (row_buf[i]);
919 /* if we're past the matching row, the loop can be quit */
920 if (cmp_result >= 0) break;
921 iter = dee_model_next (self, iter);
922 }
923
924 if (out_was_found != NULL && last_matching != NULL) *out_was_found = TRUE;
925 return last_matching ? last_matching : iter;
926 }
927
928 static void
dee_serializable_model_remove(DeeModel * self,DeeModelIter * iter_)929 dee_serializable_model_remove (DeeModel *self,
930 DeeModelIter *iter_)
931 {
932 g_critical ("%s not implemented", G_STRFUNC);
933 }
934
935 static void
dee_serializable_model_set_value(DeeModel * self,DeeModelIter * iter,guint column,GVariant * value)936 dee_serializable_model_set_value (DeeModel *self,
937 DeeModelIter *iter,
938 guint column,
939 GVariant *value)
940 {
941 g_critical ("%s not implemented", G_STRFUNC);
942 }
943
944 static void
dee_serializable_model_set_row(DeeModel * self,DeeModelIter * iter,GVariant ** row_members)945 dee_serializable_model_set_row (DeeModel *self,
946 DeeModelIter *iter,
947 GVariant **row_members)
948 {
949 g_critical ("%s not implemented", G_STRFUNC);
950 }
951
952 static GVariant*
dee_serializable_model_get_value(DeeModel * self,DeeModelIter * iter,guint column)953 dee_serializable_model_get_value (DeeModel *self,
954 DeeModelIter *iter,
955 guint column)
956 {
957 g_critical ("%s not implemented", G_STRFUNC);
958
959 return NULL;
960 }
961
962 static GVariant*
dee_serializable_model_get_value_by_name(DeeModel * self,DeeModelIter * iter,const gchar * column_name)963 dee_serializable_model_get_value_by_name (DeeModel *self,
964 DeeModelIter *iter,
965 const gchar *column_name)
966 {
967 gint col_index;
968
969 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
970
971 col_index = dee_model_get_column_index (self, column_name);
972
973 if (col_index >= 0)
974 {
975 return dee_model_get_value (self, iter, col_index);
976 }
977 else if (dee_model_get_field_schema (self, column_name, (guint*) &col_index))
978 {
979 GVariant *dict, *result;
980 const gchar *key_name;
981
982 dict = dee_model_get_value (self, iter, col_index);
983 // handle full "column::field" name
984 key_name = strstr(column_name, "::");
985 key_name = key_name != NULL ? key_name + 2 : column_name;
986 result = g_variant_lookup_value (dict, key_name, NULL);
987 g_variant_unref (dict);
988
989 return result;
990 }
991
992 return NULL;
993 }
994
995 static GVariant**
dee_serializable_model_get_row(DeeModel * self,DeeModelIter * iter,GVariant ** out_row_members)996 dee_serializable_model_get_row (DeeModel *self,
997 DeeModelIter *iter,
998 GVariant **out_row_members)
999 {
1000 guint col, n_cols;
1001
1002 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
1003
1004 n_cols = dee_model_get_n_columns (self);
1005
1006 if (out_row_members == NULL)
1007 out_row_members = g_new0 (GVariant*, n_cols + 1);
1008
1009 for (col = 0; col < n_cols; col++)
1010 out_row_members[col] = dee_model_get_value (self, iter, col);
1011
1012 return out_row_members;
1013 }
1014
1015 static gboolean
dee_serializable_model_get_bool(DeeModel * self,DeeModelIter * iter,guint column)1016 dee_serializable_model_get_bool (DeeModel *self,
1017 DeeModelIter *iter,
1018 guint column)
1019 {
1020 GVariant *value;
1021 gboolean b;
1022
1023 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), FALSE);
1024
1025 value = dee_model_get_value (self, iter, column);
1026
1027 if (G_UNLIKELY (value == NULL))
1028 {
1029 g_critical ("Failed to retrieve bool from row %u column %u in %s@%p",
1030 dee_model_get_position (self, iter), column,
1031 G_OBJECT_TYPE_NAME (self), self);
1032 return FALSE;
1033 }
1034
1035 b = g_variant_get_boolean (value);
1036 g_variant_unref (value);
1037
1038 return b;
1039 }
1040
1041 static guchar
dee_serializable_model_get_uchar(DeeModel * self,DeeModelIter * iter,guint column)1042 dee_serializable_model_get_uchar (DeeModel *self,
1043 DeeModelIter *iter,
1044 guint column)
1045 {
1046 GVariant *value;
1047 guchar u;
1048
1049 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), '\0');
1050
1051 value = dee_model_get_value (self, iter, column);
1052
1053 if (G_UNLIKELY (value == NULL))
1054 {
1055 g_critical ("Failed to retrieve uchar from row %u column %u in %s@%p",
1056 dee_model_get_position (self, iter), column,
1057 G_OBJECT_TYPE_NAME (self), self);
1058 return '\0';
1059 }
1060
1061 u = g_variant_get_byte(value);
1062 g_variant_unref (value);
1063
1064 return u;
1065 }
1066
1067 static gint32
dee_serializable_model_get_int32(DeeModel * self,DeeModelIter * iter,guint column)1068 dee_serializable_model_get_int32 (DeeModel *self,
1069 DeeModelIter *iter,
1070 guint column)
1071 {
1072 GVariant *value;
1073 gint32 i;
1074
1075 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
1076
1077 value = dee_model_get_value (self, iter, column);
1078
1079 if (G_UNLIKELY (value == NULL))
1080 {
1081 g_critical ("Failed to retrieve int64 from row %u column %u in %s@%p",
1082 dee_model_get_position (self, iter), column,
1083 G_OBJECT_TYPE_NAME (self), self);
1084 return 0;
1085 }
1086
1087 i = g_variant_get_int32 (value);
1088 g_variant_unref (value);
1089
1090 return i;
1091 }
1092
1093 static guint32
dee_serializable_model_get_uint32(DeeModel * self,DeeModelIter * iter,guint column)1094 dee_serializable_model_get_uint32 (DeeModel *self,
1095 DeeModelIter *iter,
1096 guint column)
1097 {
1098 GVariant *value;
1099 guint32 u;
1100
1101 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
1102
1103 value = dee_model_get_value (self, iter, column);
1104
1105 if (G_UNLIKELY (value == NULL))
1106 {
1107 g_critical ("Failed to retrieve uint32 from row %u column %u in %s@%p",
1108 dee_model_get_position (self, iter), column,
1109 G_OBJECT_TYPE_NAME (self), self);
1110 return 0;
1111 }
1112
1113 u = g_variant_get_uint32 (value);
1114 g_variant_unref (value);
1115
1116 return u;
1117 }
1118
1119
1120 static gint64
dee_serializable_model_get_int64(DeeModel * self,DeeModelIter * iter,guint column)1121 dee_serializable_model_get_int64 (DeeModel *self,
1122 DeeModelIter *iter,
1123 guint column)
1124 {
1125 GVariant *value;
1126 gint64 i;
1127
1128 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self),
1129 G_GINT64_CONSTANT (0));
1130
1131 value = dee_model_get_value (self, iter, column);
1132
1133 if (G_UNLIKELY (value == NULL))
1134 {
1135 g_critical ("Failed to retrieve int64 from row %u column %u in %s@%p",
1136 dee_model_get_position (self, iter), column,
1137 G_OBJECT_TYPE_NAME (self), self);
1138 return G_GINT64_CONSTANT (0);
1139 }
1140
1141 i = g_variant_get_int64 (value);
1142 g_variant_unref (value);
1143
1144 return i;
1145 }
1146
1147
1148 static guint64
dee_serializable_model_get_uint64(DeeModel * self,DeeModelIter * iter,guint column)1149 dee_serializable_model_get_uint64 (DeeModel *self,
1150 DeeModelIter *iter,
1151 guint column)
1152 {
1153 GVariant *value;
1154 guint64 u;
1155
1156 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self),
1157 G_GUINT64_CONSTANT (0));
1158
1159 value = dee_model_get_value (self, iter, column);
1160
1161 if (G_UNLIKELY (value == NULL))
1162 {
1163 g_critical ("Failed to retrieve uint64 from row %u column %u in %s@%p",
1164 dee_model_get_position (self, iter), column,
1165 G_OBJECT_TYPE_NAME (self), self);
1166 return G_GUINT64_CONSTANT (0);
1167 }
1168
1169 u = g_variant_get_uint64 (value);
1170 g_variant_unref (value);
1171
1172 return u;
1173 }
1174
1175 static gdouble
dee_serializable_model_get_double(DeeModel * self,DeeModelIter * iter,guint column)1176 dee_serializable_model_get_double (DeeModel *self,
1177 DeeModelIter *iter,
1178 guint column)
1179 {
1180 GVariant *value;
1181 gdouble d;
1182
1183 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
1184
1185 value = dee_model_get_value (self, iter, column);
1186
1187 if (G_UNLIKELY (value == NULL))
1188 {
1189 g_critical ("Failed to retrieve double from row %u column %u in %s@%p",
1190 dee_model_get_position (self, iter), column,
1191 G_OBJECT_TYPE_NAME (self), self);
1192 return 0;
1193 }
1194
1195 d = g_variant_get_double (value);
1196 g_variant_unref (value);
1197
1198 return d;
1199 }
1200
1201 static const gchar*
dee_serializable_model_get_string(DeeModel * self,DeeModelIter * iter,guint column)1202 dee_serializable_model_get_string (DeeModel *self,
1203 DeeModelIter *iter,
1204 guint column)
1205 {
1206 GVariant *value;
1207 const gchar *s;
1208
1209 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
1210
1211 value = dee_model_get_value (self, iter, column);
1212
1213 if (G_UNLIKELY (value == NULL))
1214 {
1215 g_critical ("Failed to retrieve string from row %u column %u in %s@%p",
1216 dee_model_get_position (self, iter), column,
1217 G_OBJECT_TYPE_NAME (self), self);
1218 return NULL;
1219 }
1220
1221 s = g_variant_get_string (value, NULL);
1222 g_variant_unref (value);
1223
1224 return s;
1225 }
1226
1227 static DeeModelIter*
dee_serializable_model_get_first_iter(DeeModel * self)1228 dee_serializable_model_get_first_iter (DeeModel *self)
1229 {
1230 g_critical ("%s not implemented", G_STRFUNC);
1231 return NULL;
1232 }
1233
1234 static DeeModelIter*
dee_serializable_model_get_last_iter(DeeModel * self)1235 dee_serializable_model_get_last_iter (DeeModel *self)
1236 {
1237 DeeModelIter *iter;
1238
1239 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
1240
1241 iter = dee_model_get_first_iter (self);
1242 while (!dee_model_is_last (self, iter))
1243 iter = dee_model_next (self, iter);
1244
1245 return iter;
1246 }
1247
1248 static DeeModelIter*
dee_serializable_model_get_iter_at_row(DeeModel * self,guint row)1249 dee_serializable_model_get_iter_at_row (DeeModel *self,
1250 guint row)
1251 {
1252 DeeModelIter *iter;
1253 guint pos;
1254
1255 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), NULL);
1256
1257 pos = 0;
1258 iter = dee_model_get_first_iter (self);
1259 while (!dee_model_is_last (self, iter) && pos < row)
1260 {
1261 iter = dee_model_next (self, iter);
1262 pos++;
1263 }
1264
1265 if (dee_model_is_last (self, iter))
1266 {
1267 g_critical ("Index %u is out of bounds in model of size %u",
1268 row, pos);
1269 }
1270
1271 return iter;
1272 }
1273
1274 static DeeModelIter*
dee_serializable_model_next(DeeModel * self,DeeModelIter * iter)1275 dee_serializable_model_next (DeeModel *self,
1276 DeeModelIter *iter)
1277 {
1278 g_critical ("%s not implemented", G_STRFUNC);
1279 return NULL;
1280 }
1281
1282 static DeeModelIter*
dee_serializable_model_prev(DeeModel * self,DeeModelIter * iter)1283 dee_serializable_model_prev (DeeModel *self,
1284 DeeModelIter *iter)
1285 {
1286 g_critical ("%s not implemented", G_STRFUNC);
1287 return NULL;
1288 }
1289
1290 static gboolean
dee_serializable_model_is_first(DeeModel * self,DeeModelIter * iter)1291 dee_serializable_model_is_first (DeeModel *self,
1292 DeeModelIter *iter)
1293 {
1294 DeeModelIter *first;
1295
1296 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), FALSE);
1297
1298 first = dee_model_get_first_iter (self);
1299 return first == iter;
1300 }
1301
1302 static gboolean
dee_serializable_model_is_last(DeeModel * self,DeeModelIter * iter)1303 dee_serializable_model_is_last (DeeModel *self,
1304 DeeModelIter *iter)
1305 {
1306 DeeModelIter *last;
1307
1308 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), FALSE);
1309
1310 last = dee_model_get_last_iter (self);
1311 return last == iter;
1312 }
1313
1314 static guint
dee_serializable_model_get_position(DeeModel * self,DeeModelIter * iter)1315 dee_serializable_model_get_position (DeeModel *self,
1316 DeeModelIter *iter)
1317 {
1318 DeeModelIter *_iter;
1319 guint pos;
1320
1321 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), 0);
1322
1323 pos = 0;
1324 _iter = dee_model_get_first_iter (self);
1325 while (!dee_model_is_last (self, iter) && iter != _iter)
1326 {
1327 _iter = dee_model_next (self, _iter);
1328 pos++;
1329 }
1330
1331 if (iter == _iter)
1332 return pos;
1333 else
1334 {
1335 g_critical ("Can not find position of unknown iter %p", iter);
1336 return -1;
1337 }
1338 }
1339
1340 static void
dee_serializable_model_begin_changeset(DeeModel * self)1341 dee_serializable_model_begin_changeset (DeeModel *self)
1342 {
1343 DeeSerializableModelPrivate *priv;
1344
1345 priv = DEE_SERIALIZABLE_MODEL (self)->priv;
1346
1347 if (!priv->inside_changeset)
1348 {
1349 priv->inside_changeset = TRUE;
1350 g_signal_emit (self, sigid_changeset_started, 0);
1351 }
1352 else
1353 {
1354 g_warning ("Ignored call to dee_model_begin_changeset, finish "
1355 "the current changeset using dee_model_end_changeset first");
1356 }
1357 }
1358
1359 static void
dee_serializable_model_end_changeset(DeeModel * self)1360 dee_serializable_model_end_changeset (DeeModel *self)
1361 {
1362 DeeSerializableModelPrivate *priv;
1363
1364 priv = DEE_SERIALIZABLE_MODEL (self)->priv;
1365
1366 if (priv->inside_changeset)
1367 {
1368 priv->inside_changeset = FALSE;
1369 g_signal_emit (self, sigid_changeset_finished, 0);
1370 }
1371 else
1372 {
1373 g_warning ("Ignored call to dee_model_end_changeset, "
1374 "dee_model_begin_changeset has to be called first");
1375 }
1376 }
1377
1378 static DeeModelTag*
dee_serializable_model_register_tag(DeeModel * self,GDestroyNotify tag_destroy)1379 dee_serializable_model_register_tag (DeeModel *self,
1380 GDestroyNotify tag_destroy)
1381 {
1382 g_critical ("%s not implemented", G_STRFUNC);
1383 return NULL;
1384 }
1385
1386 static gpointer
dee_serializable_model_get_tag(DeeModel * self,DeeModelIter * iter,DeeModelTag * tag)1387 dee_serializable_model_get_tag (DeeModel *self,
1388 DeeModelIter *iter,
1389 DeeModelTag *tag)
1390 {
1391 g_critical ("%s not implemented", G_STRFUNC);
1392 return NULL;
1393 }
1394
1395 static void
dee_serializable_model_set_tag(DeeModel * self,DeeModelIter * iter,DeeModelTag * tag,gpointer value)1396 dee_serializable_model_set_tag (DeeModel *self,
1397 DeeModelIter *iter,
1398 DeeModelTag *tag,
1399 gpointer value)
1400 {
1401 g_critical ("%s not implemented", G_STRFUNC);
1402 }
1403
1404 /* Build a '(sasaavauay(tt))' suitable for sending in a Clone response */
1405 static GVariant*
dee_serializable_model_serialize(DeeSerializable * self)1406 dee_serializable_model_serialize (DeeSerializable *self)
1407 {
1408 DeeModel *_self;
1409 GVariantBuilder aav, clone, fields, vardict;
1410 GVariant *val, *tt, *schema, *col_names;
1411 DeeModelIter *iter;
1412 guint i, j, n_rows, n_columns;
1413 guint64 last_seqnum;
1414 const gchar* const *column_schemas;
1415 const gchar **column_names;
1416
1417 g_return_val_if_fail (DEE_IS_SERIALIZABLE_MODEL (self), FALSE);
1418
1419 trace_object (self, "Building clone");
1420
1421 _self = DEE_MODEL (self);
1422 n_columns = dee_model_get_n_columns (_self);
1423
1424 g_variant_builder_init (&aav, G_VARIANT_TYPE ("aav"));
1425
1426 /* Clone the rows */
1427 i = 0;
1428 iter = dee_model_get_first_iter (_self);
1429 while (!dee_model_is_last (_self, iter))
1430 {
1431 g_variant_builder_open (&aav, G_VARIANT_TYPE ("av"));
1432 for (j = 0; j < n_columns; j++)
1433 {
1434 val = dee_model_get_value (_self, iter, j);
1435 g_variant_builder_add_value (&aav, g_variant_new_variant (val));
1436 g_variant_unref (val);
1437 }
1438 g_variant_builder_close (&aav);
1439
1440 iter = dee_model_next (_self, iter);
1441 i++;
1442 }
1443
1444 n_rows = i;
1445
1446 /* Collect the schema */
1447 column_schemas = dee_model_get_schema(_self, NULL);
1448 schema = g_variant_new_strv (column_schemas, -1);
1449
1450 /* Collect the column names */
1451 column_names = dee_model_get_column_names (_self, NULL);
1452 col_names = g_variant_new_strv (column_names,
1453 column_names != NULL ? n_columns : 0);
1454
1455 g_variant_builder_init (&fields, G_VARIANT_TYPE ("a(uss)"));
1456 for (i = 0; i < n_columns; i++)
1457 {
1458 GHashTable *field_schemas;
1459 GHashTableIter ht_iter;
1460 gpointer key, value;
1461
1462 if (!g_variant_type_is_subtype_of (G_VARIANT_TYPE (column_schemas[i]),
1463 G_VARIANT_TYPE_VARDICT))
1464 continue;
1465
1466 field_schemas = dee_model_get_vardict_schema (_self, i);
1467 if (field_schemas == NULL) continue;
1468 g_hash_table_iter_init (&ht_iter, field_schemas);
1469 while (g_hash_table_iter_next (&ht_iter, &key, &value))
1470 {
1471 g_variant_builder_add (&fields, "(uss)", i, key, value);
1472 }
1473
1474 g_hash_table_unref (field_schemas);
1475 }
1476
1477 /* Collect the seqnum */
1478 last_seqnum = dee_serializable_model_get_seqnum (_self);
1479 tt = g_variant_new ("(tt)", last_seqnum - n_rows, last_seqnum);
1480
1481 /* Put all extra properties in a vardict */
1482 g_variant_builder_init (&vardict, G_VARIANT_TYPE ("a{sv}"));
1483 g_variant_builder_add (&vardict, "{sv}", "column-names", col_names);
1484 g_variant_builder_add (&vardict, "{sv}", "fields", g_variant_builder_end (&fields));
1485
1486 /* Build the final clone */
1487 g_variant_builder_init (&clone, MODEL_VARIANT_TYPE);
1488 g_variant_builder_add_value (&clone, schema);
1489 g_variant_builder_add_value (&clone, g_variant_builder_end (&aav));
1490 g_variant_builder_add_value (&clone, tt);
1491 g_variant_builder_add_value (&clone, g_variant_builder_end (&vardict));
1492
1493 trace_object (self, "Serialized with %i rows", dee_model_get_n_rows (_self));
1494
1495 return g_variant_builder_end (&clone);
1496 }
1497
1498 static GObject*
dee_serializable_model_parse_serialized(GVariant * data)1499 dee_serializable_model_parse_serialized (GVariant *data)
1500 {
1501 DeeModel *model;
1502 GVariant *seqnumsv, *col, *vardict;
1503 GVariantIter *row_iter, *col_iter, *vardict_schema_iter;
1504 GVariant **row;
1505 const gchar **schemas;
1506 const gchar **column_names;
1507 gsize n_cols, i, j, tuple_items;
1508 guint64 seqnum_start, seqnum_end;
1509 static GType default_model_type = G_TYPE_INVALID;
1510
1511 if (default_model_type == G_TYPE_INVALID)
1512 {
1513 default_model_type = g_type_from_name ("DeeSequenceModel");
1514 if (default_model_type == 0)
1515 {
1516 g_critical ("Unable to look up default DeeModel type, DeeSequenceModel, for deserialization");
1517 return NULL;
1518 }
1519 }
1520
1521 tuple_items = g_variant_n_children (data);
1522 /* We support schema used by both dee 1.0 and 1.2 */
1523 if (tuple_items == 3) /* "(asaav(tt))" */
1524 {
1525 g_variant_get (data, "(^a&saav@(tt))", &schemas, &row_iter, &seqnumsv);
1526 vardict = NULL;
1527 }
1528 else if (tuple_items == 4) /* "(asaav(tt)a{sv})" */
1529 {
1530 g_variant_get (data, "(^a&saav@(tt)@a{sv})", &schemas, &row_iter,
1531 &seqnumsv, &vardict);
1532
1533 if (!g_variant_lookup (vardict, "column-names", "^a&s", &column_names))
1534 column_names = NULL;
1535 if (!g_variant_lookup (vardict, "fields", "a(uss)", &vardict_schema_iter))
1536 vardict_schema_iter = NULL;
1537 }
1538 else
1539 {
1540 g_critical ("Unable to deserialize model: Unrecognized schema");
1541 return NULL;
1542 }
1543
1544 n_cols = g_strv_length ((gchar**) schemas);
1545 g_variant_get (seqnumsv, "(tt)", &seqnum_start, &seqnum_end);
1546
1547 model = DEE_MODEL (g_object_new (default_model_type, NULL));
1548 dee_model_set_schema_full (model, schemas, n_cols);
1549 dee_serializable_model_set_seqnum (model, seqnum_start);
1550
1551 if (vardict)
1552 {
1553 if (column_names && g_strv_length ((gchar**) column_names) == n_cols)
1554 {
1555 dee_model_set_column_names_full (model, column_names, n_cols);
1556 }
1557
1558 if (vardict_schema_iter != NULL)
1559 {
1560 GHashTable **vardict_schemas;
1561 gchar *field_name, *field_schema;
1562 guint column_index;
1563
1564 vardict_schemas = g_alloca (n_cols * sizeof (GHashTable*));
1565 memset (vardict_schemas, 0, n_cols * sizeof (GHashTable*));
1566
1567 while (g_variant_iter_next (vardict_schema_iter, "(uss)",
1568 &column_index, &field_name, &field_schema))
1569 {
1570 if (vardict_schemas[column_index] == NULL)
1571 {
1572 vardict_schemas[column_index] = g_hash_table_new_full (
1573 g_str_hash, g_str_equal, g_free, g_free);
1574 }
1575
1576 // using g_variant_iter_next, so we own field_name & schema
1577 g_hash_table_insert (vardict_schemas[column_index],
1578 field_name, field_schema);
1579 }
1580
1581 for (column_index = 0; column_index < n_cols; column_index++)
1582 {
1583 if (vardict_schemas[column_index] == NULL) continue;
1584 dee_model_register_vardict_schema (model, column_index,
1585 vardict_schemas[column_index]);
1586 g_hash_table_unref (vardict_schemas[column_index]);
1587 }
1588
1589 g_variant_iter_free (vardict_schema_iter);
1590 }
1591
1592 g_free (column_names);
1593 g_variant_unref (vardict);
1594 }
1595
1596 /* Note: The 'row' variable is stack allocated. No need to free it */
1597 row = g_alloca (n_cols * sizeof (GVariant *));
1598
1599 i = 0;
1600 while (g_variant_iter_next (row_iter, "av", &col_iter))
1601 {
1602 if (g_variant_iter_n_children (col_iter) != n_cols)
1603 {
1604 g_warning ("Row %"G_GSIZE_FORMAT" of serialized DeeSerializableModel "
1605 "data has illegal length %"G_GSIZE_FORMAT". Expected %"
1606 G_GSIZE_FORMAT, i, g_variant_iter_n_children (col_iter),
1607 n_cols);
1608 /* Just skip this row - parsers for DeeSerializable should
1609 * generally never return NULL */
1610 continue;
1611 }
1612
1613 j = 0;
1614 while (g_variant_iter_next (col_iter, "v", &col))
1615 {
1616 row[j] = col; // transfering variant reference to row[j]
1617 j++;
1618 }
1619
1620 dee_model_append_row (model, row);
1621
1622 for (j = 0; j < n_cols; j++)
1623 {
1624 g_variant_unref (row[j]);
1625 }
1626
1627 i++;
1628 g_variant_iter_free (col_iter);
1629 }
1630 g_variant_iter_free (row_iter);
1631 g_free (schemas);
1632 g_variant_unref (seqnumsv);
1633
1634 return (GObject *) model;
1635 }
1636
1637 static void
dee_serializable_model_model_iface_init(DeeModelIface * iface)1638 dee_serializable_model_model_iface_init (DeeModelIface *iface)
1639 {
1640 iface->set_schema_full = dee_serializable_model_set_schema_full;
1641 iface->get_schema = dee_serializable_model_get_schema;
1642 iface->get_column_schema = dee_serializable_model_get_column_schema;
1643 iface->get_field_schema = dee_serializable_model_get_field_schema;
1644 iface->get_column_index = dee_serializable_model_get_column_index;
1645 iface->set_column_names_full = dee_serializable_model_set_column_names_full;
1646 iface->get_column_names = dee_serializable_model_get_column_names;
1647 iface->get_n_columns = dee_serializable_model_get_n_columns;
1648 iface->get_n_rows = dee_serializable_model_get_n_rows;
1649 iface->append_row = dee_serializable_model_append_row;
1650 iface->prepend_row = dee_serializable_model_prepend_row;
1651 iface->insert_row = dee_serializable_model_insert_row;
1652 iface->insert_row_before = dee_serializable_model_insert_row_before;
1653 iface->insert_row_sorted = dee_serializable_model_insert_row_sorted;
1654 iface->find_row_sorted = dee_serializable_model_find_row_sorted;
1655 iface->remove = dee_serializable_model_remove;
1656 iface->clear = dee_serializable_model_clear;
1657 iface->set_value = dee_serializable_model_set_value;
1658 iface->set_row = dee_serializable_model_set_row;
1659 iface->get_value = dee_serializable_model_get_value;
1660 iface->get_value_by_name = dee_serializable_model_get_value_by_name;
1661 iface->get_row = dee_serializable_model_get_row;
1662 iface->get_first_iter = dee_serializable_model_get_first_iter;
1663 iface->get_last_iter = dee_serializable_model_get_last_iter;
1664 iface->get_iter_at_row = dee_serializable_model_get_iter_at_row;
1665 iface->get_bool = dee_serializable_model_get_bool;
1666 iface->get_uchar = dee_serializable_model_get_uchar;
1667 iface->get_int32 = dee_serializable_model_get_int32;
1668 iface->get_uint32 = dee_serializable_model_get_uint32;
1669 iface->get_int64 = dee_serializable_model_get_int64;
1670 iface->get_uint64 = dee_serializable_model_get_uint64;
1671 iface->get_double = dee_serializable_model_get_double;
1672 iface->get_string = dee_serializable_model_get_string;
1673 iface->next = dee_serializable_model_next;
1674 iface->prev = dee_serializable_model_prev;
1675 iface->is_first = dee_serializable_model_is_first;
1676 iface->is_last = dee_serializable_model_is_last;
1677 iface->get_position = dee_serializable_model_get_position;
1678 iface->register_tag = dee_serializable_model_register_tag;
1679 iface->get_tag = dee_serializable_model_get_tag;
1680 iface->set_tag = dee_serializable_model_set_tag;
1681 iface->register_vardict_schema =
1682 dee_serializable_model_register_vardict_schema;
1683 iface->get_vardict_schema =
1684 dee_serializable_model_get_vardict_schema;
1685
1686 iface->begin_changeset = dee_serializable_model_begin_changeset;
1687 iface->end_changeset = dee_serializable_model_end_changeset;
1688 }
1689
1690 static void
dee_serializable_model_serializable_iface_init(DeeSerializableIface * iface)1691 dee_serializable_model_serializable_iface_init (DeeSerializableIface *iface)
1692 {
1693 iface->serialize = dee_serializable_model_serialize;
1694
1695 dee_serializable_register_parser (DEE_TYPE_SERIALIZABLE_MODEL,
1696 MODEL_VARIANT_TYPE_1_0,
1697 dee_serializable_model_parse_serialized);
1698 dee_serializable_register_parser (DEE_TYPE_SERIALIZABLE_MODEL,
1699 MODEL_VARIANT_TYPE,
1700 dee_serializable_model_parse_serialized);
1701 }
1702
1703