
README for the libPropList library

(c) Bjoern Giesler, July 1997


Abstract
========
========

This file documents the libPropList library, hereafter referred to as
PL. The library uses an opaque data type to represent a tree structure
made of strings, data blocks, arrays and dictionaries (key-value pair
lists). This structure can be manipulated, written out to and read in
from a file, and synchronized with the contents of a file.
The purpose of PL is to closely mimick the behaviour of the property
lists used in GNUstep/OPENSTEP (there formed with the NSString,
NSData, NSArray and NSDictionary classes) and to be compatible with
it. PL enables programs that use configuration or preference files to
make these compatible with GNUstep/OPENSTEP's user defaults handling
mechanism, without needing to use Objective-C or GNUstep/OPENSTEP
themselves.

The source code of PL contains several parts of the GNUstep base
library's source code (especially the parts that read and write string
descriptions and files). The GNUstep base library is covered by the
GNU Library Public License. The source code for the GNUstep base library
can be found at ftp://prep.ai.mit.edu/pub/gnu/gnustep. PL itself is
covered by the GNU Library Public License, as well. For more
information, read the file COPYING.LIB.




The proplist_t data type
========================
========================

The proplist_t data type is deliberately opaque (it is typedef'ed as a
pointer to void). It should not be accessed other than with the
library's commands.


The retain / release mechanism
==============================
==============================

The idea for this has been shamelessly nicked from OPENSTEP. Every
object maintains a retain count, which is set to 1 when the object is
created, increased every time it is retained (e.g. inserted in an
object or array) and decreased every time it is released. The purpose
of this is easier and more efficient memory handling. A few short
examples:

	proplist_t key, value, dict;
	key = PLMakeString("foo"); value = PLMakeString("bar");

	/* insert into array. key and value are retained */
	dict = PLMakeDictionaryFromEntries(key, value, NULL);
	/* release key and value (not needed here anymore) */
	PLRelease(key); PLRelease(value);

Releasing key and value after they have been inserted into dict makes
sure that when dict is released, key and value are destroyed.
If you want an object to stick around even after what brought it to
you has been destroyed, you can use something like

    void SomeFunction(proplist_t array)
      {
	static proplist_t permanent = 
            PLRetain(PLGetArrayElement(array, 0));
	...
      }

This makes sure that even after array has been released, the object
that permanent points to is retained. Once you don't need permanent
any more, you can release it, and it's physically destroyed (unless
it's retained somewhere else).


The library functions
=====================
=====================



File handling
=============

The routines described in this section are used to access disk files,
i.e. getting property lists stored in files, saving and synchronizing
them. The tilde notation (~/foo => $HOME/foo) is supported for file
names.

proplist_t PLGetProplistWithPath(const char *filename)
------------------------------------------------
Returns a property list read in from the specified file, or NULL if
there was an error. All the elements of the returned property list
have their filename reference set to the specified file. 

If filename is NULL or the empty string, the name of the file is set to
$GNUSTEP_USER_PATH/$GNUSTEP_DEFAULTS_FILE, with GNUSTEP_USER_PATH
defaulting to "~/GNUstep" and GNUSTEP_DEFAULTS_FILE defaulting to
"Defaults", if the environment variables aren't set. 

If filename contains a tilde as its first character, the tilde is
replaced with the user's home directory.

BOOL PLSynchronize(proplist_t pl)
---------------------------------
Synchronizes the property list with the file associated with
it. Returns YES if successful, NO if not. 

BOOL PLSave(proplist_t pl, BOOL atomically)
-------------------------------------------
Saves the property list in the file associated with it. If atomically
is YES, the function uses a temporary file to save the property list
into, then uses the rename() system call to move that file to the
final file. Returns YES if successful, NO if not.

proplist_t PLSetFilename(proplist_t pl, proplist_t filename)
-------------------------------------------------------
Sets the filename property of every element in the property list to
the string specified in filename. Returns the changed property list.

proplist_t PLGetFilename(proplist_t pl)
---------------------------------------
Returns the property list's filename property.



Talking to gsdd
===============

The routines described in this section are used to talk to the GNUstep
Defaults Daemon, gsdd. If that daemon is not already running, the
library will try to start it.

proplist_t PLGetDomainNames()
-----------------------------
Returns an array containing all registered domain names.

proplist_t PLGetDomain(proplist_t name)
---------------------------------------
Returns a property list representing the domain specified by name.

proplist_t PLSetDomain(proplist_t name, proplist_t value, BOOL kickme)
----------------------------------------------------------------------
Sets the specified value for the specified domain. If kickme is NO, a
callback the application registered for this domain will not be
called.

proplist_t PLDeleteDomain(proplist_t name, BOOL kickme)
-------------------------------------------------------
Deletes the specified domain. See above for the value of kickme.

proplist_t PLRegister(proplist_t name, plcallback_t callback)
-------------------------------------------------------------
Registers callback to be called whenever the domain associated with
name is changed. 

NOTE: The library only knows about a single callback. The reason for
this is that the daemon cannot tell a certain process which domain has
changed; it only registers that a process wants to be told if a
certain domain has changed (by sending it a signal). Therefore, you
have to specify the same callback on each call to PLRegister.

proplist_t PLUnregister(proplist_t name)
----------------------------------------
Unregister name; i.e. the callback will no longer be called if the
domain associated with name is changed.



Property list handling functions
================================

The routines in this section allow manipulation of property lists, and
converting between ASCII representations of property lists and the
lists themselves.

proplist_t PLGetProplistWithDescription(const char *description)
----------------------------------------------------------------
Returns a property list by parsing description, or NULL if there was
an error. description has to be in GNUstep/OPENSTEP property list
format.

BOOL PLIsString(proplist_t pl)
BOOL PLIsData(proplist_t pl)
BOOL PLIsArray(proplist_t pl)
BOOL PLIsDictionary(proplist_t pl)
BOOL PLIsSimple(proplist_t pl)
BOOL PLIsCompound(proplist_t pl)
--------------------------------
All these functions return YES if pl is of the respective type, NO if
it isn't. PLIsSimple returns YES if pl is a string or data object,
PLIsCompound returns YES if pl is an array or dictionary object.


unsigned char *PLGetStringDescription(proplist_t pl)
----------------------------------------------------
Returns a description of pl (which must be a string) in
GNUstep/OPENSTEP format. The difference between this function's output
and that returned by PLGetString is that this function's output is
surrounded by quotes if the string contains whitespace or any special
character. The string returned by this function is allocated by the
library; it is the user's responsibility to free it.

unsigned char *PLGetString(proplist_t pl)
-----------------------------------------
Returns the string contents of pl (which must be a string). This
function returns a reference to pl's contents; do not free it!

unsigned char *PLGetDataDescription(proplist_t pl)
--------------------------------------------------
Returns a description of pl (which must be a data object) in
GNUstep/OPENSTEP format. It is the user's responsibility to free the
returned string.

unsigned int PLGetDataLength(proplist_t pl)
-------------------------------------------
Returns the number of bytes contained in pl (which must be a data
object).

unsigned char *PLGetDataBytes(proplist_t pl)
--------------------------------------------
Returns a reference to the contents of pl (which must be a data
object). Do not free the memory associated with the returned value,
and keep in mind that it is not a string (i.e. it may contain NUL
bytes.


unsigned char *PLGetDescriptionIndent(proplist_t pl, unsigned int level)
------------------------------------------------------------------------
Returns a pretty-printed description of the property list in
GNUstep property list format. You probably want to call it with
level==0, but YMMV. Free the returned string after you're done.

unsigned char *PLGetDescription(proplist_t pl)
----------------------------------------------
Returns a compact description of the property list in GNUstep
format. Free the returned string after you're done.


unsigned int PLGetNumberOfElements(proplist_t pl)
-------------------------------------------------
Returns the number of elements contained in pl. This is always 0 if pl
is a string or data object. If pl is a dictionary, its number of keys
== its number of values == the returned number.

proplist_t PLGetArrayElement(proplist_t pl, unsigned int index)
---------------------------------------------------------------
Returns the array element at index, or NULL if index is out of
bounds. The returned value is a reference; do not destroy it before
having removed it from the array!

proplist_t PLGetAllDictionaryKeys(proplist_t pl)
------------------------------------------------
Returns an array containing all the keys of pl (which must be a
dictionary). The array returned is newly created for this purpose.

proplist_t PLGetDictionaryEntry(proplist_t pl, proplist_t key)
--------------------------------------------------------------
Returns the dictionary entry associated with key, or NULL if key isn't
in the dictionary. The returned value is a reference to a dictionary
value; do not destroy it!


proplist_t PLGetContainer(proplist_t pl)
----------------------------------------
Returns pl's container (i.e. the array or dictionary of which pl is an
element), or NULL if pl is at top level.


proplist_t PLMakeString(unsigned char *bytes)
---------------------------------------------
Returns a newly created string object. The passed string is copied for
this purpose, i.e. you can free it after this call.

proplist_t PLMakeData(unsigned char *data, unsigned int length)
---------------------------------------------------------------
Returns a newly created data object. The passed data is copied.

proplist_t PLMakeArrayFromElements(proplist_t pl, ...)
------------------------------------------------------
Returns a newly created array object. The passed arguments (all of
type proplist_t) must be NULL-terminated. If the first argument is
NULL, an empty array is returned. None of the passed property lists
are copied, so do not free them!

proplist_t PLInsertArrayElement(proplist_t array, proplist_t pl,
				unsigned int index)
----------------------------------------------------------------
Inserts pl into array at the specified index. Returns array if
successful, NULL if index is out of bounds. pl is not copied.

proplist_t PLRemoveArrayElement(proplist_t array, unsigned int index)
---------------------------------------------------------------------
Removes the element at the specified index from the array. Returns
array if successful, NULL if index is out of bounds. The removed
element is not destroyed.

proplist_t PLAppendArrayElement(proplist_t array, proplist_t pl)
----------------------------------------------------------------
Appends pl as the last element of array. Returns array. pl is not
copied.

proplist_t PLMakeDictionaryFromEntries(proplist_t key, proplist_t value,
				       ...)
------------------------------------------------------------------------
Returns a newly created dictionary object. The arguments must have the
form key1, value1, ..., keyn, valuen, NULL. None of the arguments are
copied. NOTE: all the dictionary functions use PLIsEqual() for the key
comparison. 

proplist_t PLInsertDictionaryEntry(proplist_t dict, proplist_t key,
				   proplist_t value)
-------------------------------------------------------------------
Inserts value as the new value for key into dict. key and value are
retained, i.e. you can release them afterwards.

proplist_t PLRemoveDictionaryEntry(proplist_t dict, proplist_t key)
-------------------------------------------------------------------
Removes key and its associated value from dict, and releases both.

proplist_t PLMergeDictionaries(proplist_t dest, proplist_t source)
------------------------------------------------------------------
Merges source into dest. It does so by PLDeepCopy()ing every key-value
pair in source. Be careful about this function, because it might throw
out references by calling PLInsertDictionaryEntry(), which can create
a memory hole if you don't retain references.


void PLRelease(proplist_t pl)
-----------------------------
Releases pl and all its contents. Only actually destroys them if they
aren't retained somewhere else.

proplist_t PLShallowCopy(proplist_t pl)
---------------------------------------
Copies pl. If pl is a string or data object, its contents are copied
as well. If pl is a dictionary or array object, only pl itself, but
not its contents, is copied. Returns the copy.

proplist_t PLDeepCopy(proplist_t pl)
------------------------------------
Copies pl and all its contents. Returns the copy.


BOOL PLIsEqual(proplist_t pl1, proplist_t pl2)
----------------------------------------------
Returns YES if pl1 (i.e. all its contents) is equal to pl2. You can
specify a comparison function that compares strings (in case you do
not want to do case-sensitive comparison, etc.) with
PLSetStringCmpHook().

void PLSetStringCmpHook(BOOL(*fn)(proplist_t, proplist_t))
----------------------------------------------------------
Sets the hook that is called upon string comparison to fn. Both
arguments supplied to fn are strings. fn must return YES if both
strings are equal, or NO if they aren't. The default function does
case-sensitive comparison; you can reset libPropList to use the
default function by passing NULL as an argument.
NOTE: This is to change soon to a strcmp()-compatible comparing
function, to optimize searching.








