glib/auto/key_file.rs
1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{Bytes, Error, KeyFileFlags, ffi, translate::*};
6
7crate::wrapper! {
8 /// `GKeyFile` parses .ini-like config files.
9 ///
10 /// `GKeyFile` lets you parse, edit or create files containing groups of
11 /// key-value pairs, which we call ‘key files’ for lack of a better name.
12 /// Several freedesktop.org specifications use key files. For example, the
13 /// [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/)
14 /// and the [Icon Theme Specification](https://specifications.freedesktop.org/icon-theme-spec/latest/).
15 ///
16 /// The syntax of key files is described in detail in the
17 /// [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/),
18 /// here is a quick summary: Key files consists of groups of key-value pairs, interspersed
19 /// with comments.
20 ///
21 /// **⚠️ The following code is in txt ⚠️**
22 ///
23 /// ```txt
24 /// # this is just an example
25 /// # there can be comments before the first group
26 ///
27 /// [First Group]
28 ///
29 /// Name=Key File Example\tthis value shows\nescaping
30 ///
31 /// # localized strings are stored in multiple key-value pairs
32 /// Welcome=Hello
33 /// Welcome[de]=Hallo
34 /// Welcome[fr_FR]=Bonjour
35 /// Welcome[it]=Ciao
36 ///
37 /// [Another Group]
38 ///
39 /// Numbers=2;20;-200;0
40 ///
41 /// Booleans=true;false;true;true
42 /// ```
43 ///
44 /// Lines beginning with a `#` and blank lines are considered comments.
45 ///
46 /// Groups are started by a header line containing the group name enclosed
47 /// in `[` and `]`, and ended implicitly by the start of the next group or
48 /// the end of the file. Each key-value pair must be contained in a group.
49 ///
50 /// Key-value pairs generally have the form `key=value`, with the exception
51 /// of localized strings, which have the form `key[locale]=value`, with a
52 /// locale identifier of the form `lang_COUNTRY@MODIFIER` where `COUNTRY`
53 /// and `MODIFIER` are optional. As a special case, the locale `C` is associated
54 /// with the untranslated pair `key=value` (since GLib 2.84). Space before and
55 /// after the `=` character is ignored. Newline, tab, carriage return and
56 /// backslash characters in value are escaped as `\n`, `\t`, `\r`, and `\\\\`,
57 /// respectively. To preserve leading spaces in values, these can also be escaped
58 /// as `\s`.
59 ///
60 /// Key files can store strings (possibly with localized variants), integers,
61 /// booleans and lists of these. Lists are separated by a separator character,
62 /// typically `;` or `,`. To use the list separator character in a value in
63 /// a list, it has to be escaped by prefixing it with a backslash.
64 ///
65 /// This syntax is obviously inspired by the .ini files commonly met
66 /// on Windows, but there are some important differences:
67 ///
68 /// - .ini files use the `;` character to begin comments,
69 /// key files use the `#` character.
70 ///
71 /// - Key files do not allow for ungrouped keys meaning only
72 /// comments can precede the first group.
73 ///
74 /// - Key files are always encoded in UTF-8.
75 ///
76 /// - Key and Group names are case-sensitive. For example, a group called
77 /// `[GROUP]` is a different from `[group]`.
78 ///
79 /// - .ini files don’t have a strongly typed boolean entry type,
80 /// they only have `GetProfileInt()`. In key files, only
81 /// `true` and `false` (in lower case) are allowed.
82 ///
83 /// Note that in contrast to the
84 /// [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/latest/),
85 /// groups in key files may contain the same key multiple times; the last entry wins.
86 /// Key files may also contain multiple groups with the same name; they are merged
87 /// together. Another difference is that keys and group names in key files are not
88 /// restricted to ASCII characters.
89 ///
90 /// Here is an example of loading a key file and reading a value:
91 ///
92 /// **⚠️ The following code is in c ⚠️**
93 ///
94 /// ```c
95 /// g_autoptr(GError) error = NULL;
96 /// g_autoptr(GKeyFile) key_file = g_key_file_new ();
97 ///
98 /// if (!g_key_file_load_from_file (key_file, "key-file.ini", flags, &error))
99 /// {
100 /// if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
101 /// g_warning ("Error loading key file: %s", error->message);
102 /// return;
103 /// }
104 ///
105 /// g_autofree gchar *val = g_key_file_get_string (key_file, "Group Name", "SomeKey", &error);
106 /// if (val == NULL &&
107 /// !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
108 /// {
109 /// g_warning ("Error finding key in key file: %s", error->message);
110 /// return;
111 /// }
112 /// else if (val == NULL)
113 /// {
114 /// // Fall back to a default value.
115 /// val = g_strdup ("default-value");
116 /// }
117 /// ```
118 ///
119 /// Here is an example of creating and saving a key file:
120 ///
121 /// **⚠️ The following code is in c ⚠️**
122 ///
123 /// ```c
124 /// g_autoptr(GKeyFile) key_file = g_key_file_new ();
125 /// const gchar *val = …;
126 /// g_autoptr(GError) error = NULL;
127 ///
128 /// g_key_file_set_string (key_file, "Group Name", "SomeKey", val);
129 ///
130 /// // Save as a file.
131 /// if (!g_key_file_save_to_file (key_file, "key-file.ini", &error))
132 /// {
133 /// g_warning ("Error saving key file: %s", error->message);
134 /// return;
135 /// }
136 ///
137 /// // Or store to a GBytes for use elsewhere.
138 /// gsize data_len;
139 /// g_autofree guint8 *data = (guint8 *) g_key_file_to_data (key_file, &data_len, &error);
140 /// if (data == NULL)
141 /// {
142 /// g_warning ("Error saving key file: %s", error->message);
143 /// return;
144 /// }
145 /// g_autoptr(GBytes) bytes = g_bytes_new_take (g_steal_pointer (&data), data_len);
146 /// ```
147 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
148 pub struct KeyFile(Shared<ffi::GKeyFile>);
149
150 match fn {
151 ref => |ptr| ffi::g_key_file_ref(ptr),
152 unref => |ptr| ffi::g_key_file_unref(ptr),
153 type_ => || ffi::g_key_file_get_type(),
154 }
155}
156
157impl KeyFile {
158 /// Creates a new empty [`KeyFile`][crate::KeyFile] object.
159 ///
160 /// Use [`load_from_file()`][Self::load_from_file()],
161 /// [`load_from_data()`][Self::load_from_data()], [`load_from_dirs()`][Self::load_from_dirs()] or
162 /// [`load_from_data_dirs()`][Self::load_from_data_dirs()] to
163 /// read an existing key file.
164 ///
165 /// # Returns
166 ///
167 /// an empty [`KeyFile`][crate::KeyFile].
168 #[doc(alias = "g_key_file_new")]
169 pub fn new() -> KeyFile {
170 unsafe { from_glib_full(ffi::g_key_file_new()) }
171 }
172
173 /// Retrieves a comment above @key from @group_name.
174 ///
175 /// If @key is `NULL` then @comment will be read from above
176 /// @group_name. If both @key and @group_name are `NULL`, then
177 /// @comment will be read from above the first group in the file.
178 ///
179 /// Note that the returned string does not include the `#` comment markers,
180 /// but does include any whitespace after them (on each line). It includes
181 /// the line breaks between lines, but does not include the final line break.
182 /// ## `group_name`
183 /// a group name, or `NULL` to get a top-level comment
184 /// ## `key`
185 /// a key, or `NULL` to get a group comment
186 ///
187 /// # Returns
188 ///
189 /// a comment that should be freed with `free()`
190 #[doc(alias = "g_key_file_get_comment")]
191 #[doc(alias = "get_comment")]
192 pub fn comment(
193 &self,
194 group_name: Option<&str>,
195 key: Option<&str>,
196 ) -> Result<crate::GString, crate::Error> {
197 unsafe {
198 let mut error = std::ptr::null_mut();
199 let ret = ffi::g_key_file_get_comment(
200 self.to_glib_none().0,
201 group_name.to_glib_none().0,
202 key.to_glib_none().0,
203 &mut error,
204 );
205 if error.is_null() {
206 Ok(from_glib_full(ret))
207 } else {
208 Err(from_glib_full(error))
209 }
210 }
211 }
212
213 /// Returns the value associated with @key under @group_name as a double.
214 ///
215 /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
216 /// returned. Likewise, if the value associated with @key cannot be interpreted
217 /// as a double then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
218 /// ## `group_name`
219 /// a group name
220 /// ## `key`
221 /// a key
222 ///
223 /// # Returns
224 ///
225 /// the value associated with the key as a double, or
226 /// `0.0` if the key was not found or could not be parsed.
227 #[doc(alias = "g_key_file_get_double")]
228 #[doc(alias = "get_double")]
229 pub fn double(&self, group_name: &str, key: &str) -> Result<f64, crate::Error> {
230 unsafe {
231 let mut error = std::ptr::null_mut();
232 let ret = ffi::g_key_file_get_double(
233 self.to_glib_none().0,
234 group_name.to_glib_none().0,
235 key.to_glib_none().0,
236 &mut error,
237 );
238 if error.is_null() {
239 Ok(ret)
240 } else {
241 Err(from_glib_full(error))
242 }
243 }
244 }
245
246 /// Returns the values associated with @key under @group_name as
247 /// doubles.
248 ///
249 /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
250 /// returned. Likewise, if the values associated with @key cannot be interpreted
251 /// as doubles then [error@GLib.KeyFileError.INVALID_VALUE] is returned.
252 /// ## `group_name`
253 /// a group name
254 /// ## `key`
255 /// a key
256 ///
257 /// # Returns
258 ///
259 ///
260 /// the values associated with the key as a list of doubles, or `NULL` if the
261 /// key was not found or could not be parsed. The returned list of doubles
262 /// should be freed with `free()` when no longer needed.
263 #[doc(alias = "g_key_file_get_double_list")]
264 #[doc(alias = "get_double_list")]
265 pub fn double_list(&self, group_name: &str, key: &str) -> Result<Vec<f64>, crate::Error> {
266 unsafe {
267 let mut length = std::mem::MaybeUninit::uninit();
268 let mut error = std::ptr::null_mut();
269 let ret = ffi::g_key_file_get_double_list(
270 self.to_glib_none().0,
271 group_name.to_glib_none().0,
272 key.to_glib_none().0,
273 length.as_mut_ptr(),
274 &mut error,
275 );
276 if error.is_null() {
277 Ok(FromGlibContainer::from_glib_container_num(
278 ret,
279 length.assume_init() as _,
280 ))
281 } else {
282 Err(from_glib_full(error))
283 }
284 }
285 }
286
287 /// Returns the value associated with @key under @group_name as a signed
288 /// 64-bit integer.
289 ///
290 /// This is similar to [`integer()`][Self::integer()] but can return
291 /// 64-bit results without truncation.
292 /// ## `group_name`
293 /// a group name
294 /// ## `key`
295 /// a key
296 ///
297 /// # Returns
298 ///
299 /// the value associated with the key as a signed 64-bit integer, or
300 /// `0` if the key was not found or could not be parsed.
301 #[doc(alias = "g_key_file_get_int64")]
302 #[doc(alias = "get_int64")]
303 pub fn int64(&self, group_name: &str, key: &str) -> Result<i64, crate::Error> {
304 unsafe {
305 let mut error = std::ptr::null_mut();
306 let ret = ffi::g_key_file_get_int64(
307 self.to_glib_none().0,
308 group_name.to_glib_none().0,
309 key.to_glib_none().0,
310 &mut error,
311 );
312 if error.is_null() {
313 Ok(ret)
314 } else {
315 Err(from_glib_full(error))
316 }
317 }
318 }
319
320 /// Returns the value associated with @key under @group_name as an
321 /// integer.
322 ///
323 /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
324 /// returned. Likewise, if the value associated with @key cannot be interpreted
325 /// as an integer, or is out of range for a `gint`, then
326 /// [error@GLib.KeyFileError.INVALID_VALUE] is returned.
327 /// ## `group_name`
328 /// a group name
329 /// ## `key`
330 /// a key
331 ///
332 /// # Returns
333 ///
334 /// the value associated with the key as an integer, or
335 /// `0` if the key was not found or could not be parsed.
336 #[doc(alias = "g_key_file_get_integer")]
337 #[doc(alias = "get_integer")]
338 pub fn integer(&self, group_name: &str, key: &str) -> Result<i32, crate::Error> {
339 unsafe {
340 let mut error = std::ptr::null_mut();
341 let ret = ffi::g_key_file_get_integer(
342 self.to_glib_none().0,
343 group_name.to_glib_none().0,
344 key.to_glib_none().0,
345 &mut error,
346 );
347 if error.is_null() {
348 Ok(ret)
349 } else {
350 Err(from_glib_full(error))
351 }
352 }
353 }
354
355 /// Returns the values associated with @key under @group_name as
356 /// integers.
357 ///
358 /// If @key cannot be found then [error@GLib.KeyFileError.KEY_NOT_FOUND] is
359 /// returned. Likewise, if the values associated with @key cannot be interpreted
360 /// as integers, or are out of range for `gint`, then
361 /// [error@GLib.KeyFileError.INVALID_VALUE] is returned.
362 /// ## `group_name`
363 /// a group name
364 /// ## `key`
365 /// a key
366 ///
367 /// # Returns
368 ///
369 ///
370 /// the values associated with the key as a list of integers, or `NULL` if
371 /// the key was not found or could not be parsed. The returned list of
372 /// integers should be freed with `free()` when no longer needed.
373 #[doc(alias = "g_key_file_get_integer_list")]
374 #[doc(alias = "get_integer_list")]
375 pub fn integer_list(&self, group_name: &str, key: &str) -> Result<Vec<i32>, crate::Error> {
376 unsafe {
377 let mut length = std::mem::MaybeUninit::uninit();
378 let mut error = std::ptr::null_mut();
379 let ret = ffi::g_key_file_get_integer_list(
380 self.to_glib_none().0,
381 group_name.to_glib_none().0,
382 key.to_glib_none().0,
383 length.as_mut_ptr(),
384 &mut error,
385 );
386 if error.is_null() {
387 Ok(FromGlibContainer::from_glib_container_num(
388 ret,
389 length.assume_init() as _,
390 ))
391 } else {
392 Err(from_glib_full(error))
393 }
394 }
395 }
396
397 /// Returns the actual locale which the result of
398 /// [`locale_string()`][Self::locale_string()] or
399 /// [`locale_string_list()`][Self::locale_string_list()] came from.
400 ///
401 /// If calling [`locale_string()`][Self::locale_string()] or
402 /// [`locale_string_list()`][Self::locale_string_list()] with exactly the same @self,
403 /// @group_name, @key and @locale, the result of those functions will
404 /// have originally been tagged with the locale that is the result of
405 /// this function.
406 /// ## `group_name`
407 /// a group name
408 /// ## `key`
409 /// a key
410 /// ## `locale`
411 /// a locale identifier or `NULL` to use the current locale
412 ///
413 /// # Returns
414 ///
415 /// the locale from the file, or `NULL` if the key was not
416 /// found or the entry in the file was was untranslated
417 #[doc(alias = "g_key_file_get_locale_for_key")]
418 #[doc(alias = "get_locale_for_key")]
419 pub fn locale_for_key(
420 &self,
421 group_name: &str,
422 key: &str,
423 locale: Option<&str>,
424 ) -> Option<crate::GString> {
425 unsafe {
426 from_glib_full(ffi::g_key_file_get_locale_for_key(
427 self.to_glib_none().0,
428 group_name.to_glib_none().0,
429 key.to_glib_none().0,
430 locale.to_glib_none().0,
431 ))
432 }
433 }
434
435 /// Returns the name of the start group of the file.
436 ///
437 /// # Returns
438 ///
439 /// The start group of the key file.
440 #[doc(alias = "g_key_file_get_start_group")]
441 #[doc(alias = "get_start_group")]
442 pub fn start_group(&self) -> Option<crate::GString> {
443 unsafe { from_glib_full(ffi::g_key_file_get_start_group(self.to_glib_none().0)) }
444 }
445
446 /// Returns the value associated with @key under @group_name as an unsigned
447 /// 64-bit integer.
448 ///
449 /// This is similar to [`integer()`][Self::integer()] but can return
450 /// large positive results without truncation.
451 /// ## `group_name`
452 /// a group name
453 /// ## `key`
454 /// a key
455 ///
456 /// # Returns
457 ///
458 /// the value associated with the key as an unsigned 64-bit integer,
459 /// or `0` if the key was not found or could not be parsed.
460 #[doc(alias = "g_key_file_get_uint64")]
461 #[doc(alias = "get_uint64")]
462 pub fn uint64(&self, group_name: &str, key: &str) -> Result<u64, crate::Error> {
463 unsafe {
464 let mut error = std::ptr::null_mut();
465 let ret = ffi::g_key_file_get_uint64(
466 self.to_glib_none().0,
467 group_name.to_glib_none().0,
468 key.to_glib_none().0,
469 &mut error,
470 );
471 if error.is_null() {
472 Ok(ret)
473 } else {
474 Err(from_glib_full(error))
475 }
476 }
477 }
478
479 /// Returns the raw value associated with @key under @group_name.
480 ///
481 /// Use [`string()`][Self::string()] to retrieve an unescaped UTF-8 string.
482 ///
483 /// If the key cannot be found, [error@GLib.KeyFileError.KEY_NOT_FOUND]
484 /// is returned. If the @group_name cannot be found,
485 /// [error@GLib.KeyFileError.GROUP_NOT_FOUND] is returned.
486 /// ## `group_name`
487 /// a group name
488 /// ## `key`
489 /// a key
490 ///
491 /// # Returns
492 ///
493 /// a newly allocated string or `NULL` if the specified
494 /// key cannot be found.
495 #[doc(alias = "g_key_file_get_value")]
496 #[doc(alias = "get_value")]
497 pub fn value(&self, group_name: &str, key: &str) -> Result<crate::GString, crate::Error> {
498 unsafe {
499 let mut error = std::ptr::null_mut();
500 let ret = ffi::g_key_file_get_value(
501 self.to_glib_none().0,
502 group_name.to_glib_none().0,
503 key.to_glib_none().0,
504 &mut error,
505 );
506 if error.is_null() {
507 Ok(from_glib_full(ret))
508 } else {
509 Err(from_glib_full(error))
510 }
511 }
512 }
513
514 /// Looks whether the key file has the group @group_name.
515 /// ## `group_name`
516 /// a group name
517 ///
518 /// # Returns
519 ///
520 /// true if @group_name is a part of @self, false otherwise.
521 #[doc(alias = "g_key_file_has_group")]
522 pub fn has_group(&self, group_name: &str) -> bool {
523 unsafe {
524 from_glib(ffi::g_key_file_has_group(
525 self.to_glib_none().0,
526 group_name.to_glib_none().0,
527 ))
528 }
529 }
530
531 /// Loads a key file from the data in @bytes into an empty [`KeyFile`][crate::KeyFile]
532 /// structure.
533 ///
534 /// If the object cannot be created then a [`KeyFileError`][crate::KeyFileError] is returned.
535 /// ## `bytes`
536 /// a [`Bytes`][crate::Bytes]
537 /// ## `flags`
538 /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
539 ///
540 /// # Returns
541 ///
542 /// true if a key file could be loaded, false otherwise
543 #[doc(alias = "g_key_file_load_from_bytes")]
544 pub fn load_from_bytes(&self, bytes: &Bytes, flags: KeyFileFlags) -> Result<(), crate::Error> {
545 unsafe {
546 let mut error = std::ptr::null_mut();
547 let is_ok = ffi::g_key_file_load_from_bytes(
548 self.to_glib_none().0,
549 bytes.to_glib_none().0,
550 flags.into_glib(),
551 &mut error,
552 );
553 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
554 if error.is_null() {
555 Ok(())
556 } else {
557 Err(from_glib_full(error))
558 }
559 }
560 }
561
562 /// Loads a key file from memory into an empty [`KeyFile`][crate::KeyFile] structure.
563 ///
564 /// If the object cannot be created then a [`KeyFileError`][crate::KeyFileError] is returned.
565 /// ## `data`
566 /// key file loaded in memory
567 /// ## `length`
568 /// the length of @data in bytes (or `(gsize)-1` if data is nul-terminated)
569 /// ## `flags`
570 /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
571 ///
572 /// # Returns
573 ///
574 /// true if a key file could be loaded, false otherwise
575 #[doc(alias = "g_key_file_load_from_data")]
576 pub fn load_from_data(&self, data: &str, flags: KeyFileFlags) -> Result<(), crate::Error> {
577 let length = data.len() as _;
578 unsafe {
579 let mut error = std::ptr::null_mut();
580 let is_ok = ffi::g_key_file_load_from_data(
581 self.to_glib_none().0,
582 data.to_glib_none().0,
583 length,
584 flags.into_glib(),
585 &mut error,
586 );
587 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
588 if error.is_null() {
589 Ok(())
590 } else {
591 Err(from_glib_full(error))
592 }
593 }
594 }
595
596 /// Loads a key file into an empty [`KeyFile`][crate::KeyFile] structure.
597 ///
598 /// If the OS returns an error when opening or reading the file, a
599 /// [`FileError`][crate::FileError] is returned. If there is a problem parsing the file,
600 /// a [`KeyFileError`][crate::KeyFileError] is returned.
601 ///
602 /// This function will never return a [error@GLib.KeyFileError.NOT_FOUND]
603 /// error. If the @file is not found, [error@GLib.FileError.NOENT] is returned.
604 /// ## `file`
605 /// the path of a filename to load, in the GLib filename encoding
606 /// ## `flags`
607 /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
608 ///
609 /// # Returns
610 ///
611 /// true if a key file could be loaded, false otherwise
612 #[doc(alias = "g_key_file_load_from_file")]
613 pub fn load_from_file(
614 &self,
615 file: impl AsRef<std::path::Path>,
616 flags: KeyFileFlags,
617 ) -> Result<(), crate::Error> {
618 unsafe {
619 let mut error = std::ptr::null_mut();
620 let is_ok = ffi::g_key_file_load_from_file(
621 self.to_glib_none().0,
622 file.as_ref().to_glib_none().0,
623 flags.into_glib(),
624 &mut error,
625 );
626 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
627 if error.is_null() {
628 Ok(())
629 } else {
630 Err(from_glib_full(error))
631 }
632 }
633 }
634
635 /// Evaluates and merges configuration key/values from multiple Unix directories into a single key file.
636 ///
637 /// This function reads and merges all available configuration files based on the rules defined by
638 /// the [UAPI Configuration Files Specification](https://github.com/uapi-group/specifications/blob/main/specs/configuration_files_specification.md) (version 1).
639 ///
640 /// This API is primarily intended for system daemons or CLI tools that need to load systemd-style
641 /// configuration files spread across vendor and customization directories. User applications
642 /// should generally use [`GSettings`](../gio/class.Settings.html) instead to manage user preferences.
643 ///
644 /// ### Directory Layout Guidance
645 /// When choosing paths for @etc_subdir and @usr_subdir, you should prefer using your build
646 /// system's standard configuration variables (such as `$sysconfdir` and `$libdir`) rather
647 /// than hard-coding absolute paths. For context, on a standard Linux layout, @etc_subdir
648 /// typically points to administrative overrides (e.g., `/etc`), @run_subdir to /run while
649 /// @usr_subdir points to the vendor defaults (e.g., `/usr/lib` or `/usr/share`). Passing `NULL`
650 /// will fall back to platform-specific defaults where appropriate.
651 ///
652 /// ### Relationship to XDG Base Directory Specification
653 /// Note that this function operates independently of the
654 /// [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir/latest/)
655 /// and [`system_config_dirs()`][crate::system_config_dirs()]. While XDG directories (like `$XDG_CONFIG_DIRS`)
656 /// are intended to manage desktop session applications and user-facing environments, this
657 /// API is strictly designed for low-level system-wide components following the UAPI
658 /// specification. Mixing the two concepts should be avoided.
659 ///
660 /// Note that this function is synchronous and blocking. Because it may load an arbitrary amount
661 /// of files, it is best suited for application startup or non-interactive environments. If called
662 /// from a user-interactive UI thread, you must handle asynchronicity yourself if needed.
663 ///
664 /// If no file for parsing has been found, [error@GLib.KeyFileError.NOT_FOUND] is returned.
665 /// If files have been found but the OS returns an error when opening or reading a
666 /// file, a [`FileError`][crate::FileError] is returned. If there is a problem parsing
667 /// files, a [`KeyFileError`][crate::KeyFileError] is returned.
668 ///
669 ///
670 /// The following example parses files in following order:
671 ///
672 /// - `<SYSCONFDIR>/project/mydaemon.conf`
673 /// - `/run/project/mydaemon.conf` (if <SYSCONFDIR>/project/mydaemon.conf is not defined)
674 /// - `<LIBDIR>/project/mydaemon.conf`
675 /// (if `<SYSCONFDIR>/project/mydaemon.conf` and `/run/project/mydaemon.conf are not defined`)
676 /// - valid drop-ins in `<SYSCONFDIR>/project/mydaemon.conf.d/`, `/run/project/mydaemon.conf.d/`, `<LIBDIR>/project/mydaemon.conf.d/`
677 ///
678 /// ```text
679 /// g_autoptr(GKeyFile) kf = g_key_file_new ();
680 /// g_autoptr(GError) local_error = NULL;
681 ///
682 /// // Using build-configured paths or defaults instead of hardcoded strings
683 /// gboolean success = g_key_file_load_unix_configurations (kf,
684 /// "my-daemon",
685 /// SYSCONFDIR,
686 /// RUNDIR,
687 /// LIBDIR,
688 /// "mydaemon",
689 /// "conf",
690 /// G_KEY_FILE_NONE,
691 /// &local_error);
692 /// if (!success)
693 /// {
694 /// g_warning ("Failed to load configuration: %s", local_error->message);
695 /// return;
696 /// }
697 ///
698 /// g_autofree char *val = g_key_file_get_string (kf, "Management", "Setting", NULL);
699 /// ```
700 /// ## `project`
701 /// name of the project used as subdirectory
702 /// ## `etc_subdir`
703 /// directory path for administrative configuration files
704 /// ## `run_subdir`
705 /// directory path for ephemeral overrides
706 /// ## `usr_subdir`
707 /// directory path for vendor-defined settings
708 /// ## `config_name`
709 /// basename of the configuration file
710 /// ## `config_suffix`
711 /// suffix of the configuration file
712 /// ## `flags`
713 /// flags from [`KeyFileFlags`][crate::KeyFileFlags]
714 ///
715 /// # Returns
716 ///
717 /// true on success, false otherwise
718 #[cfg(feature = "v2_90")]
719 #[cfg_attr(docsrs, doc(cfg(feature = "v2_90")))]
720 #[doc(alias = "g_key_file_load_unix_configurations")]
721 pub fn load_unix_configurations(
722 &self,
723 project: Option<&str>,
724 etc_subdir: Option<impl AsRef<std::path::Path>>,
725 run_subdir: Option<impl AsRef<std::path::Path>>,
726 usr_subdir: Option<impl AsRef<std::path::Path>>,
727 config_name: impl AsRef<std::path::Path>,
728 config_suffix: Option<impl AsRef<std::path::Path>>,
729 flags: KeyFileFlags,
730 ) -> Result<(), crate::Error> {
731 unsafe {
732 let mut error = std::ptr::null_mut();
733 let is_ok = ffi::g_key_file_load_unix_configurations(
734 self.to_glib_none().0,
735 project.to_glib_none().0,
736 etc_subdir.as_ref().map(|p| p.as_ref()).to_glib_none().0,
737 run_subdir.as_ref().map(|p| p.as_ref()).to_glib_none().0,
738 usr_subdir.as_ref().map(|p| p.as_ref()).to_glib_none().0,
739 config_name.as_ref().to_glib_none().0,
740 config_suffix.as_ref().map(|p| p.as_ref()).to_glib_none().0,
741 flags.into_glib(),
742 &mut error,
743 );
744 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
745 if error.is_null() {
746 Ok(())
747 } else {
748 Err(from_glib_full(error))
749 }
750 }
751 }
752
753 /// Removes a comment above @key from @group_name.
754 ///
755 /// If @key is `NULL` then @comment will be removed above @group_name.
756 /// If both @key and @group_name are `NULL`, then @comment will
757 /// be removed above the first group in the file.
758 /// ## `group_name`
759 /// a group name, or `NULL` to get a top-level comment
760 /// ## `key`
761 /// a key, or `NULL` to get a group comment
762 ///
763 /// # Returns
764 ///
765 /// true if the comment was removed, false otherwise
766 #[doc(alias = "g_key_file_remove_comment")]
767 pub fn remove_comment(
768 &self,
769 group_name: Option<&str>,
770 key: Option<&str>,
771 ) -> Result<(), crate::Error> {
772 unsafe {
773 let mut error = std::ptr::null_mut();
774 let is_ok = ffi::g_key_file_remove_comment(
775 self.to_glib_none().0,
776 group_name.to_glib_none().0,
777 key.to_glib_none().0,
778 &mut error,
779 );
780 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
781 if error.is_null() {
782 Ok(())
783 } else {
784 Err(from_glib_full(error))
785 }
786 }
787 }
788
789 /// Removes the specified group, @group_name,
790 /// from the key file.
791 /// ## `group_name`
792 /// a group name
793 ///
794 /// # Returns
795 ///
796 /// true if the group was removed, false otherwise
797 #[doc(alias = "g_key_file_remove_group")]
798 pub fn remove_group(&self, group_name: &str) -> Result<(), crate::Error> {
799 unsafe {
800 let mut error = std::ptr::null_mut();
801 let is_ok = ffi::g_key_file_remove_group(
802 self.to_glib_none().0,
803 group_name.to_glib_none().0,
804 &mut error,
805 );
806 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
807 if error.is_null() {
808 Ok(())
809 } else {
810 Err(from_glib_full(error))
811 }
812 }
813 }
814
815 /// Removes @key in @group_name from the key file.
816 /// ## `group_name`
817 /// a group name
818 /// ## `key`
819 /// a key name to remove
820 ///
821 /// # Returns
822 ///
823 /// true if the key was removed, false otherwise
824 #[doc(alias = "g_key_file_remove_key")]
825 pub fn remove_key(&self, group_name: &str, key: &str) -> Result<(), crate::Error> {
826 unsafe {
827 let mut error = std::ptr::null_mut();
828 let is_ok = ffi::g_key_file_remove_key(
829 self.to_glib_none().0,
830 group_name.to_glib_none().0,
831 key.to_glib_none().0,
832 &mut error,
833 );
834 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
835 if error.is_null() {
836 Ok(())
837 } else {
838 Err(from_glib_full(error))
839 }
840 }
841 }
842
843 /// Associates a new boolean value with @key under @group_name.
844 ///
845 /// If @key cannot be found then it is created.
846 /// ## `group_name`
847 /// a group name
848 /// ## `key`
849 /// a key
850 /// ## `value`
851 /// true or false
852 #[doc(alias = "g_key_file_set_boolean")]
853 pub fn set_boolean(&self, group_name: &str, key: &str, value: bool) {
854 unsafe {
855 ffi::g_key_file_set_boolean(
856 self.to_glib_none().0,
857 group_name.to_glib_none().0,
858 key.to_glib_none().0,
859 value.into_glib(),
860 );
861 }
862 }
863
864 //#[doc(alias = "g_key_file_set_boolean_list")]
865 //pub fn set_boolean_list(&self, group_name: &str, key: &str, list: /*Unimplemented*/&CArray TypeId { ns_id: 0, id: 1 }) {
866 // unsafe { TODO: call ffi:g_key_file_set_boolean_list() }
867 //}
868
869 /// Places a comment above @key from @group_name.
870 ///
871 /// If @key is `NULL` then @comment will be written above @group_name.
872 /// If both @key and @group_name are `NULL`, then @comment will be
873 /// written above the first group in the file.
874 ///
875 /// Passing a non-existent @group_name or @key to this function returns
876 /// false and populates @error. (In contrast, passing a non-existent
877 /// `group_name` or `key` to [`set_string()`][Self::set_string()]
878 /// creates the associated group name and key.)
879 ///
880 /// Note that this function prepends a `#` comment marker to
881 /// each line of @comment.
882 /// ## `group_name`
883 /// a group name, or `NULL` to write a top-level comment
884 /// ## `key`
885 /// a key, or `NULL` to write a group comment
886 /// ## `comment`
887 /// a comment
888 ///
889 /// # Returns
890 ///
891 /// true if the comment was written, false otherwise
892 #[doc(alias = "g_key_file_set_comment")]
893 pub fn set_comment(
894 &self,
895 group_name: Option<&str>,
896 key: Option<&str>,
897 comment: &str,
898 ) -> Result<(), crate::Error> {
899 unsafe {
900 let mut error = std::ptr::null_mut();
901 let is_ok = ffi::g_key_file_set_comment(
902 self.to_glib_none().0,
903 group_name.to_glib_none().0,
904 key.to_glib_none().0,
905 comment.to_glib_none().0,
906 &mut error,
907 );
908 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
909 if error.is_null() {
910 Ok(())
911 } else {
912 Err(from_glib_full(error))
913 }
914 }
915 }
916
917 /// Associates a new double value with @key under @group_name.
918 ///
919 /// If @key cannot be found then it is created.
920 /// ## `group_name`
921 /// a group name
922 /// ## `key`
923 /// a key
924 /// ## `value`
925 /// a double value
926 #[doc(alias = "g_key_file_set_double")]
927 pub fn set_double(&self, group_name: &str, key: &str, value: f64) {
928 unsafe {
929 ffi::g_key_file_set_double(
930 self.to_glib_none().0,
931 group_name.to_glib_none().0,
932 key.to_glib_none().0,
933 value,
934 );
935 }
936 }
937
938 /// Associates a new integer value with @key under @group_name.
939 ///
940 /// If @key cannot be found then it is created.
941 /// ## `group_name`
942 /// a group name
943 /// ## `key`
944 /// a key
945 /// ## `value`
946 /// an integer value
947 #[doc(alias = "g_key_file_set_int64")]
948 pub fn set_int64(&self, group_name: &str, key: &str, value: i64) {
949 unsafe {
950 ffi::g_key_file_set_int64(
951 self.to_glib_none().0,
952 group_name.to_glib_none().0,
953 key.to_glib_none().0,
954 value,
955 );
956 }
957 }
958
959 /// Associates a new integer value with @key under @group_name.
960 ///
961 /// If @key cannot be found then it is created.
962 /// ## `group_name`
963 /// a group name
964 /// ## `key`
965 /// a key
966 /// ## `value`
967 /// an integer value
968 #[doc(alias = "g_key_file_set_integer")]
969 pub fn set_integer(&self, group_name: &str, key: &str, value: i32) {
970 unsafe {
971 ffi::g_key_file_set_integer(
972 self.to_glib_none().0,
973 group_name.to_glib_none().0,
974 key.to_glib_none().0,
975 value,
976 );
977 }
978 }
979
980 /// Sets the character which is used to separate values in lists.
981 ///
982 /// Typically `;` or `,` are used as separators. The default list separator
983 /// is `;`.
984 /// ## `separator`
985 /// the separator
986 #[doc(alias = "g_key_file_set_list_separator")]
987 pub fn set_list_separator(&self, separator: crate::Char) {
988 unsafe {
989 ffi::g_key_file_set_list_separator(self.to_glib_none().0, separator.into_glib());
990 }
991 }
992
993 /// Associates a string value for @key and @locale under @group_name.
994 ///
995 /// If the translation for @key cannot be found then it is created.
996 ///
997 /// If @locale is `C` then the untranslated value is set (since GLib 2.84).
998 /// ## `group_name`
999 /// a group name
1000 /// ## `key`
1001 /// a key
1002 /// ## `locale`
1003 /// a locale identifier
1004 /// ## `string`
1005 /// a string
1006 #[doc(alias = "g_key_file_set_locale_string")]
1007 pub fn set_locale_string(&self, group_name: &str, key: &str, locale: &str, string: &str) {
1008 unsafe {
1009 ffi::g_key_file_set_locale_string(
1010 self.to_glib_none().0,
1011 group_name.to_glib_none().0,
1012 key.to_glib_none().0,
1013 locale.to_glib_none().0,
1014 string.to_glib_none().0,
1015 );
1016 }
1017 }
1018
1019 /// Associates a new string value with @key under @group_name.
1020 ///
1021 /// If @key cannot be found then it is created.
1022 /// If @group_name cannot be found then it is created.
1023 /// Unlike [`set_value()`][Self::set_value()], this function handles characters
1024 /// that need escaping, such as newlines.
1025 /// ## `group_name`
1026 /// a group name
1027 /// ## `key`
1028 /// a key
1029 /// ## `string`
1030 /// a string
1031 #[doc(alias = "g_key_file_set_string")]
1032 pub fn set_string(&self, group_name: &str, key: &str, string: &str) {
1033 unsafe {
1034 ffi::g_key_file_set_string(
1035 self.to_glib_none().0,
1036 group_name.to_glib_none().0,
1037 key.to_glib_none().0,
1038 string.to_glib_none().0,
1039 );
1040 }
1041 }
1042
1043 /// Associates a new integer value with @key under @group_name.
1044 ///
1045 /// If @key cannot be found then it is created.
1046 /// ## `group_name`
1047 /// a group name
1048 /// ## `key`
1049 /// a key
1050 /// ## `value`
1051 /// an integer value
1052 #[doc(alias = "g_key_file_set_uint64")]
1053 pub fn set_uint64(&self, group_name: &str, key: &str, value: u64) {
1054 unsafe {
1055 ffi::g_key_file_set_uint64(
1056 self.to_glib_none().0,
1057 group_name.to_glib_none().0,
1058 key.to_glib_none().0,
1059 value,
1060 );
1061 }
1062 }
1063
1064 /// Associates a new value with @key under @group_name.
1065 ///
1066 /// If @key cannot be found then it is created. If @group_name cannot
1067 /// be found then it is created. To set an UTF-8 string which may contain
1068 /// characters that need escaping (such as newlines or spaces), use
1069 /// [`set_string()`][Self::set_string()].
1070 /// ## `group_name`
1071 /// a group name
1072 /// ## `key`
1073 /// a key
1074 /// ## `value`
1075 /// a string
1076 #[doc(alias = "g_key_file_set_value")]
1077 pub fn set_value(&self, group_name: &str, key: &str, value: &str) {
1078 unsafe {
1079 ffi::g_key_file_set_value(
1080 self.to_glib_none().0,
1081 group_name.to_glib_none().0,
1082 key.to_glib_none().0,
1083 value.to_glib_none().0,
1084 );
1085 }
1086 }
1087}
1088
1089impl Default for KeyFile {
1090 fn default() -> Self {
1091 Self::new()
1092 }
1093}