// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600.  If not, see <https://www.gnu.org/licenses/>.

// Package prefs facilitates the storage of preferential values in the
// Gopher2600 system. It is a key/value system and is quite flexible. The most
// significant feature is the ability to only specify the preferences you are
// interested in for a given task. Loading and saving a preference will ignore
// and preserve values that haven't been added to the "Disk" type.
//
// The Disk type is the key resource in the package. First, create new a Disk
// instance with NewDisk(), specifying the location of the preferences file
// (using resources.ResourcePath() as necessary).
//
//	fn, _ := resources.ResourcePath(prefs.DefaultPrefsFile)
//	prf := prefs.NewDisk(fn)
//
// Preference value can then be added with the Add() function, specifying the
// "key" value. For clarity the key value should be similar to the name of the
// variable as used in the calling code, although this isn't required (note the
// restrictions on the key value in the documtation for the Add() function).
//
//	prf.Add("auto", &auto)
//
// Values that are added to the Disk type must use one of the preference types
// defined in this package. Currently, there are Bool, String and Int types and
// also a Generic type (unreleated to Go "generics").
//
// Once added to the disk object, preference values can be changed in the
// program in the normal way. Changes can be committed to disk with the
// Disk.Save() function and restored with Disk.Load().
//
// # Prefs valus and Multiple Disk Instances
//
// A prefs values can be added to more than one disk intance at once. Moreover,
// more than disk instance can point to the same file on disk.
//
// This is useful when only wanting to save a subset of prefs values. The
// values that are to be saved can be allocated to a limited disk object and be
// saved. Values that exist on the physical disk but which are missing from the
// limited disk object will be preserved.
//
// # Concurrency
//
// Generally, it is safe to access a prefs value from any goroutine. However,
// Set() should be used with care *if* SetHookPost() or SetHookPre() has been
// set for that value.
//
// # Command Line Support
//
// The *CommandLine*() functions are designed to help with the overriding of
// disk values with a value given on the command line. These values are added
// as a group with AddCommandLineGroup(). For example
//
//	AddCommandLineGroup("foo::bar; baz::qux")
//
// (see below for more detail about the format of the prefs string)
//
// These values are then looked up when preferences are first loaded by an
// instance of the Disk type. The command line value will be used instead of
// the saved value for the first load only. If Load() is never called then the
// command line value will not be used -- this shouldn't be an issue because it
// is good practice for Load() to always be called after the a set of prefs
// values have been added with the Add() function
//
// Commandline groups can be nested. Subsequent calls to AddCommandLineGroup()
// will hide the previous group until EndCommandLineGroup() is called.
//
// The prefs string used with AddCommandLineGroup() mirror the format of the
// preferences file except that entries are separated by semi-colons instead of
// newlines.
//
// For example, if the preferences file has the following entries:
//
//	a.b.c :: 100
//	d.e.f.g :: false
//	h.i :: wibble
//
// A valid string to use with AddCommandLineGroup() might be:
//
//	a.b.c::100; h.i::wibble
//
// Leading and trailing spaces around the key and value are stripped.
//
// # Note
//
// While saved preference files are stored in UTF-8 it is not a good idea for
// the files to be edited by hand. As such, manual editing is discorouaged with
// the warning at the top of the file:
//
//	*** do not edit this file by hand ***
//
// This also serves as the means of identification for the Load() function. ie.
// if this warning is not present then the Load() operation will fail.
package prefs
