(root)/
glib-2.79.0/
gio/
gsettings-mapping.c
       1  /*
       2   * Copyright © 2010 Novell, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Author: Vincent Untz <vuntz@gnome.org>
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include "gsettings-mapping.h"
      25  
      26  static GVariant *
      27  g_settings_set_mapping_int (const GValue       *value,
      28                              const GVariantType *expected_type)
      29  {
      30    GVariant *variant = NULL;
      31    gint64 l;
      32  
      33    if (G_VALUE_HOLDS_INT (value))
      34      l = g_value_get_int (value);
      35    else if (G_VALUE_HOLDS_INT64 (value))
      36      l = g_value_get_int64 (value);
      37    else
      38      return NULL;
      39  
      40    if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
      41      {
      42        if (G_MININT16 <= l && l <= G_MAXINT16)
      43          variant = g_variant_new_int16 ((gint16) l);
      44      }
      45    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
      46      {
      47        if (0 <= l && l <= G_MAXUINT16)
      48          variant = g_variant_new_uint16 ((guint16) l);
      49      }
      50    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
      51      {
      52        if (G_MININT32 <= l && l <= G_MAXINT32)
      53          variant = g_variant_new_int32 ((gint) l);
      54      }
      55    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
      56      {
      57        if (0 <= l && l <= G_MAXUINT32)
      58          variant = g_variant_new_uint32 ((guint) l);
      59      }
      60    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
      61      {
      62        if (G_MININT64 <= l && l <= G_MAXINT64)
      63          variant = g_variant_new_int64 ((gint64) l);
      64      }
      65    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
      66      {
      67        if (0 <= l && (guint64) l <= G_MAXUINT64)
      68          variant = g_variant_new_uint64 ((guint64) l);
      69      }
      70    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
      71      {
      72        if (0 <= l && l <= G_MAXUINT32)
      73          variant = g_variant_new_handle ((guint) l);
      74      }
      75    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
      76      variant = g_variant_new_double ((gdouble) l);
      77  
      78    return variant;
      79  }
      80  
      81  static GVariant *
      82  g_settings_set_mapping_float (const GValue       *value,
      83                                const GVariantType *expected_type)
      84  {
      85    GVariant *variant = NULL;
      86    gdouble d;
      87    gint64 l;
      88  
      89    if (G_VALUE_HOLDS_DOUBLE (value))
      90      d = g_value_get_double (value);
      91    else
      92      return NULL;
      93  
      94    l = (gint64) d;
      95    if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
      96      {
      97        if (G_MININT16 <= l && l <= G_MAXINT16)
      98          variant = g_variant_new_int16 ((gint16) l);
      99      }
     100    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
     101      {
     102        if (0 <= l && l <= G_MAXUINT16)
     103          variant = g_variant_new_uint16 ((guint16) l);
     104      }
     105    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
     106      {
     107        if (G_MININT32 <= l && l <= G_MAXINT32)
     108          variant = g_variant_new_int32 ((gint) l);
     109      }
     110    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
     111      {
     112        if (0 <= l && l <= G_MAXUINT32)
     113          variant = g_variant_new_uint32 ((guint) l);
     114      }
     115    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
     116      {
     117        if (G_MININT64 <= l && l <= G_MAXINT64)
     118          variant = g_variant_new_int64 ((gint64) l);
     119      }
     120    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
     121      {
     122        if (0 <= l && (guint64) l <= G_MAXUINT64)
     123          variant = g_variant_new_uint64 ((guint64) l);
     124      }
     125    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
     126      {
     127        if (0 <= l && l <= G_MAXUINT32)
     128          variant = g_variant_new_handle ((guint) l);
     129      }
     130    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
     131      variant = g_variant_new_double ((gdouble) d);
     132  
     133    return variant;
     134  }
     135  static GVariant *
     136  g_settings_set_mapping_unsigned_int (const GValue       *value,
     137                                       const GVariantType *expected_type)
     138  {
     139    GVariant *variant = NULL;
     140    guint64 u;
     141  
     142    if (G_VALUE_HOLDS_UINT (value))
     143      u = g_value_get_uint (value);
     144    else if (G_VALUE_HOLDS_UINT64 (value))
     145      u = g_value_get_uint64 (value);
     146    else
     147      return NULL;
     148  
     149    if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT16))
     150      {
     151        if (u <= G_MAXINT16)
     152          variant = g_variant_new_int16 ((gint16) u);
     153      }
     154    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT16))
     155      {
     156        if (u <= G_MAXUINT16)
     157          variant = g_variant_new_uint16 ((guint16) u);
     158      }
     159    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT32))
     160      {
     161        if (u <= G_MAXINT32)
     162          variant = g_variant_new_int32 ((gint) u);
     163      }
     164    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT32))
     165      {
     166        if (u <= G_MAXUINT32)
     167          variant = g_variant_new_uint32 ((guint) u);
     168      }
     169    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_INT64))
     170      {
     171        if (u <= G_MAXINT64)
     172          variant = g_variant_new_int64 ((gint64) u);
     173      }
     174    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_UINT64))
     175      {
     176        if (u <= G_MAXUINT64)
     177          variant = g_variant_new_uint64 ((guint64) u);
     178      }
     179    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_HANDLE))
     180      {
     181        if (u <= G_MAXUINT32)
     182          variant = g_variant_new_handle ((guint) u);
     183      }
     184    else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_DOUBLE))
     185      variant = g_variant_new_double ((gdouble) u);
     186  
     187    return variant;
     188  }
     189  
     190  static gboolean
     191  g_settings_get_mapping_int (GValue   *value,
     192                              GVariant *variant)
     193  {
     194    const GVariantType *type;
     195    gint64 l;
     196  
     197    type = g_variant_get_type (variant);
     198  
     199    if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
     200      l = g_variant_get_int16 (variant);
     201    else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
     202      l = g_variant_get_int32 (variant);
     203    else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
     204      l = g_variant_get_int64 (variant);
     205    else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
     206      l = g_variant_get_handle (variant);
     207    else
     208      return FALSE;
     209  
     210    if (G_VALUE_HOLDS_INT (value))
     211      {
     212        g_value_set_int (value, l);
     213        return (G_MININT32 <= l && l <= G_MAXINT32);
     214      }
     215    else if (G_VALUE_HOLDS_UINT (value))
     216      {
     217        g_value_set_uint (value, l);
     218        return (0 <= l && l <= G_MAXUINT32);
     219      }
     220    else if (G_VALUE_HOLDS_INT64 (value))
     221      {
     222        g_value_set_int64 (value, l);
     223        return (G_MININT64 <= l && l <= G_MAXINT64);
     224      }
     225    else if (G_VALUE_HOLDS_UINT64 (value))
     226      {
     227        g_value_set_uint64 (value, l);
     228        return (0 <= l && (guint64) l <= G_MAXUINT64);
     229      }
     230    else if (G_VALUE_HOLDS_DOUBLE (value))
     231      {
     232        g_value_set_double (value, l);
     233        return TRUE;
     234      }
     235  
     236    return FALSE;
     237  }
     238  
     239  static gboolean
     240  g_settings_get_mapping_float (GValue   *value,
     241                                GVariant *variant)
     242  {
     243    const GVariantType *type;
     244    gdouble d;
     245    gint64 l;
     246  
     247    type = g_variant_get_type (variant);
     248  
     249    if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
     250      d = g_variant_get_double (variant);
     251    else
     252      return FALSE;
     253  
     254    l = (gint64)d;
     255    if (G_VALUE_HOLDS_INT (value))
     256      {
     257        g_value_set_int (value, l);
     258        return (G_MININT32 <= l && l <= G_MAXINT32);
     259      }
     260    else if (G_VALUE_HOLDS_UINT (value))
     261      {
     262        g_value_set_uint (value, l);
     263        return (0 <= l && l <= G_MAXUINT32);
     264      }
     265    else if (G_VALUE_HOLDS_INT64 (value))
     266      {
     267        g_value_set_int64 (value, l);
     268        return (G_MININT64 <= l && l <= G_MAXINT64);
     269      }
     270    else if (G_VALUE_HOLDS_UINT64 (value))
     271      {
     272        g_value_set_uint64 (value, l);
     273        return (0 <= l && (guint64) l <= G_MAXUINT64);
     274      }
     275    else if (G_VALUE_HOLDS_DOUBLE (value))
     276      {
     277        g_value_set_double (value, d);
     278        return TRUE;
     279      }
     280  
     281    return FALSE;
     282  }
     283  static gboolean
     284  g_settings_get_mapping_unsigned_int (GValue   *value,
     285                                       GVariant *variant)
     286  {
     287    const GVariantType *type;
     288    guint64 u;
     289  
     290    type = g_variant_get_type (variant);
     291  
     292    if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
     293      u = g_variant_get_uint16 (variant);
     294    else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
     295      u = g_variant_get_uint32 (variant);
     296    else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
     297      u = g_variant_get_uint64 (variant);
     298    else
     299      return FALSE;
     300  
     301    if (G_VALUE_HOLDS_INT (value))
     302      {
     303        g_value_set_int (value, u);
     304        return (u <= G_MAXINT32);
     305      }
     306    else if (G_VALUE_HOLDS_UINT (value))
     307      {
     308        g_value_set_uint (value, u);
     309        return (u <= G_MAXUINT32);
     310      }
     311    else if (G_VALUE_HOLDS_INT64 (value))
     312      {
     313        g_value_set_int64 (value, u);
     314        return (u <= G_MAXINT64);
     315      }
     316    else if (G_VALUE_HOLDS_UINT64 (value))
     317      {
     318        g_value_set_uint64 (value, u);
     319        return (u <= G_MAXUINT64);
     320      }
     321    else if (G_VALUE_HOLDS_DOUBLE (value))
     322      {
     323        g_value_set_double (value, u);
     324        return TRUE;
     325      }
     326  
     327    return FALSE;
     328  }
     329  
     330  GVariant *
     331  g_settings_set_mapping (const GValue       *value,
     332                          const GVariantType *expected_type,
     333                          gpointer            user_data)
     334  {
     335    gchar *type_string;
     336  
     337    if (G_VALUE_HOLDS_BOOLEAN (value))
     338      {
     339        if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BOOLEAN))
     340          return g_variant_new_boolean (g_value_get_boolean (value));
     341      }
     342  
     343    else if (G_VALUE_HOLDS_CHAR (value)  ||
     344             G_VALUE_HOLDS_UCHAR (value))
     345      {
     346        if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTE))
     347          {
     348            if (G_VALUE_HOLDS_CHAR (value))
     349              return g_variant_new_byte (g_value_get_schar (value));
     350            else
     351              return g_variant_new_byte (g_value_get_uchar (value));
     352          }
     353      }
     354  
     355    else if (G_VALUE_HOLDS_INT (value)   ||
     356             G_VALUE_HOLDS_INT64 (value))
     357      return g_settings_set_mapping_int (value, expected_type);
     358  
     359    else if (G_VALUE_HOLDS_DOUBLE (value))
     360      return g_settings_set_mapping_float (value, expected_type);
     361  
     362    else if (G_VALUE_HOLDS_UINT (value)  ||
     363             G_VALUE_HOLDS_UINT64 (value))
     364      return g_settings_set_mapping_unsigned_int (value, expected_type);
     365  
     366    else if (G_VALUE_HOLDS_STRING (value))
     367      {
     368        if (g_value_get_string (value) == NULL)
     369          return NULL;
     370        else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING))
     371          return g_variant_new_string (g_value_get_string (value));
     372        else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_BYTESTRING))
     373          return g_variant_new_bytestring (g_value_get_string (value));
     374        else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_OBJECT_PATH))
     375          return g_variant_new_object_path (g_value_get_string (value));
     376        else if (g_variant_type_equal (expected_type, G_VARIANT_TYPE_SIGNATURE))
     377          return g_variant_new_signature (g_value_get_string (value));
     378      }
     379  
     380    else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
     381      {
     382        if (g_value_get_boxed (value) == NULL)
     383          return NULL;
     384        return g_variant_new_strv ((const gchar **) g_value_get_boxed (value),
     385                                   -1);
     386      }
     387  
     388    else if (G_VALUE_HOLDS_ENUM (value))
     389      {
     390        GEnumValue *enumval;
     391        GEnumClass *eclass;
     392  
     393        /* GParamSpecEnum holds a ref on the class so we just peek... */
     394        eclass = g_type_class_peek (G_VALUE_TYPE (value));
     395        enumval = g_enum_get_value (eclass, g_value_get_enum (value));
     396  
     397        if (enumval)
     398          return g_variant_new_string (enumval->value_nick);
     399        else
     400          return NULL;
     401      }
     402  
     403    else if (G_VALUE_HOLDS_FLAGS (value))
     404      {
     405        GVariantBuilder builder;
     406        GFlagsValue *flagsval;
     407        GFlagsClass *fclass;
     408        guint flags;
     409  
     410        fclass = g_type_class_peek (G_VALUE_TYPE (value));
     411        flags = g_value_get_flags (value);
     412  
     413        g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
     414        while (flags)
     415          {
     416            flagsval = g_flags_get_first_value (fclass, flags);
     417  
     418            if (flagsval == NULL)
     419              {
     420                g_variant_builder_clear (&builder);
     421                return NULL;
     422              }
     423  
     424            g_variant_builder_add (&builder, "s", flagsval->value_nick);
     425            flags &= ~flagsval->value;
     426          }
     427  
     428        return g_variant_builder_end (&builder);
     429      }
     430  
     431    type_string = g_variant_type_dup_string (expected_type);
     432    g_critical ("No GSettings bind handler for type \"%s\".", type_string);
     433    g_free (type_string);
     434  
     435    return NULL;
     436  }
     437  
     438  gboolean
     439  g_settings_get_mapping (GValue   *value,
     440                          GVariant *variant,
     441                          gpointer  user_data)
     442  {
     443    if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
     444      {
     445        if (!G_VALUE_HOLDS_BOOLEAN (value))
     446          return FALSE;
     447        g_value_set_boolean (value, g_variant_get_boolean (variant));
     448        return TRUE;
     449      }
     450  
     451    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTE))
     452      {
     453        if (G_VALUE_HOLDS_UCHAR (value))
     454          g_value_set_uchar (value, g_variant_get_byte (variant));
     455        else if (G_VALUE_HOLDS_CHAR (value))
     456          g_value_set_schar (value, (gint8)g_variant_get_byte (variant));
     457        else
     458          return FALSE;
     459        return TRUE;
     460      }
     461  
     462    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT16)  ||
     463             g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32)  ||
     464             g_variant_is_of_type (variant, G_VARIANT_TYPE_INT64)  ||
     465             g_variant_is_of_type (variant, G_VARIANT_TYPE_HANDLE))
     466      return g_settings_get_mapping_int (value, variant);
     467  
     468    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE))
     469      return g_settings_get_mapping_float (value, variant);
     470  
     471    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT16) ||
     472             g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32) ||
     473             g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT64))
     474      return g_settings_get_mapping_unsigned_int (value, variant);
     475  
     476    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)      ||
     477             g_variant_is_of_type (variant, G_VARIANT_TYPE_OBJECT_PATH) ||
     478             g_variant_is_of_type (variant, G_VARIANT_TYPE_SIGNATURE))
     479      {
     480        if (G_VALUE_HOLDS_STRING (value))
     481          {
     482            g_value_set_string (value, g_variant_get_string (variant, NULL));
     483            return TRUE;
     484          }
     485  
     486        else if (G_VALUE_HOLDS_ENUM (value))
     487          {
     488            GEnumClass *eclass;
     489            GEnumValue *evalue;
     490            const gchar *nick;
     491  
     492            /* GParamSpecEnum holds a ref on the class so we just peek... */
     493            eclass = g_type_class_peek (G_VALUE_TYPE (value));
     494            nick = g_variant_get_string (variant, NULL);
     495            evalue = g_enum_get_value_by_nick (eclass, nick);
     496  
     497            if (evalue)
     498              {
     499               g_value_set_enum (value, evalue->value);
     500               return TRUE;
     501              }
     502  
     503            g_warning ("Unable to look up enum nick ‘%s’ via GType", nick);
     504            return FALSE;
     505          }
     506      }
     507    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("as")))
     508      {
     509        if (G_VALUE_HOLDS (value, G_TYPE_STRV))
     510          {
     511            g_value_take_boxed (value, g_variant_dup_strv (variant, NULL));
     512            return TRUE;
     513          }
     514  
     515        else if (G_VALUE_HOLDS_FLAGS (value))
     516          {
     517            GFlagsClass *fclass;
     518            GFlagsValue *fvalue;
     519            const gchar *nick;
     520            GVariantIter iter;
     521            guint flags = 0;
     522  
     523            fclass = g_type_class_peek (G_VALUE_TYPE (value));
     524  
     525            g_variant_iter_init (&iter, variant);
     526            while (g_variant_iter_next (&iter, "&s", &nick))
     527              {
     528                fvalue = g_flags_get_value_by_nick (fclass, nick);
     529  
     530                if (fvalue)
     531                  flags |= fvalue->value;
     532  
     533                else
     534                  {
     535                    g_warning ("Unable to lookup flags nick '%s' via GType",
     536                               nick);
     537                    return FALSE;
     538                  }
     539              }
     540  
     541            g_value_set_flags (value, flags);
     542            return TRUE;
     543          }
     544      }
     545    else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BYTESTRING))
     546      {
     547        g_value_set_string (value, g_variant_get_bytestring (variant));
     548        return TRUE;
     549      }
     550  
     551    g_critical ("No GSettings bind handler for type \"%s\".",
     552                g_variant_get_type_string (variant));
     553  
     554    return FALSE;
     555  }
     556  
     557  gboolean
     558  g_settings_mapping_is_compatible (GType               gvalue_type,
     559                                    const GVariantType *variant_type)
     560  {
     561    gboolean ok = FALSE;
     562  
     563    if (gvalue_type == G_TYPE_BOOLEAN)
     564      ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN);
     565    else if (gvalue_type == G_TYPE_CHAR  ||
     566             gvalue_type == G_TYPE_UCHAR)
     567      ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE);
     568    else if (gvalue_type == G_TYPE_INT    ||
     569             gvalue_type == G_TYPE_UINT   ||
     570             gvalue_type == G_TYPE_INT64  ||
     571             gvalue_type == G_TYPE_UINT64 ||
     572             gvalue_type == G_TYPE_DOUBLE)
     573      ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16)  ||
     574            g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16) ||
     575            g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32)  ||
     576            g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32) ||
     577            g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64)  ||
     578            g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64) ||
     579            g_variant_type_equal (variant_type, G_VARIANT_TYPE_HANDLE) ||
     580            g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE));
     581    else if (gvalue_type == G_TYPE_STRING)
     582      ok = (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING)      ||
     583            g_variant_type_equal (variant_type, G_VARIANT_TYPE ("ay")) ||
     584            g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
     585            g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
     586    else if (gvalue_type == G_TYPE_STRV)
     587      ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
     588    else if (G_TYPE_IS_ENUM (gvalue_type))
     589      ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
     590    else if (G_TYPE_IS_FLAGS (gvalue_type))
     591      ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
     592  
     593    return ok;
     594  }