gleipnir_lang
=============



Name
----
struct gleip_lang,
gleip_lang_size,
gleip_lang_key,
gleip_lang_value,
gleip_lang_mem_trim,
gleip_lang_get,
gleip_lang_getany,
gleip_lang_invalid_why,
gleip_lang_valid,
gleip_lang_clear,
gleip_lang_read,
gleip_lang_read_file,
gleip_lang_read_cstr,
gleip_lang_isreg,
gleip_lang_regcpy,
gleip_lang_regref,
gleip_lang_unreg_i,
gleip_lang_unreg,
gleip_lang_unreg_all,
gleip_lang_print,
gleip_lang_cpy,
gleip_lang_free,
gleip_lang_alloc_mem,
gleip_lang_alloc_cpy,
gleip_lang_alloc - gleipnir_lang.



Synopsis
--------
	long	GLEIP_LANG_VERSION;

	struct gleip_lang
	{
		struct gleip_lines	* keys,
					* values;
	};

	size_t
	gleip_lang_size (
		const struct gleip_lang	* const restrict lang
		);

	const char *
	gleip_lang_key (
		const struct gleip_lang	* const restrict lang,
		const size_t		i
		);

	const char *
	gleip_lang_value (
		const struct gleip_lang	* const restrict lang,
		const size_t		i
		);

	int
	gleip_lang_mem_trim (
		struct gleip_lang	* const restrict lang
		);

	const char *
	gleip_lang_get (
		const struct gleip_lang	* const restrict lang,
		const char		* const restrict key
		);

	const char *
	gleip_lang_getany (
		const struct gleip_lang	* const restrict lang,
		const char		* const restrict key
		);

	const char *
	gleip_lang_invalid_why (
		const struct gleip_lang	* const restrict lang
		);

	int
	gleip_lang_valid (
		const struct gleip_lang	* const restrict lang
		);

	void
	gleip_lang_clear (
		struct gleip_lang	* const restrict lang
		);

	int
	gleip_lang_read (
		struct gleip_lang	* const restrict lang,
		void			* const data,
		struct gleip_lines	* restrict buf,
		int			* const restrict valid,
		int			(* callback_data_next) (void *)
		);

	int
	gleip_lang_read_file (
		struct gleip_lang	* const restrict lang,
		FILE			* const file,
		struct gleip_lines	* restrict buf,
		int			* const restrict valid
		);

	int
	gleip_lang_read_cstr (
		struct gleip_lang	* const restrict lang,
		const char		* * const src,
		struct gleip_lines	* restrict buf,
		int			* const restrict valid
		);

	int
	gleip_lang_isreg (
		const struct gleip_lang	* const restrict lang,
		const char		* const key
		);

	int
	gleip_lang_regcpy (
		struct gleip_lang	* const restrict lang,
		const char		* const key
		);

	int
	gleip_lang_regref (
		struct gleip_lang	* const restrict lang,
		char			* const ref
		);

	void
	gleip_lang_unreg_i (
		struct gleip_lang	* const restrict lang,
		const size_t		i
		);

	void
	gleip_lang_unreg (
		struct gleip_lang	* const restrict lang,
		const char		* const key
		);

	void
	gleip_lang_unreg_all (
		struct gleip_lang	* const restrict lang
		);

	int
	gleip_lang_print (
		const struct gleip_lang	* const restrict lang,
		FILE			* const restrict out,
		const char		sep
		);

	int
	gleip_lang_cpy (
		struct gleip_lang	* const restrict lang,
		const struct gleip_lang	* const restrict orig
		);

	void
	gleip_lang_free (
		struct gleip_lang	* const restrict lang
		);

	struct gleip_lang *
	gleip_lang_alloc_mem (
		const size_t	mem
		);

	struct gleip_lang *
	gleip_lang_alloc_cpy (
		const struct gleip_lang	* const restrict orig
		);

	struct gleip_lang *
	gleip_lang_alloc (void);



Options
-------

`lang`
:	The language struct to operate on.

`orig`
:	The source language struct to copy from.

`i`
:	The index to retrieve a key or value for. This must be
	`< gleip_lang_size(lang)`.

`key`
:	The key to operate on. This is a regular C-string and may even
	be read-only storage.

`ref`
:	The key reference. This *must* be a growable C-string, and
	`lang` becomes responsible for freeing it.

`data`
:	See `gleipnir_lineread`(7).

`callback_data_next`
:	See `gleipnir_lineread`(7).

`file`
:	See `gleipnir_lineread`(7).

`src`
:	See `gleipnir_lineread`(7).

`buf`
:	A buffer that can optionally be passed to the reading functions.
	If `NULL`, then one will be allocated ad hoc and freed before
	the function returns. If non-`NULL`, then the function will use
	the buffer for reading, but the function does *not* become
	responsible for freeing it.

`valid`
:	A pointer to a boolean. This is set to true if the language file
	was valid, or false otherwise. This may be `NULL` if you don't
	care.

`out`
:	Output stream or file.

`sep`
:	The symbol that separates every printed key. This can be any
	`char`, even `'\0'`. `'\n'` prints them with one key per line.

`mem`
:	The memory capacity of the struct. This is how many keys it will
	hold without having to grow. Must be > 0.



Description
-----------
**Note that all of the `gleipnir_lang` functions simply iterate over all
keys and compare them using `strcmp` on lookup. This is not efficient,
and is only suitable for a relatively small number of keys. Since keys
are unique, it would be very suitable to use a hashmap instead if you
have a lot of keys.**

A language struct maps keys to values. The keys are the same during the
lifetime of the language struct. The values are the translated language
strings. The values can be read from files. One file should contain all
the key-value-mappings for one language.

`GLEIP_LANG_VERSION` is the version of the library.

`struct gleip_lang` should be treated as an abstract data type.

`gleip_lang_size` returns the number of registered language keys.

`gleip_lang_key` retrieves the key at `i`. `i < gleip_lang_size(lang)`.
The returned key is never `NULL`.

`gleip_lang_value` retrieves the value at `i`.
`i < gleip_lang_size(lang)`. The returned value is `NULL` if it has not
been read, or non-`NULL` (and non-empty) if it has been read.

`gleip_lang_mem_trim` trims the memory capacity.

`gleip_lang_get` returns the value mapped to `key`. `key` *must* be
registered. The returned value is a growable (but read-only) C-string.
If the value has not been read, then this function returns `NULL`. If
the value has been read, then this function returns the value, which is
always a non-empty string.

Note that it is a programming error to call this function with a key
that has not been registered. `gleip_lang_isreg` can be used to check if
a key has been registered.

`gleip_lang_getany` is like `gleip_lang_get`, but if the value has not
been read, then it returns the key (the parameter) instead. Consequently
the returned string is never `NULL`.

`gleip_lang_invalid_why` returns the key for the first value that has
not been read. If the values for all registered keys have been read,
then this function returns `NULL`.

`gleip_lang_valid` returns true if all values have been read. If this
returns false, then `gleip_lang_invalid_why` is guaranteed to return a
non-`NULL` key. Note that this function can only determine if all values
are present; `gleip_lang_read` can detect other errors in language
files.

`gleip_lang_clear` blanks out all values, so that `gleip_lang_get` will
return `NULL` for every registered key. Note that this does not
unregister any keys (use `gleip_lang_unreg*` for that).

`gleip_lang_read` reads language values into `lang` from the data source
(see `gleipnir_lineread`(7)). `buf` and `valid` are both optional. `buf`
is used for temporarily saving the text that is read from the data
source before copying it into `lang`; if `NULL`, then a buffer will be
allocated by the function and freed before it returns. `valid` is set to
determine if the file is valid or not. `valid` may not have gone through
all validation checks if the function returns false (out of memory).
`lang` is automatically cleared before reading the data source.

If `valid` is false, you may be able to determine which key is missing
by calling `gleip_lang_invalid_why`. However, this function will also
flag the language file as invalid for the following reasons, which are
not detected by `gleip_lang_invalid_why`:

*	Some line only has a key, and no value.
*	The same key occurs more than once.
*	There is an unregistered key in the file.

Note that this function calls `gleip_lang_valid` as a part of its
validation. You do not have to call that function yourself after
reading.

A language file has two tokens per line. The first token is the language
key, and all subsequent text on the same line (the value) is treated
like a single token (white space is condensed). For example, it can look
like this:

	key1	Bävrarnas framfart i Europa
	key2	Vad gör bävrarna\
		i Europa?

After reading, this will result in the following key-value-pairs:

	"key1": "Bävrarnas framfart i Europa"
	"key2": "Vad gör bävrarna i Europa?"

This function returns true (1) or false (0). It always reads the data
source to `EOF` (unless interrupted by a failure to allocate) and
therefore never returns `EOF`. However, if `data` is a `FILE *`, you can
still call `ferror(FILE *)` on it to check for errors.

`gleip_lang_read_file` calls `gleip_lang_read` with a `FILE *` data
source.

`gleip_lang_read_cstr` calls `gleip_lang_read` with a `const char *`
data source.

`gleip_lang_isreg` checks if `key` has been registered in `lang`.

`gleip_lang_regcpy` registers `key` in `lang`. A copy is made of `key`
before it is added in `lang`, so `key` may be a regular C-string and
`lang` does *not* become responsible for freeing it.

*	The key may not be empty.
*	A key is case sensitive.
*	The same key may only be registered once (unless it is
	unregistered in-between).

`gleip_lang_regref` is like `gleip_lang_regcpy` except that `ref` is a
growable C-string, and `lang` becomes responsible for freeing it (unless
the function fails).

`gleip_lang_unreg_i` unregisters the key at `i`.

`gleip_lang_unreg` unregisters `key`. `key` *must* have been registered
(you can use `gleip_lang_isreg` to determine if it has been).

`gleip_lang_unreg_all` unregisters all keys. If no keys have been
registered, then this function does nothing.

`gleip_lang_print` prints out all registered keys, separated by the
`sep` character, to `out`. Returns false on failure to print any key.

`gleip_lang_cpy` copies all keys and values from `orig` to `lang`. All
keys in `lang` are automatically unregistered first. If this function
fails, then no keys are registered in `lang`. Note that all values are
copied as they currently are, even if `orig` is invalid. Further note
that this is a "deep" copy, so subsequent changes in `lang` do not
automatically propagate into `orig`.

`gleip_lang_free` frees a language struct and all related resources.
This includes keys that have been registered using `gleip_lang_regref`.

`gleip_lang_alloc_mem` allocates a language struct with room for `mem`
keys. Of course the language struct will grow automatically if needed.

`gleip_lang_alloc_cpy` allocates a copy of `orig` (see `gleip_lang_cpy`
for details).

`gleip_lang_alloc` allocates a language struct with default memory
capacity (27).



Exit status
-----------
*	Allocation functions (`gleip_lang_alloc*`) return a pointer to
	a language struct that must be freed by the caller with
	`gleip_lang_free`.
*	Non-allocation functions that return a boolean return `true` (1)
	for success and `false` (0) for failure. (1 is always returned
	for `true`.)
*	Retrieval functions may or may not return `NULL`. In general,
	keys are never returned as `NULL`, but values are returned as
	`NULL` if they have not been read (however the
	`gleip_lang_getany` function guarantees a non-`NULL` value
	retrieval by returning the key if the value is missing).
*	If a function fails, then it "does nothing", but it may change
	garbage strings used internally. Reading functions that fail may
	result in a partially read file.



Examples
--------
	/*
	 * Error checking omitted.
	 */
	struct gleip_lang	* lang	= ...
	gleip_lang_regcpy	(lang, "key1");
	gleip_lang_regcpy	(lang, "key2");
	FILE			* file	= ...
	gleip_lang_read_file	(lang, file, ...);
	/*
	 * `gleip_lang_get(lang, "key1")` and
	 * `gleip_lang_get(lang, "key2")` are the translated language
	 * strings.
	 */



Diagnostics
-----------
Functions return false (0) for failure to allocate memory. No function
returns `EOF`, but an I/O error may always result when you pass a
`FILE *` to a function. It is up to the caller to call `ferror(FILE *)`
on it to check for errors.



Bugs
----
The fetter shall burst at Ragnarök, and the Wolf runs free.



See also
--------
`gleipnir_line`(7),
`gleipnir_lines`(7),
`gleipnir_lineread`(7)



Homepage
--------
`www.tafl.se/gleipnir`



Author
------
Alexander Söderlund, Sweden
`<soderlund` **at** `tafl` **dot** `se>`



Copyright
---------
© 2013-2014 Alexander Söderlund, Sweden



License and warranty
--------------------
Copyright © 2013-2014 Alexander Söderlund, Sweden

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

