2017-09-21 15:26:06 -04:00
/*
2011-11-04 13:42:05 -04:00
* Copyright ( C ) 2011 Colin Walters < walters @ verbum . org >
*
2018-01-30 20:26:26 +01:00
* SPDX - License - Identifier : LGPL - 2.0 +
*
2011-11-10 13:17:04 -05:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
2011-11-04 13:42:05 -04:00
*
2011-11-10 13:17:04 -05:00
* This library is distributed in the hope that it will be useful ,
2011-11-04 13:42:05 -04:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2011-11-10 13:17:04 -05:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
2011-11-04 13:42:05 -04:00
*
2011-11-10 13:17:04 -05:00
* You should have received a copy of the GNU Lesser General Public
2021-12-06 20:20:55 -05:00
* License along with this library . If not , see < https : //www.gnu.org/licenses/>.
2011-11-04 13:42:05 -04:00
*
* Author : Colin Walters < walters @ verbum . org >
*/
# include "config.h"
2013-08-15 09:17:37 -04:00
# include <gio/gfiledescriptorbased.h>
2023-05-01 14:24:29 -04:00
# include <gio/gio.h>
2011-11-04 13:42:05 -04:00
# include <string.h>
# include "otutil.h"
2017-10-04 06:32:10 -04:00
/* Create a new GVariant empty GVariant of type a{sv} */
2014-07-31 18:50:19 -04:00
GVariant *
ot_gvariant_new_empty_string_dict ( void )
{
2023-05-01 14:24:29 -04:00
g_auto ( GVariantBuilder ) builder = OT_VARIANT_BUILDER_INITIALIZER ;
2016-05-24 10:36:38 +02:00
g_variant_builder_init ( & builder , G_VARIANT_TYPE ( " a{sv} " ) ) ;
return g_variant_builder_end ( & builder ) ;
2014-07-31 18:50:19 -04:00
}
2017-10-04 06:32:10 -04:00
/* Create a new GVariant of type ay from the raw @data pointer */
2012-04-02 13:42:09 -04:00
GVariant *
2023-05-01 14:24:29 -04:00
ot_gvariant_new_bytearray ( const guchar * data , gsize len )
2012-04-02 13:42:09 -04:00
{
2022-10-28 12:19:29 +01:00
gpointer data_copy = g_memdup2 ( data , len ) ;
2023-05-01 14:24:29 -04:00
GVariant * ret
= g_variant_new_from_data ( G_VARIANT_TYPE ( " ay " ) , data_copy , len , FALSE , g_free , data_copy ) ;
2012-04-02 13:42:09 -04:00
return ret ;
}
2017-10-04 06:32:10 -04:00
/* Convert a GBytes into a GVariant of type ay (byte array) */
2013-08-14 18:20:02 -04:00
GVariant *
ot_gvariant_new_ay_bytes ( GBytes * bytes )
{
2013-08-18 07:50:50 -04:00
gsize size ;
2017-10-04 06:32:10 -04:00
gconstpointer data = g_bytes_get_data ( bytes , & size ) ;
2013-08-18 07:50:50 -04:00
g_bytes_ref ( bytes ) ;
2023-05-01 14:24:29 -04:00
return g_variant_new_from_data ( G_VARIANT_TYPE ( " ay " ) , data , size , TRUE ,
( GDestroyNotify ) g_bytes_unref , bytes ) ;
2013-08-14 18:20:02 -04:00
}
2017-10-04 15:06:31 -04:00
/* Create a GVariant in @out_variant that is backed by
* the data from @ fd , starting at @ start . If the data is
* large enough , mmap ( ) may be used . @ trusted is used
* by the GVariant core ; see g_variant_new_from_data ( ) .
*/
2016-01-27 22:02:36 -05:00
gboolean
2023-05-01 14:24:29 -04:00
ot_variant_read_fd ( int fd , goffset start , const GVariantType * type , gboolean trusted ,
GVariant * * out_variant , GError * * error )
2013-08-15 09:17:37 -04:00
{
2023-05-01 14:24:29 -04:00
g_autoptr ( GBytes ) bytes = ot_fd_readall_or_mmap ( fd , start , error ) ;
2017-10-04 15:06:31 -04:00
if ( ! bytes )
return FALSE ;
2013-08-15 09:17:37 -04:00
2017-10-04 15:06:31 -04:00
* out_variant = g_variant_ref_sink ( g_variant_new_from_bytes ( type , bytes , trusted ) ) ;
return TRUE ;
2013-08-15 09:17:37 -04:00
}
2017-10-04 06:32:10 -04:00
/* GVariants are immutable; this function allows generating an open builder
* for a new variant , inherting the data from @ variant .
*/
2013-09-02 19:43:49 -06:00
GVariantBuilder *
2023-05-01 14:24:29 -04:00
ot_util_variant_builder_from_variant ( GVariant * variant , const GVariantType * type )
2013-09-02 19:43:49 -06:00
{
2017-10-04 06:32:10 -04:00
GVariantBuilder * builder = g_variant_builder_new ( type ) ;
2015-03-02 14:55:01 -05:00
if ( variant ! = NULL )
2013-09-02 19:43:49 -06:00
{
2017-10-04 06:32:10 -04:00
const int n = g_variant_n_children ( variant ) ;
for ( int i = 0 ; i < n ; i + + )
2015-03-02 14:55:01 -05:00
{
2023-05-01 14:24:29 -04:00
g_autoptr ( GVariant ) child = g_variant_get_child_value ( variant , i ) ;
2015-03-02 14:55:01 -05:00
g_variant_builder_add_value ( builder , child ) ;
}
2013-09-02 19:43:49 -06:00
}
2017-10-04 06:32:10 -04:00
2013-09-02 19:43:49 -06:00
return builder ;
}
2014-07-31 18:50:19 -04:00
/**
* ot_variant_bsearch_str :
* @ array : A GVariant array whose first element must be a string
* @ str : Search for this string
* @ out_pos : Output position
*
*
* Binary search in a GVariant array , which must be of the form ' a ( s . . . ) ' ,
* where ' . . . ' may be anything . The array elements must be sorted .
*
* Returns : % TRUE if found , % FALSE otherwise
*/
gboolean
2023-05-01 14:24:29 -04:00
ot_variant_bsearch_str ( GVariant * array , const char * str , int * out_pos )
2014-07-31 18:50:19 -04:00
{
2017-10-04 06:32:10 -04:00
const gsize n = g_variant_n_children ( array ) ;
2014-07-31 18:50:19 -04:00
if ( n = = 0 )
return FALSE ;
2017-10-04 06:32:10 -04:00
gsize imax = n - 1 ;
gsize imin = 0 ;
gsize imid = - 1 ;
2014-07-31 18:50:19 -04:00
while ( imax > = imin )
{
const char * cur ;
imid = ( imin + imax ) / 2 ;
2023-05-01 14:24:29 -04:00
g_autoptr ( GVariant ) child = g_variant_get_child_value ( array , imid ) ;
2016-04-08 12:18:17 -04:00
g_variant_get_child ( child , 0 , " &s " , & cur , NULL ) ;
2014-07-31 18:50:19 -04:00
2017-10-04 06:32:10 -04:00
int cmp = strcmp ( cur , str ) ;
2014-07-31 18:50:19 -04:00
if ( cmp < 0 )
imin = imid + 1 ;
else if ( cmp > 0 )
{
if ( imid = = 0 )
break ;
imax = imid - 1 ;
}
else
{
* out_pos = imid ;
return TRUE ;
}
}
* out_pos = imid ;
return FALSE ;
}