Skip to content

Settings

Settings is a small named set of values a program reads at startup and writes back when it changes — the NSUserDefaults-shaped hole in the library. The store itself is memory; persistence is the platform’s own settings store or a text file, so the same source works on a Mac, on Windows, in a browser and on a machine with no filesystem at all.

#import "Settings.xc"

Three constructors, each a superset of the one before:

Settings.memory()in memory only. Every target, including those with no filesystem.
Settings.open(path)memory plus a file: read once here, rewritten whole by save.
Settings.standard(name)the platform’s own settings store (macOS and iOS preferences, the Windows registry, a browser’s localStorage), else open at the conventional per-user path, else memory.

Values are read with get (a String*, or null) or the typed getInt / getBool, each of which takes a fallback so a missing key needs no test. Writes go through set and its typed siblings; remove drops one key.

The store keeps insertion order, so serialise writes what was set, in the order it was set, and saving an unchanged store rewrites the same bytes.

Text, one setting per line:

# a comment
alpha = one
beta=two
  • # at the start of a line begins a comment; blank lines are ignored.
  • A line with no = is not a setting and is dropped.
  • Both sides of the = are trimmed.
  • A value cannot contain a newline; a key cannot contain = or #.

loadText reads that format and serialise writes it. Comments and blank lines are not preserved across a load-then-save: the file is a settings file, not a document.

When $XCC_SETTINGS_DIR is set and non-empty, standard keeps its values in the text file $XCC_SETTINGS_DIR/<name>.conf on every platform; a test or a script uses it to say exactly where the settings go. Otherwise the store is the platform’s:

PlatformStoreTo look at it
macOS, iOSthe user’s preferences, domain <name> (CFPreferences, what NSUserDefaults uses)defaults read <name>
Windowsthe registry key HKEY_CURRENT_USER\Software\<name>, one REG_SZ value per settingreg query HKCU\Software\<name>
a browser (wasm32)the page’s localStorage item <name>, a JSON object of stringsJSON.parse(localStorage.getItem(name))
Linux, Androidthe text file $XDG_CONFIG_HOME/<name>.conf, or $HOME/.config/<name>.conf when that is not setcat ~/.config/<name>.conf
arm9, m68kthe same text file when the target gives a home directory ($HOME); else a memory storethe file
xt6502none: a memory store, whose save returns false—

path is 0 for the three native stores and names the file for the others. On macOS a reverse-DNS name such as com.example.demo is the convention, as it is for any app’s preferences.

The platform stores hold only text, as Settings does. A value some other program put there as a number or a boolean (defaults write <name> k -int 3, a registry DWORD) reads back in decimal or as true/false. A value with no text form (an array, binary data) is not read, and save leaves it where it is.

Construction · memory · open · standard

Reading · get · has · getInt · getBool · count · keys

Writing · set · setInt · setBool · remove · removeAll

Persistence · path · serialise · loadText · save · reload


static Settings* memory(void)

A store with no backing file. It works everywhere, and save reports false because there is nowhere to write.

static Settings* open(String* path)

A store backed by path. An existing file is read now; a missing one is an empty store, not an error — the first save creates it. A null or empty path is the same as memory.

static Settings* standard(String* name)

The settings of an app called name, kept where this platform keeps them: see Where standard keeps the values. The rest of the API is the same whichever store is underneath.

Settings* s = Settings.standard(String.withCString("demo"));

↑ Topics

String* get(String* key)
String* get(String* key, String* fallback)

The value stored under key. The one-argument form returns 0 when the key is absent; the two-argument form returns fallback instead, so a default needs no test at the call site.

bool has(String* key)

true when key is present, whatever its value.

i32 getInt(String* key, i32 fallback)

The value parsed as a decimal integer. Returns fallback when the key is absent or the text is not an integer (a leading - or + is accepted). The stored text is not changed by reading it.

bool getBool(String* key, bool fallback)

The value as a boolean: true for true, yes or 1, false for false, no or 0, and fallback for anything else or an absent key.

u32 count(void)

How many settings are stored.

Array* keys(void)

A fresh Array of the keys, in insertion order.

↑ Topics

void set(String* key, String* value)

Stores value under key, replacing any previous value in place — the key keeps its original position. A null value stores the empty string; a null or empty key stores nothing.

void setInt(String* key, i32 value)

set with the value written out as a decimal.

void setBool(String* key, bool value)

set with the value written as true or false.

void remove(String* key)

Drops the setting, if it is there.

void removeAll(void)

Empties the store. The backing file is untouched until the next save.

↑ Topics

String* path(void)

The backing file, or 0 for a memory-only store or one kept in the platform’s own store (see standard).

String* serialise(void)

The whole store as file text — one key = value per line, in insertion order. This is exactly what save writes.

void loadText(String* text)

Replaces the store with what text says, in the format described in The file format. 0 empties the store.

bool save(void)

Writes the store out. A store from standard kept in the platform’s own store is written there: a key removed since it was read is removed there too, and the change is flushed. A file-backed store rewrites its file, first creating any directory above it that is missing, so the first save to ~/.config/<name>.conf works on a machine that has never had one. false when there is nowhere to write — a memory-only store, or a target with no filesystem — so a caller can say the settings did not persist instead of believing they did.

bool reload(void)

Re-reads the platform store or the backing file. The store is the truth: a file that has since gone leaves the store empty rather than stale. false when there is nothing to read from.

↑ Topics

  • Bundle: where a program’s files live, as opposed to where its values are kept.
  • FILE: the stdio-shaped stream layer — a FILE* for byte-at-a-time and seekable access.
  • String: every setting is read and written as one.