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    // rustdoc-stripper-ignore-next-stop
228    /// Outputs @self as a string.
229    ///
230    /// Note that this function never reports an error.
231    ///
232    /// # Returns
233    ///
234    /// a newly allocated string holding the contents of the key file
235    ///
236    /// ## `length`
237    /// return location for the length of the
238    ///   returned string, or `NULL` to ignore
239    #[doc(alias = "g_key_file_to_data")]
240    pub fn to_data(&self) -> GString {
241        unsafe {
242            let ret =
243                ffi::g_key_file_to_data(self.to_glib_none().0, ptr::null_mut(), ptr::null_mut());
244            from_glib_full(ret)
245        }
246    }
247
248    /// Returns all groups in the key file loaded with @self.
249    ///
250    /// The array of returned groups will be `NULL`-terminated, so
251    /// @length may optionally be `NULL`.
252    ///
253    /// # Returns
254    ///
255    /// a newly-allocated
256    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
257    ///
258    /// ## `length`
259    /// return location for the number of returned groups,
260    ///    or `NULL` to ignore
261    // rustdoc-stripper-ignore-next-stop
262    /// Returns all groups in the key file loaded with @self.
263    ///
264    /// The array of returned groups will be `NULL`-terminated, so
265    /// @length may optionally be `NULL`.
266    ///
267    /// # Returns
268    ///
269    /// a newly-allocated
270    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
271    ///
272    /// ## `length`
273    /// return location for the number of returned groups,
274    ///    or `NULL` to ignore
275    #[doc(alias = "g_key_file_get_groups")]
276    #[doc(alias = "get_groups")]
277    pub fn groups(&self) -> PtrSlice<GStringPtr> {
278        unsafe {
279            let mut length = mem::MaybeUninit::uninit();
280            let ret = ffi::g_key_file_get_groups(self.to_glib_none().0, length.as_mut_ptr());
281            FromGlibContainer::from_glib_full_num(ret, length.assume_init() as _)
282        }
283    }
284
285    /// Returns all keys for the group name @group_name.
286    ///
287    /// The array of returned keys will be `NULL`-terminated, so @length may
288    /// optionally be `NULL`. If the @group_name cannot be found,
289    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
290    /// ## `group_name`
291    /// a group name
292    ///
293    /// # Returns
294    ///
295    /// a newly-allocated
296    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
297    ///
298    /// ## `length`
299    /// return location for the number of keys returned,
300    ///    or `NULL` to ignore
301    // rustdoc-stripper-ignore-next-stop
302    /// Returns all keys for the group name @group_name.
303    ///
304    /// The array of returned keys will be `NULL`-terminated, so @length may
305    /// optionally be `NULL`. If the @group_name cannot be found,
306    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
307    /// ## `group_name`
308    /// a group name
309    ///
310    /// # Returns
311    ///
312    /// a newly-allocated
313    ///    `NULL`-terminated array of strings. Use `strfreev()` to free it.
314    ///
315    /// ## `length`
316    /// return location for the number of keys returned,
317    ///    or `NULL` to ignore
318    #[doc(alias = "g_key_file_get_keys")]
319    #[doc(alias = "get_keys")]
320    pub fn keys(&self, group_name: &str) -> Result<PtrSlice<GStringPtr>, crate::Error> {
321        unsafe {
322            let mut length = mem::MaybeUninit::uninit();
323            let mut error = ptr::null_mut();
324            let ret = ffi::g_key_file_get_keys(
325                self.to_glib_none().0,
326                group_name.to_glib_none().0,
327                length.as_mut_ptr(),
328                &mut error,
329            );
330            if error.is_null() {
331                Ok(FromGlibContainer::from_glib_full_num(
332                    ret,
333                    length.assume_init() as _,
334                ))
335            } else {
336                Err(from_glib_full(error))
337            }
338        }
339    }
340
341    /// Returns the value associated with @key under @group_name as a
342    /// boolean.
343    ///
344    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
345    /// returned. Likewise, if the value associated with @key cannot be interpreted
346    /// as a boolean then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
347    /// ## `group_name`
348    /// a group name
349    /// ## `key`
350    /// a key
351    ///
352    /// # Returns
353    ///
354    /// the value associated with the key as a boolean,
355    ///    or false if the key was not found or could not be parsed.
356    // rustdoc-stripper-ignore-next-stop
357    /// Returns the value associated with @key under @group_name as a
358    /// boolean.
359    ///
360    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
361    /// returned. Likewise, if the value associated with @key cannot be interpreted
362    /// as a boolean then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
363    /// ## `group_name`
364    /// a group name
365    /// ## `key`
366    /// a key
367    ///
368    /// # Returns
369    ///
370    /// the value associated with the key as a boolean,
371    ///    or false if the key was not found or could not be parsed.
372    #[doc(alias = "g_key_file_get_boolean")]
373    #[doc(alias = "get_boolean")]
374    pub fn boolean(&self, group_name: &str, key: &str) -> Result<bool, Error> {
375        unsafe {
376            let mut error = ptr::null_mut();
377            let ret = ffi::g_key_file_get_boolean(
378                self.to_glib_none().0,
379                group_name.to_glib_none().0,
380                key.to_glib_none().0,
381                &mut error,
382            );
383            if error.is_null() {
384                Ok(from_glib(ret))
385            } else {
386                Err(from_glib_full(error))
387            }
388        }
389    }
390
391    /// Looks whether the key file has the key @key in the group
392    /// @group_name.
393    ///
394    /// Note that this function does not follow the rules for [`Error`][crate::Error]
395    /// strictly;
396    /// the return value both carries meaning and signals an error.  To use
397    /// this function, you must pass a [`Error`][crate::Error] pointer in @error, and
398    /// check whether it is not `NULL` to see if an error occurred.
399    ///
400    /// Language bindings should use [`value()`][Self::value()] to test whether
401    /// a key exists.
402    /// ## `group_name`
403    /// a group name
404    /// ## `key`
405    /// a key name
406    ///
407    /// # Returns
408    ///
409    /// true if @key is a part of @group_name, false otherwise
410    // rustdoc-stripper-ignore-next-stop
411    /// Looks whether the key file has the key @key in the group
412    /// @group_name.
413    ///
414    /// Note that this function does not follow the rules for [`Error`][crate::Error]
415    /// strictly;
416    /// the return value both carries meaning and signals an error.  To use
417    /// this function, you must pass a [`Error`][crate::Error] pointer in @error, and
418    /// check whether it is not `NULL` to see if an error occurred.
419    ///
420    /// Language bindings should use [`value()`][Self::value()] to test whether
421    /// a key exists.
422    /// ## `group_name`
423    /// a group name
424    /// ## `key`
425    /// a key name
426    ///
427    /// # Returns
428    ///
429    /// true if @key is a part of @group_name, false otherwise
430    #[doc(alias = "g_key_file_has_key")]
431    pub fn has_key(&self, group_name: &str, key: &str) -> Result<bool, Error> {
432        unsafe {
433            let mut error = ptr::null_mut();
434            let ret = ffi::g_key_file_has_key(
435                self.to_glib_none().0,
436                group_name.to_glib_none().0,
437                key.to_glib_none().0,
438                &mut error,
439            );
440            if error.is_null() {
441                Ok(from_glib(ret))
442            } else {
443                Err(from_glib_full(error))
444            }
445        }
446    }
447
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    // rustdoc-stripper-ignore-next-stop
466    /// Returns the values associated with @key under @group_name as
467    /// booleans.
468    ///
469    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
470    /// returned. Likewise, if the values associated with @key cannot be interpreted
471    /// as booleans then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
472    /// ## `group_name`
473    /// a group name
474    /// ## `key`
475    /// a key
476    ///
477    /// # Returns
478    ///
479    ///
480    ///    the values associated with the key as a list of booleans, or `NULL` if the
481    ///    key was not found or could not be parsed. The returned list of booleans
482    ///    should be freed with `free()` when no longer needed.
483    #[doc(alias = "g_key_file_get_boolean_list")]
484    #[doc(alias = "get_boolean_list")]
485    pub fn boolean_list(&self, group_name: &str, key: &str) -> Result<Vec<bool>, Error> {
486        unsafe {
487            let mut length = mem::MaybeUninit::uninit();
488            let mut error = ptr::null_mut();
489            let ret = ffi::g_key_file_get_boolean_list(
490                self.to_glib_none().0,
491                group_name.to_glib_none().0,
492                key.to_glib_none().0,
493                length.as_mut_ptr(),
494                &mut error,
495            );
496            if !error.is_null() {
497                return Err(from_glib_full(error));
498            }
499            Ok(FromGlibContainer::from_glib_container_num(
500                ret,
501                length.assume_init() as _,
502            ))
503        }
504    }
505
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    // rustdoc-stripper-ignore-next-stop
524    /// Returns the string value associated with @key under @group_name.
525    ///
526    /// Unlike [`value()`][Self::value()], this function handles escape
527    /// sequences like `\s`.
528    ///
529    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
530    /// returned. If the @group_name cannot be found,
531    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
532    /// ## `group_name`
533    /// a group name
534    /// ## `key`
535    /// a key
536    ///
537    /// # Returns
538    ///
539    /// a newly allocated string or `NULL` if the specified
540    ///   key cannot be found.
541    #[doc(alias = "g_key_file_get_string")]
542    #[doc(alias = "get_string")]
543    pub fn string(&self, group_name: &str, key: &str) -> Result<GString, Error> {
544        unsafe {
545            let mut error = ptr::null_mut();
546            let ret = ffi::g_key_file_get_string(
547                self.to_glib_none().0,
548                group_name.to_glib_none().0,
549                key.to_glib_none().0,
550                &mut error,
551            );
552            if error.is_null() {
553                Ok(from_glib_full(ret))
554            } else {
555                ffi::g_free(ret as *mut _);
556                Err(from_glib_full(error))
557            }
558        }
559    }
560
561    /// Returns the values associated with @key under @group_name.
562    ///
563    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
564    /// returned. If the @group_name cannot be found,
565    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
566    /// ## `group_name`
567    /// a group name
568    /// ## `key`
569    /// a key
570    ///
571    /// # Returns
572    ///
573    ///
574    ///  a `NULL`-terminated string array or `NULL` if the specified
575    ///  key cannot be found. The array should be freed with `strfreev()`.
576    // rustdoc-stripper-ignore-next-stop
577    /// Returns the values associated with @key under @group_name.
578    ///
579    /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND] is
580    /// returned. If the @group_name cannot be found,
581    /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
582    /// ## `group_name`
583    /// a group name
584    /// ## `key`
585    /// a key
586    ///
587    /// # Returns
588    ///
589    ///
590    ///  a `NULL`-terminated string array or `NULL` if the specified
591    ///  key cannot be found. The array should be freed with `strfreev()`.
592    #[doc(alias = "g_key_file_get_string_list")]
593    #[doc(alias = "get_string_list")]
594    pub fn string_list(&self, group_name: &str, key: &str) -> Result<PtrSlice<GStringPtr>, Error> {
595        unsafe {
596            let mut length = mem::MaybeUninit::uninit();
597            let mut error = ptr::null_mut();
598            let ret = ffi::g_key_file_get_string_list(
599                self.to_glib_none().0,
600                group_name.to_glib_none().0,
601                key.to_glib_none().0,
602                length.as_mut_ptr(),
603                &mut error,
604            );
605            if error.is_null() {
606                Ok(FromGlibContainer::from_glib_full_num(
607                    ret,
608                    length.assume_init() as _,
609                ))
610            } else {
611                ffi::g_strfreev(ret);
612                Err(from_glib_full(error))
613            }
614        }
615    }
616
617    /// Returns the value associated with @key under @group_name
618    /// translated in the given @locale if available.
619    ///
620    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
621    ///
622    /// If @locale is `NULL` then the current locale is assumed.
623    ///
624    /// If @locale is to be non-`NULL`, or if the current locale will change over
625    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
626    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
627    /// locales.
628    ///
629    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
630    /// returned. If the value associated
631    /// with @key cannot be interpreted or no suitable translation can
632    /// be found then the untranslated value is returned.
633    /// ## `group_name`
634    /// a group name
635    /// ## `key`
636    /// a key
637    /// ## `locale`
638    /// a locale identifier or `NULL` to use the current locale
639    ///
640    /// # Returns
641    ///
642    /// a newly allocated string or `NULL` if the specified
643    ///   key cannot be found.
644    // rustdoc-stripper-ignore-next-stop
645    /// Returns the value associated with @key under @group_name
646    /// translated in the given @locale if available.
647    ///
648    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
649    ///
650    /// If @locale is `NULL` then the current locale is assumed.
651    ///
652    /// If @locale is to be non-`NULL`, or if the current locale will change over
653    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
654    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
655    /// locales.
656    ///
657    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
658    /// returned. If the value associated
659    /// with @key cannot be interpreted or no suitable translation can
660    /// be found then the untranslated value is returned.
661    /// ## `group_name`
662    /// a group name
663    /// ## `key`
664    /// a key
665    /// ## `locale`
666    /// a locale identifier or `NULL` to use the current locale
667    ///
668    /// # Returns
669    ///
670    /// a newly allocated string or `NULL` if the specified
671    ///   key cannot be found.
672    #[doc(alias = "g_key_file_get_locale_string")]
673    #[doc(alias = "get_locale_string")]
674    pub fn locale_string(
675        &self,
676        group_name: &str,
677        key: &str,
678        locale: Option<&str>,
679    ) -> Result<GString, Error> {
680        unsafe {
681            let mut error = ptr::null_mut();
682            let ret = ffi::g_key_file_get_locale_string(
683                self.to_glib_none().0,
684                group_name.to_glib_none().0,
685                key.to_glib_none().0,
686                locale.to_glib_none().0,
687                &mut error,
688            );
689            if error.is_null() {
690                Ok(from_glib_full(ret))
691            } else {
692                ffi::g_free(ret as *mut _);
693                Err(from_glib_full(error))
694            }
695        }
696    }
697
698    /// Returns the values associated with @key under @group_name
699    /// translated in the given @locale if available.
700    ///
701    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
702    ///
703    /// If @locale is `NULL` then the current locale is assumed.
704    ///
705    /// If @locale is to be non-`NULL`, or if the current locale will change over
706    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
707    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
708    /// locales.
709    ///
710    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
711    /// returned. If the values associated
712    /// with @key cannot be interpreted or no suitable translations
713    /// can be found then the untranslated values are returned. The
714    /// returned array is `NULL`-terminated, so @length may optionally
715    /// be `NULL`.
716    /// ## `group_name`
717    /// a group name
718    /// ## `key`
719    /// a key
720    /// ## `locale`
721    /// a locale identifier or `NULL` to use the current locale
722    ///
723    /// # Returns
724    ///
725    ///
726    ///    a newly allocated `NULL`-terminated string array or `NULL` if the key
727    ///    isn’t found. The string array should be freed with `strfreev()`.
728    // rustdoc-stripper-ignore-next-stop
729    /// Returns the values associated with @key under @group_name
730    /// translated in the given @locale if available.
731    ///
732    /// If @locale is `C` then the untranslated value is returned (since GLib 2.84).
733    ///
734    /// If @locale is `NULL` then the current locale is assumed.
735    ///
736    /// If @locale is to be non-`NULL`, or if the current locale will change over
737    /// the lifetime of the [`KeyFile`][crate::KeyFile], it must be loaded with
738    /// [flags@GLib.KeyFileFlags.KEEP_TRANSLATIONS] in order to load strings for all
739    /// locales.
740    ///
741    /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
742    /// returned. If the values associated
743    /// with @key cannot be interpreted or no suitable translations
744    /// can be found then the untranslated values are returned. The
745    /// returned array is `NULL`-terminated, so @length may optionally
746    /// be `NULL`.
747    /// ## `group_name`
748    /// a group name
749    /// ## `key`
750    /// a key
751    /// ## `locale`
752    /// a locale identifier or `NULL` to use the current locale
753    ///
754    /// # Returns
755    ///
756    ///
757    ///    a newly allocated `NULL`-terminated string array or `NULL` if the key
758    ///    isn’t found. The string array should be freed with `strfreev()`.
759    #[doc(alias = "g_key_file_get_locale_string_list")]
760    #[doc(alias = "get_locale_string_list")]
761    pub fn locale_string_list(
762        &self,
763        group_name: &str,
764        key: &str,
765        locale: Option<&str>,
766    ) -> Result<PtrSlice<GStringPtr>, Error> {
767        unsafe {
768            let mut length = mem::MaybeUninit::uninit();
769            let mut error = ptr::null_mut();
770            let ret = ffi::g_key_file_get_locale_string_list(
771                self.to_glib_none().0,
772                group_name.to_glib_none().0,
773                key.to_glib_none().0,
774                locale.to_glib_none().0,
775                length.as_mut_ptr(),
776                &mut error,
777            );
778            if error.is_null() {
779                Ok(FromGlibContainer::from_glib_full_num(
780                    ret,
781                    length.assume_init() as _,
782                ))
783            } else {
784                ffi::g_strfreev(ret);
785                Err(from_glib_full(error))
786            }
787        }
788    }
789}