Merge remote-tracking branch 'origin/master' into sheet
[pspp] / src / ui / gui / value-variant.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2016  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <gtk/gtk.h>
19
20 #include <string.h>
21 #include "value-variant.h"
22 #include "data/value.h"
23
24
25 enum
26   {
27     IDX_WIDTH,
28     IDX_DATA
29   };
30
31 /* Returns a GVariant containing the data contained
32    in IN and WIDTH.  The returned GVariant has a floating
33    reference.
34  */
35 GVariant *
36 value_variant_new (const union value *in, int width)
37 {
38   GVariant *vv[2] = {NULL, NULL};
39   vv[IDX_WIDTH] = g_variant_new_int32 (width);
40
41   if (width == 0)
42     vv[IDX_DATA] = g_variant_new_double (in->f);
43   else if (width <= MAX_SHORT_STRING)
44     {
45       char xx[MAX_SHORT_STRING + 1];
46       memset (xx, '\0', MAX_SHORT_STRING + 1);
47       memcpy (xx, in->short_string, width);
48       vv[IDX_DATA] = g_variant_new_bytestring (xx);
49     }
50   else
51     {
52       gchar *q = xmalloc (width + 1);
53       memcpy (q, in->long_string, width);
54       q[width] = '\0';
55       vv[IDX_DATA] = g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, q,
56                                               width + 1, FALSE, NULL, NULL);
57     }
58
59   return g_variant_new_tuple (vv, 2);
60 }
61
62 /* Destroy the contents of VAL.  Also unref V */
63 void
64 value_destroy_from_variant (union value *val, GVariant *v)
65 {
66   GVariant *vwidth = g_variant_get_child_value (v, IDX_WIDTH);
67   gint32 width = g_variant_get_int32 (vwidth); /* v is unreffed here */
68   g_variant_unref (vwidth);
69   value_destroy (val, width);
70 }
71
72
73 /* Fills VAL with the value data held in V.
74    When VAL is no longer required it must be destroyed using
75    value_destroy_from_variant. */
76 void
77 value_variant_get (union value *val, GVariant *v)
78 {
79   GVariant *vwidth = g_variant_get_child_value (v, IDX_WIDTH);
80   gint32 width = g_variant_get_int32 (vwidth);
81   g_variant_unref (vwidth);
82
83   GVariant *vdata = g_variant_get_child_value (v, IDX_DATA);
84
85   if (0 == width)
86     val->f = g_variant_get_double (vdata);
87   else
88     {
89       const gchar *data = g_variant_get_bytestring (vdata);
90       if (width <= MAX_SHORT_STRING)
91         memcpy (val->short_string, data, MAX_SHORT_STRING);
92       else
93         {
94           val->long_string = xmemdup (data, width);
95         }
96     }
97
98   g_variant_unref (vdata);
99 }