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