glib/
key_file.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, path, ptr};
4
5use crate::{ffi, translate::*, Error, GString, GStringPtr, KeyFile, KeyFileFlags, PtrSlice};
6
7impl KeyFile {
8    /// Writes the contents of @self to @filename using
9    /// [`file_set_contents()`][crate::file_set_contents()].
10    ///
11    /// If you need stricter guarantees about durability of
12    /// the written file than are provided by [`file_set_contents()`][crate::file_set_contents()], use
13    /// [`file_set_contents_full()`][crate::file_set_contents_full()] with the return value of
14    /// [`to_data()`][Self::to_data()].
15    ///
16    /// This function can fail for any of the reasons that
17    /// [`file_set_contents()`][crate::file_set_contents()] may fail.
18    /// ## `filename`
19    /// the name of the file to write to
20    ///
21    /// # Returns
22    ///
23    /// true if successful, false otherwise
24    // rustdoc-stripper-ignore-next-stop
25    /// Writes the contents of @self to @filename using
26    /// [`file_set_contents()`][crate::file_set_contents()].
27    ///
28    /// If you need stricter guarantees about durability of
29    /// the written file than are provided by [`file_set_contents()`][crate::file_set_contents()], use
30    /// [`file_set_contents_full()`][crate::file_set_contents_full()] with the return value of
31    /// [`to_data()`][Self::to_data()].
32    ///
33    /// This function can fail for any of the reasons that
34    /// [`file_set_contents()`][crate::file_set_contents()] may fail.
35    /// ## `filename`
36    /// the name of the file to write to
37    ///
38    /// # Returns
39    ///
40    /// true if successful, false otherwise
41    #[doc(alias = "g_key_file_save_to_file")]
42    pub fn save_to_file<T: AsRef<std::path::Path>>(&self, filename: T) -> Result<(), Error> {
43        unsafe {
44            let mut error = ptr::null_mut();
45            let _ = ffi::g_key_file_save_to_file(
46                self.to_glib_none().0,
47                filename.as_ref().to_glib_none().0,
48                &mut error,
49            );
50            if error.is_null() {
51                Ok(())
52            } else {
53                Err(from_glib_full(error))
54            }
55        }
56    }
57
58    /// Looks for a key file named @file in the paths returned from
59    /// [`user_data_dir()`][crate::user_data_dir()] and [`system_data_dirs()`][crate::system_data_dirs()],
60    /// loads the file into @self and returns the file’s full path in
61    /// @full_path.
62    ///
63    /// If the file could not be loaded then either a [`FileError`][crate::FileError] or
64    /// [`KeyFileError`][crate::KeyFileError] is returned.
65    /// ## `file`
66    /// a relative path to a filename to open and parse
67    /// ## `flags`
68    /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
69    ///
70    /// # Returns
71    ///
72    /// true if a key file could be loaded, false otherwise
73    ///
74    /// ## `full_path`
75    /// return location for a string
76    ///    containing the full path of the file, or `NULL` to ignore
77    // rustdoc-stripper-ignore-next-stop
78    /// Looks for a key file named @file in the paths returned from
79    /// [`user_data_dir()`][crate::user_data_dir()] and [`system_data_dirs()`][crate::system_data_dirs()],
80    /// loads the file into @self and returns the file’s full path in
81    /// @full_path.
82    ///
83    /// If the file could not be loaded then either a [`FileError`][crate::FileError] or
84    /// [`KeyFileError`][crate::KeyFileError] is returned.
85    /// ## `file`
86    /// a relative path to a filename to open and parse
87    /// ## `flags`
88    /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
89    ///
90    /// # Returns
91    ///
92    /// true if a key file could be loaded, false otherwise
93    ///
94    /// ## `full_path`
95    /// return location for a string
96    ///    containing the full path of the file, or `NULL` to ignore
97    #[doc(alias = "g_key_file_load_from_data_dirs")]
98    pub fn load_from_data_dirs<T: AsRef<std::path::Path>>(
99        &self,
100        file: T,
101        flags: KeyFileFlags,
102    ) -> Result<path::PathBuf, Error> {
103        unsafe {
104            let mut error = ptr::null_mut();
105            let mut full_path: *mut libc::c_char = ptr::null_mut();
106            let _ = ffi::g_key_file_load_from_data_dirs(
107                self.to_glib_none().0,
108                file.as_ref().to_glib_none().0,
109                &mut full_path,
110                flags.into_glib(),
111                &mut error,
112            );
113            if error.is_null() {
114                let path: GString = from_glib_full(full_path);
115                Ok(path::PathBuf::from(&path))
116            } else {
117                Err(from_glib_full(error))
118            }
119        }
120    }
121
122    /// Looks for a key file named @file in the paths specified in @search_dirs,
123    /// loads the file into @self and returns the file’s full path in @full_path.
124    ///
125    /// If the file could not be found in any of the @search_dirs,
126    /// [error@GLib.KeyFileError.NOT_FOUND] is returned. If
127    /// the file is found but the OS returns an error when opening or reading the
128    /// file, a [`FileError`][crate::FileError] is returned. If there is a problem parsing the
129    /// file, a [`KeyFileError`][crate::KeyFileError] is returned.
130    /// ## `file`
131    /// a relative path to a filename to open and parse
132    /// ## `search_dirs`
133    /// `NULL`-terminated
134    ///    array of directories to search
135    /// ## `flags`
136    /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
137    ///
138    /// # Returns
139    ///
140    /// true if a key file could be loaded, false otherwise
141    ///
142    /// ## `full_path`
143    /// return location for a string
144    ///    containing the full path of the file, or `NULL` to ignore
145    // rustdoc-stripper-ignore-next-stop
146    /// Looks for a key file named @file in the paths specified in @search_dirs,
147    /// loads the file into @self and returns the file’s full path in @full_path.
148    ///
149    /// If the file could not be found in any of the @search_dirs,
150    /// [error@GLib.KeyFileError.NOT_FOUND] is returned. If
151    /// the file is found but the OS returns an error when opening or reading the
152    /// file, a [`FileError`][crate::FileError] is returned. If there is a problem parsing the
153    /// file, a [`KeyFileError`][crate::KeyFileError] is returned.
154    /// ## `file`
155    /// a relative path to a filename to open and parse
156    /// ## `search_dirs`
157    /// `NULL`-terminated
158    ///    array of directories to search
159    /// ## `flags`
160    /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
161    ///
162    /// # Returns
163    ///
164    /// true if a key file could be loaded, false otherwise
165    ///
166    /// ## `full_path`
167    /// return location for a string
168    ///    containing the full path of the file, or `NULL` to ignore
169    #[doc(alias = "g_key_file_load_from_dirs")]
170    pub fn load_from_dirs<T: AsRef<std::path::Path>, U: AsRef<std::path::Path>>(
171        &self,
172        file: T,
173        search_dirs: &[U],
174        flags: KeyFileFlags,
175    ) -> Result<path::PathBuf, Error> {
176        unsafe {
177            let search_dirs: Vec<&std::path::Path> =
178                search_dirs.iter().map(AsRef::as_ref).collect();
179            let mut error = ptr::null_mut();
180            let mut full_path: *mut libc::c_char = ptr::null_mut();
181            let _ = ffi::g_key_file_load_from_dirs(
182                self.to_glib_none().0,
183                file.as_ref().to_glib_none().0,
184                search_dirs.to_glib_none().0,
185                &mut full_path,
186                flags.into_glib(),
187                &mut error,
188            );
189            if error.is_null() {
190                let path: GString = from_glib_full(full_path);
191                Ok(path::PathBuf::from(&path))
192            } else {
193                Err(from_glib_full(error))
194            }
195        }
196    }
197
198    /// Outputs @self as a string.
199    ///
200    /// Note that this function never reports an error.
201    ///
202    /// # Returns
203    ///
204    /// a newly allocated string holding the contents of the key file
205    ///
206    /// ## `length`
207    /// return location for the length of the
208    ///   returned string, or `NULL` to ignore
209    // rustdoc-stripper-ignore-next-stop
210    /// Outputs @self as a string.
211    ///
212    /// Note that this function never reports an error.
213    ///
214    /// # Returns
215    ///
216    /// a newly allocated string holding the contents of the key file
217    ///
218    /// ## `length`
219    /// return location for the length of the
220    ///   returned string, or `NULL` to ignore
221    #[doc(alias = "g_key_file_to_data")]
222    pub fn to_data(&self) -> GString {
223        unsafe {
224            let ret =
225                ffi::g_key_file_to_data(self.to_glib_none().0, ptr::null_mut(), ptr::null_mut());
226            from_glib_full(ret)
227        }
228    }
229
230    /// Returns all groups in the key file loaded with @self.
231    ///
232    /// The array of returned groups will be `NULL`-terminated, so
233    /// @length may optionally be `NULL`.
234    ///
235    /// # Returns
236    ///
237    /// a newly-allocated
238    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
239    ///
240    /// ## `length`
241    /// return location for the number of returned groups,
242    ///    or `NULL` to ignore
243    // rustdoc-stripper-ignore-next-stop
244    /// Returns all groups in the key file loaded with @self.
245    ///
246    /// The array of returned groups will be `NULL`-terminated, so
247    /// @length may optionally be `NULL`.
248    ///
249    /// # Returns
250    ///
251    /// a newly-allocated
252    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
253    ///
254    /// ## `length`
255    /// return location for the number of returned groups,
256    ///    or `NULL` to ignore
257    #[doc(alias = "g_key_file_get_groups")]
258    #[doc(alias = "get_groups")]
259    pub fn groups(&self) -> PtrSlice<GStringPtr> {
260        unsafe {
261            let mut length = mem::MaybeUninit::uninit();
262            let ret = ffi::g_key_file_get_groups(self.to_glib_none().0, length.as_mut_ptr());
263            FromGlibContainer::from_glib_full_num(ret, length.assume_init() as _)
264        }
265    }
266
267    /// Returns all keys for the group name @group_name.
268    ///
269    /// The array of returned keys will be `NULL`-terminated, so @length may
270    /// optionally be `NULL`. If the @group_name cannot be found,
271    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
272    /// ## `group_name`
273    /// a group name
274    ///
275    /// # Returns
276    ///
277    /// a newly-allocated
278    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
279    ///
280    /// ## `length`
281    /// return location for the number of keys returned,
282    ///    or `NULL` to ignore
283    // rustdoc-stripper-ignore-next-stop
284    /// Returns all keys for the group name @group_name.
285    ///
286    /// The array of returned keys will be `NULL`-terminated, so @length may
287    /// optionally be `NULL`. If the @group_name cannot be found,
288    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
289    /// ## `group_name`
290    /// a group name
291    ///
292    /// # Returns
293    ///
294    /// a newly-allocated
295    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
296    ///
297    /// ## `length`
298    /// return location for the number of keys returned,
299    ///    or `NULL` to ignore
300    #[doc(alias = "g_key_file_get_keys")]
301    #[doc(alias = "get_keys")]
302    pub fn keys(&self, group_name: &str) -> Result<PtrSlice<GStringPtr>, crate::Error> {
303        unsafe {
304            let mut length = mem::MaybeUninit::uninit();
305            let mut error = ptr::null_mut();
306            let ret = ffi::g_key_file_get_keys(
307                self.to_glib_none().0,
308                group_name.to_glib_none().0,
309                length.as_mut_ptr(),
310                &mut error,
311            );
312            if error.is_null() {
313                Ok(FromGlibContainer::from_glib_full_num(
314                    ret,
315                    length.assume_init() as _,
316                ))
317            } else {
318                Err(from_glib_full(error))
319            }
320        }
321    }
322
323    /// Returns the value associated with @key under @group_name as a
324    /// boolean.
325    ///
326    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
327    /// returned. Likewise, if the value associated with @key cannot be interpreted
328    /// as a boolean then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
329    /// ## `group_name`
330    /// a group name
331    /// ## `key`
332    /// a key
333    ///
334    /// # Returns
335    ///
336    /// the value associated with the key as a boolean,
337    ///    or false if the key was not found or could not be parsed.
338    // rustdoc-stripper-ignore-next-stop
339    /// Returns the value associated with @key under @group_name as a
340    /// boolean.
341    ///
342    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
343    /// returned. Likewise, if the value associated with @key cannot be interpreted
344    /// as a boolean then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
345    /// ## `group_name`
346    /// a group name
347    /// ## `key`
348    /// a key
349    ///
350    /// # Returns
351    ///
352    /// the value associated with the key as a boolean,
353    ///    or false if the key was not found or could not be parsed.
354    #[doc(alias = "g_key_file_get_boolean")]
355    #[doc(alias = "get_boolean")]
356    pub fn boolean(&self, group_name: &str, key: &str) -> Result<bool, Error> {
357        unsafe {
358            let mut error = ptr::null_mut();
359            let ret = ffi::g_key_file_get_boolean(
360                self.to_glib_none().0,
361                group_name.to_glib_none().0,
362                key.to_glib_none().0,
363                &mut error,
364            );
365            if error.is_null() {
366                Ok(from_glib(ret))
367            } else {
368                Err(from_glib_full(error))
369            }
370        }
371    }
372
373    /// Looks whether the key file has the key @key in the group
374    /// @group_name.
375    ///
376    /// Note that this function does not follow the rules for [`Error`][crate::Error]
377    /// strictly;
378    /// the return value both carries meaning and signals an error.  To use
379    /// this function, you must pass a [`Error`][crate::Error] pointer in @error, and
380    /// check whether it is not `NULL` to see if an error occurred.
381    ///
382    /// Language bindings should use [`value()`][Self::value()] to test whether
383    /// a key exists.
384    /// ## `group_name`
385    /// a group name
386    /// ## `key`
387    /// a key name
388    ///
389    /// # Returns
390    ///
391    /// true if @key is a part of @group_name, false otherwise
392    // rustdoc-stripper-ignore-next-stop
393    /// Looks whether the key file has the key @key in the group
394    /// @group_name.
395    ///
396    /// Note that this function does not follow the rules for [`Error`][crate::Error]
397    /// strictly;
398    /// the return value both carries meaning and signals an error.  To use
399    /// this function, you must pass a [`Error`][crate::Error] pointer in @error, and
400    /// check whether it is not `NULL` to see if an error occurred.
401    ///
402    /// Language bindings should use [`value()`][Self::value()] to test whether
403    /// a key exists.
404    /// ## `group_name`
405    /// a group name
406    /// ## `key`
407    /// a key name
408    ///
409    /// # Returns
410    ///
411    /// true if @key is a part of @group_name, false otherwise
412    #[doc(alias = "g_key_file_has_key")]
413    pub fn has_key(&self, group_name: &str, key: &str) -> Result<bool, Error> {
414        unsafe {
415            let mut error = ptr::null_mut();
416            let ret = ffi::g_key_file_has_key(
417                self.to_glib_none().0,
418                group_name.to_glib_none().0,
419                key.to_glib_none().0,
420                &mut error,
421            );
422            if error.is_null() {
423                Ok(from_glib(ret))
424            } else {
425                Err(from_glib_full(error))
426            }
427        }
428    }
429
430    /// Returns the values associated with @key under @group_name as
431    /// booleans.
432    ///
433    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
434    /// returned. Likewise, if the values associated with @key cannot be interpreted
435    /// as booleans then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
436    /// ## `group_name`
437    /// a group name
438    /// ## `key`
439    /// a key
440    ///
441    /// # Returns
442    ///
443    ///
444    ///    the values associated with the key as a list of booleans, or `NULL` if the
445    ///    key was not found or could not be parsed. The returned list of booleans
446    ///    should be freed with `free()` when no longer needed.
447    // rustdoc-stripper-ignore-next-stop
448    /// Returns the values associated with @key under @group_name as
449    /// booleans.
450    ///
451    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
452    /// returned. Likewise, if the values associated with @key cannot be interpreted
453    /// as booleans then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
454    /// ## `group_name`
455    /// a group name
456    /// ## `key`
457    /// a key
458    ///
459    /// # Returns
460    ///
461    ///
462    ///    the values associated with the key as a list of booleans, or `NULL` if the
463    ///    key was not found or could not be parsed. The returned list of booleans
464    ///    should be freed with `free()` when no longer needed.
465    #[doc(alias = "g_key_file_get_boolean_list")]
466    #[doc(alias = "get_boolean_list")]
467    pub fn boolean_list(&self, group_name: &str, key: &str) -> Result<Vec<bool>, Error> {
468        unsafe {
469            let mut length = mem::MaybeUninit::uninit();
470            let mut error = ptr::null_mut();
471            let ret = ffi::g_key_file_get_boolean_list(
472                self.to_glib_none().0,
473                group_name.to_glib_none().0,
474                key.to_glib_none().0,
475                length.as_mut_ptr(),
476                &mut error,
477            );
478            if !error.is_null() {
479                return Err(from_glib_full(error));
480            }
481            Ok(FromGlibContainer::from_glib_container_num(
482                ret,
483                length.assume_init() as _,
484            ))
485        }
486    }
487
488    /// Returns the string value associated with @key under @group_name.
489    ///
490    /// Unlike [`value()`][Self::value()], this function handles escape
491    /// sequences like `\s`.
492    ///
493    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
494    /// returned. If the @group_name cannot be found,
495    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
496    /// ## `group_name`
497    /// a group name
498    /// ## `key`
499    /// a key
500    ///
501    /// # Returns
502    ///
503    /// a newly allocated string or `NULL` if the specified
504    ///   key cannot be found.
505    // rustdoc-stripper-ignore-next-stop
506    /// Returns the string value associated with @key under @group_name.
507    ///
508    /// Unlike [`value()`][Self::value()], this function handles escape
509    /// sequences like `\s`.
510    ///
511    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
512    /// returned. If the @group_name cannot be found,
513    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
514    /// ## `group_name`
515    /// a group name
516    /// ## `key`
517    /// a key
518    ///
519    /// # Returns
520    ///
521    /// a newly allocated string or `NULL` if the specified
522    ///   key cannot be found.
523    #[doc(alias = "g_key_file_get_string")]
524    #[doc(alias = "get_string")]
525    pub fn string(&self, group_name: &str, key: &str) -> Result<GString, Error> {
526        unsafe {
527            let mut error = ptr::null_mut();
528            let ret = ffi::g_key_file_get_string(
529                self.to_glib_none().0,
530                group_name.to_glib_none().0,
531                key.to_glib_none().0,
532                &mut error,
533            );
534            if error.is_null() {
535                Ok(from_glib_full(ret))
536            } else {
537                ffi::g_free(ret as *mut _);
538                Err(from_glib_full(error))
539            }
540        }
541    }
542
543    /// Returns the values associated with @key under @group_name.
544    ///
545    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
546    /// returned. If the @group_name cannot be found,
547    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
548    /// ## `group_name`
549    /// a group name
550    /// ## `key`
551    /// a key
552    ///
553    /// # Returns
554    ///
555    ///
556    ///  a `NULL`-terminated string array or `NULL` if the specified
557    ///  key cannot be found. The array should be freed with `strfreev()`.
558    // rustdoc-stripper-ignore-next-stop
559    /// Returns the values associated with @key under @group_name.
560    ///
561    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
562    /// returned. If the @group_name cannot be found,
563    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
564    /// ## `group_name`
565    /// a group name
566    /// ## `key`
567    /// a key
568    ///
569    /// # Returns
570    ///
571    ///
572    ///  a `NULL`-terminated string array or `NULL` if the specified
573    ///  key cannot be found. The array should be freed with `strfreev()`.
574    #[doc(alias = "g_key_file_get_string_list")]
575    #[doc(alias = "get_string_list")]
576    pub fn string_list(&self, group_name: &str, key: &str) -> Result<PtrSlice<GStringPtr>, Error> {
577        unsafe {
578            let mut length = mem::MaybeUninit::uninit();
579            let mut error = ptr::null_mut();
580            let ret = ffi::g_key_file_get_string_list(
581                self.to_glib_none().0,
582                group_name.to_glib_none().0,
583                key.to_glib_none().0,
584                length.as_mut_ptr(),
585                &mut error,
586            );
587            if error.is_null() {
588                Ok(FromGlibContainer::from_glib_full_num(
589                    ret,
590                    length.assume_init() as _,
591                ))
592            } else {
593                ffi::g_strfreev(ret);
594                Err(from_glib_full(error))
595            }
596        }
597    }
598
599    /// Returns the value associated with @key under @group_name
600    /// translated in the given @locale if available.
601    ///
602    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
603    ///
604    /// If @locale is `NULL` then the current locale is assumed.
605    ///
606    /// If @locale is to be non-`NULL`, or if the current locale will change over
607    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
608    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
609    /// locales.
610    ///
611    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
612    /// returned. If the value associated
613    /// with @key cannot be interpreted or no suitable translation can
614    /// be found then the untranslated value is returned.
615    /// ## `group_name`
616    /// a group name
617    /// ## `key`
618    /// a key
619    /// ## `locale`
620    /// a locale identifier or `NULL` to use the current locale
621    ///
622    /// # Returns
623    ///
624    /// a newly allocated string or `NULL` if the specified
625    ///   key cannot be found.
626    // rustdoc-stripper-ignore-next-stop
627    /// Returns the value associated with @key under @group_name
628    /// translated in the given @locale if available.
629    ///
630    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
631    ///
632    /// If @locale is `NULL` then the current locale is assumed.
633    ///
634    /// If @locale is to be non-`NULL`, or if the current locale will change over
635    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
636    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
637    /// locales.
638    ///
639    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
640    /// returned. If the value associated
641    /// with @key cannot be interpreted or no suitable translation can
642    /// be found then the untranslated value is returned.
643    /// ## `group_name`
644    /// a group name
645    /// ## `key`
646    /// a key
647    /// ## `locale`
648    /// a locale identifier or `NULL` to use the current locale
649    ///
650    /// # Returns
651    ///
652    /// a newly allocated string or `NULL` if the specified
653    ///   key cannot be found.
654    #[doc(alias = "g_key_file_get_locale_string")]
655    #[doc(alias = "get_locale_string")]
656    pub fn locale_string(
657        &self,
658        group_name: &str,
659        key: &str,
660        locale: Option<&str>,
661    ) -> Result<GString, Error> {
662        unsafe {
663            let mut error = ptr::null_mut();
664            let ret = ffi::g_key_file_get_locale_string(
665                self.to_glib_none().0,
666                group_name.to_glib_none().0,
667                key.to_glib_none().0,
668                locale.to_glib_none().0,
669                &mut error,
670            );
671            if error.is_null() {
672                Ok(from_glib_full(ret))
673            } else {
674                ffi::g_free(ret as *mut _);
675                Err(from_glib_full(error))
676            }
677        }
678    }
679
680    /// Returns the values associated with @key under @group_name
681    /// translated in the given @locale if available.
682    ///
683    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
684    ///
685    /// If @locale is `NULL` then the current locale is assumed.
686    ///
687    /// If @locale is to be non-`NULL`, or if the current locale will change over
688    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
689    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
690    /// locales.
691    ///
692    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
693    /// returned. If the values associated
694    /// with @key cannot be interpreted or no suitable translations
695    /// can be found then the untranslated values are returned. The
696    /// returned array is `NULL`-terminated, so @length may optionally
697    /// be `NULL`.
698    /// ## `group_name`
699    /// a group name
700    /// ## `key`
701    /// a key
702    /// ## `locale`
703    /// a locale identifier or `NULL` to use the current locale
704    ///
705    /// # Returns
706    ///
707    ///
708    ///    a newly allocated `NULL`-terminated string array or `NULL` if the key
709    ///    isn’t found. The string array should be freed with `strfreev()`.
710    // rustdoc-stripper-ignore-next-stop
711    /// Returns the values associated with @key under @group_name
712    /// translated in the given @locale if available.
713    ///
714    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
715    ///
716    /// If @locale is `NULL` then the current locale is assumed.
717    ///
718    /// If @locale is to be non-`NULL`, or if the current locale will change over
719    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
720    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
721    /// locales.
722    ///
723    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
724    /// returned. If the values associated
725    /// with @key cannot be interpreted or no suitable translations
726    /// can be found then the untranslated values are returned. The
727    /// returned array is `NULL`-terminated, so @length may optionally
728    /// be `NULL`.
729    /// ## `group_name`
730    /// a group name
731    /// ## `key`
732    /// a key
733    /// ## `locale`
734    /// a locale identifier or `NULL` to use the current locale
735    ///
736    /// # Returns
737    ///
738    ///
739    ///    a newly allocated `NULL`-terminated string array or `NULL` if the key
740    ///    isn’t found. The string array should be freed with `strfreev()`.
741    #[doc(alias = "g_key_file_get_locale_string_list")]
742    #[doc(alias = "get_locale_string_list")]
743    pub fn locale_string_list(
744        &self,
745        group_name: &str,
746        key: &str,
747        locale: Option<&str>,
748    ) -> Result<PtrSlice<GStringPtr>, Error> {
749        unsafe {
750            let mut length = mem::MaybeUninit::uninit();
751            let mut error = ptr::null_mut();
752            let ret = ffi::g_key_file_get_locale_string_list(
753                self.to_glib_none().0,
754                group_name.to_glib_none().0,
755                key.to_glib_none().0,
756                locale.to_glib_none().0,
757                length.as_mut_ptr(),
758                &mut error,
759            );
760            if error.is_null() {
761                Ok(FromGlibContainer::from_glib_full_num(
762                    ret,
763                    length.assume_init() as _,
764                ))
765            } else {
766                ffi::g_strfreev(ret);
767                Err(from_glib_full(error))
768            }
769        }
770    }
771}