gleipnir_lines
==============



Name
----
struct gleip_lines,
gleip_lines_get_ro,
gleip_lines_get,
gleip_lines_get_ptr,
gleip_lines_mem,
gleip_lines_size,
gleip_lines_empty,
gleip_lines_mem_trim,
gleip_lines_mem_grow,
gleip_lines_addcpy,
gleip_lines_addcpy_back,
gleip_lines_addref,
gleip_lines_addref_back,
gleip_lines_rm_range,
gleip_lines_rm_range_back,
gleip_lines_rm_line,
gleip_lines_rm_line_back,
gleip_lines_rm,
gleip_lines_shift,
gleip_lines_new,
gleip_lines_new_back,
gleip_lines_new_line,
gleip_lines_new_line_back,
gleip_lines_mv_range,
gleip_lines_mv_range_back,
gleip_lines_mv,
gleip_lines_mv_back,
gleip_lines_mv_line,
gleip_lines_mv_line_back,
gleip_lines_cpy_range,
gleip_lines_cpy_range_back,
gleip_lines_cpy,
gleip_lines_cpy_back,
gleip_lines_cpy_line,
gleip_lines_cpy_line_back,
gleip_lines_free,
gleip_lines_alloc_mem,
gleip_lines_alloc,
gleip_lines_alloc_mv_range,
gleip_lines_alloc_mv_line,
gleip_lines_alloc_cpy_range,
gleip_lines_alloc_cpy,
gleip_lines_alloc_cpy_line - gleipnir_lines.



Synopsis
--------
	long GLEIP_LINES_VERSION;

	struct gleip_lines
	{
		size_t	size,
			mem;
		char	* * arr;
	};

	const char *
	gleip_lines_get_ro (
		const struct gleip_lines	* const restrict lines,
		const size_t			i
		);

	char *
	gleip_lines_get (
		struct gleip_lines	* const restrict lines,
		const size_t		i
		);

	char * *
	gleip_lines_get_ptr (
		struct gleip_lines	* const restrict lines,
		const size_t		i
		);

	size_t
	gleip_lines_mem (
		const struct gleip_lines	* const restrict lines
		);

	size_t
	gleip_lines_size (
		const struct gleip_lines	* const restrict lines
		);

	int
	gleip_lines_empty (
		const struct gleip_lines	* const restrict lines
		);

	int
	gleip_lines_mem_trim (
		struct gleip_lines	* const restrict lines
		);

	int
	gleip_lines_mem_grow (
		struct gleip_lines	* const restrict lines,
		const size_t		mem
		);

	int
	gleip_lines_addcpy (
		struct gleip_lines	* const restrict lines,
		const char		* const restrict line,
		const size_t		i
		);

	int
	gleip_lines_addcpy_back (
		struct gleip_lines	* const restrict lines,
		const char		* const restrict line
		);

	int
	gleip_lines_addref (
		struct gleip_lines	* const restrict lines,
		char			* const restrict ref,
		const size_t		i
		);

	int
	gleip_lines_addref_back (
		struct gleip_lines	* const restrict lines,
		char			* const restrict ref
		);

	void
	gleip_lines_rm_range (
		struct gleip_lines	* const restrict lines,
		size_t			i,
		const size_t		count
		);

	void
	gleip_lines_rm_range_back (
		struct gleip_lines	* const restrict lines,
		const size_t		count
		);

	void
	gleip_lines_rm_line (
		struct gleip_lines	* const restrict lines,
		const size_t		i
		);

	void
	gleip_lines_rm_line_back (
		struct gleip_lines	* const restrict lines
		);

	void
	gleip_lines_rm (
		struct gleip_lines	* const restrict lines
		);

	void
	gleip_lines_shift (
		struct gleip_lines	* const restrict lines,
		const size_t		i_to,
		const size_t		i_from,
		const size_t		count
		);

	int
	gleip_lines_new (
		struct gleip_lines	* const restrict lines,
		const size_t		i,
		const size_t		count
		);

	int
	gleip_lines_new_back (
		struct gleip_lines	* const restrict lines,
		const size_t		count
		);

	int
	gleip_lines_new_line (
		struct gleip_lines	* const restrict lines,
		const size_t		i
		);

	int
	gleip_lines_new_line_back (
		struct gleip_lines	* const restrict lines
		);

	int
	gleip_lines_mv_range (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src,
		const size_t		i_dst,
		const size_t		i_src,
		const size_t		count
		);

	int
	gleip_lines_mv_range_back (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src,
		const size_t		i_src,
		const size_t		count
		);

	int
	gleip_lines_mv (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src,
		const size_t		i_dst
		);

	int
	gleip_lines_mv_back (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src
		);

	int
	gleip_lines_mv_line (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src,
		const size_t		i_dst,
		const size_t		i_src
		);

	int
	gleip_lines_mv_line_back (
		struct gleip_lines	* const restrict dst,
		struct gleip_lines	* const restrict src,
		const size_t		i_src
		);

	int
	gleip_lines_cpy_range (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src,
		const size_t			i_dst,
		const size_t			i_src,
		const size_t			count
		);

	int
	gleip_lines_cpy_range_back (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src,
		const size_t			i_src,
		const size_t			count
		);

	int
	gleip_lines_cpy (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src,
		const size_t			i_dst
		);

	int
	gleip_lines_cpy_back (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src
		);

	int
	gleip_lines_cpy_line (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src,
		const size_t			i_dst,
		const size_t			i_src
		);

	int
	gleip_lines_cpy_line_back (
		struct gleip_lines		* const restrict dst,
		const struct gleip_lines	* const restrict src,
		const size_t			i_src
		);

	void
	gleip_lines_free (
		struct gleip_lines	* const restrict lines
		);

	struct gleip_lines *
	gleip_lines_alloc_mem (
		const size_t	mem
		);

	struct gleip_lines *
	gleip_lines_alloc (void);

	struct gleip_lines *
	gleip_lines_alloc_mv_range (
		struct gleip_lines	* const restrict src,
		const size_t		i_src,
		const size_t		count
		);

	struct gleip_lines *
	gleip_lines_alloc_mv_line (
		struct gleip_lines	* const restrict src,
		const size_t		i_src
		);

	struct gleip_lines *
	gleip_lines_alloc_cpy_range (
		const struct gleip_lines	* const restrict src,
		const size_t			i_src,
		const size_t			count
		);

	struct gleip_lines *
	gleip_lines_alloc_cpy (
		const struct gleip_lines	* const restrict src
		);

	struct gleip_lines *
	gleip_lines_alloc_cpy_line (
		const struct gleip_lines	* const restrict src,
		const size_t			i_src
		);



Options
-------

`lines`
:	The buffer to operate on.

`dst`
:	The destination buffer for the operation when growable C-strings
	are moved or copied from `src`.

`src`
:	The source buffer for the operation. Growable C-strings in `src`
	are moved or copied to `dst` (or the returned buffer).

`line`
:	The line to add a copy of. This does not have to be a growable
	C-string (but it can be, or it can be read-only storage), and
	`lines` does *not* become responsible for freeing it.

`ref`
:	The line to add as a reference. This *must* be a growable
	C-string (it may not be read-only storage), and `lines` becomes
	responsible for freeing it.

`i`
:	The index in `lines`. Must be `< lines->size`.

`i_dst`
:	The index in `dst`. Must be `< lines->size`.

`i_src`
:	The index in `src`. Must be `< lines->size`.

`i_from`
:	The beginning index in `lines`. The growable C-strings that are
	in the range `[i_from, i_from + count)` in `lines` are shifted
	to `i_to`. `i_from + count` must be `≤ lines->size`.

`i_to`
:	The end index in `lines`. `i_to + count` must be
	`≤ lines->size`.

`count`
:	The number of growable C-strings to operate on. Must be > 0.

`mem`
:	The desired memory capacity. Must be > 0.



Description
-----------
`GLEIP_LINES_VERSION` is the version of the library.

`struct gleip_lines` is a buffer of growable C-strings.

*	`arr` is a ragged array of growable C-strings.
*	`size` is the amount of growable C-strings in the buffer.
	-	`size` is always within `[0, mem]`.
*	`mem` is the length of `arr`.
	-	`mem` is always within `[size, ∞)` (where `∞` is
		actually `SIZE_MAX` (≥ C99) or `(size_t)-1` (< C99)),
		and always > 0.

The following rules apply for pointers in `arr`:

*	`arr[n]` where `n` is within `[0, size)` (assuming `size > 0`):
	-	Is always non-`NULL`.
	-	Can have any length (`strlen()`).
	-	Can have any memory (`gleip_line_mem()`).
*	`arr[n]` where `n` is within `[size, mem)` (assuming
	`mem > size`):
	-	May be `NULL` or non-`NULL`.
	-	Always has length 0 (`strlen()`) if non-`NULL`.
	-	Can have any memory (`gleip_line_mem()`) if non-`NULL`.

Normally you only access elements in `arr` that are within `[0, size)`.
Elements `≥ size` are referred to as "garbage" and are re-used when you
add new strings to the buffer (to reduce allocations and frees). When
you remove strings, they are blanked out (so that `strlen() = 0`) and
moved to the garbage indices. Garbage strings should generally not be
manipulated manually.

`gleip_lines_get_ro` is equivalent to `lines->arr[i]`.
`i < lines->size`.

`gleip_lines_get` is equivalent to `lines->arr[i]`. `i < lines->size`.

`gleip_lines_get_ptr` is equivalent to `& lines->arr[i]`.
`i < lines->size`.

`gleip_lines_mem` is equivalent to `lines->mem`.

`gleip_lines_size` is equivalent to `lines->size`.

`gleip_lines_empty` checks if `lines` is empty, which is the case if
`size` is 0.

`gleip_lines_mem_trim` trims the memory capacity of all strings in the
buffer and reduces `mem` to `size` (or 1 if `size` is 0). Doing this
will probably only lead to heap fragmentation.

`gleip_lines_mem_grow` grows `lines->mem` to `mem`. `mem` must be > 0.

`gleip_lines_addcpy` makes a copy of `line`, adds it at `lines->arr[i]`
and shifts the indices of all following elements with +1. `i` must be
`[0, lines->size]`. If `i = lines->size`, then the copy is added last
in the buffer. The memory capacity of the copy is just big enough to fit
all characters.

*	`line` may be any type of C-string (writable (`char *`),
	read-only (`const char *`) or growable). If `line` is
	dynamically allocated, then `lines` does *not* become
	responsible for freeing it.

`gleip_lines_addcpy_back` adds a copy of `line` last in `lines`.

`gleip_lines_addref` adds `ref` at `i` and shifts the indices of all
following elements with +1. `i` must be `[0, lines->size]`. If
`i = lines->size`, then the reference is added last in the buffer.

*	`ref` must be a growable C-string, and `lines` becomes
	responsible for freeing it (unless the function fails, in which
	case ownership is not transferred).

`gleip_lines_addref_back` adds `ref` last in `lines`.

`gleip_lines_rm_range` removes `[i, i + count)` in `lines` and shifts
all following lines. `size` is reduced by `count`, so `count ≤ size`.

`gleip_lines_rm_range_back` removes the last `count` strings in `lines`.

`gleip_lines_rm_line` removes the string at index `i` in `lines`.

`gleip_lines_rm_line_back` removes the last string in `lines`.

`gleip_lines_shift` shifts `count` lines beginning at index `i_from` in
`lines` to `i_to`. Lines in-between are shifted in the opposite
direction. Lines can be shifted in any direction but both `i_to + count`
and `i_from + count` must be `≤ size`. Examples:

	/*
	 * lines->arr:
	 *	0	"A"
	 *	1	"B"	i_to
	 *	2	"C"
	 *	3	"X"	i_from
	 *	4	"Y"
	 */
	gleip_lines_shift(lines,
			1,	/* i_to */
			3,	/* i_from */
			2);	/* count */
	/*
	 * lines->arr:
	 *	0	"A"
	 *	1	"X"
	 *	2	"Y"
	 *	3	"B"
	 *	4	"C"
	 */

	/*
	 * lines->arr:
	 *	0	"A"
	 *	1	"X"	i_from
	 *	2	"Y"
	 *	3	"B"	i_to
	 *	4	"C"
	 */
	gleip_lines_shift(lines,
			3,	/* i_to */
			1,	/* i_from */
			1);	/* count */
	/*
	 * lines->arr:
	 *	0	"A"
	 *	1	"Y"
	 *	2	"B"
	 *	3	"X"
	 *	4	"C"
	 */

`gleip_lines_new` adds `count` empty (`strlen() = 0`) lines at `i` in
`lines`, and shifts all following lines with `+count`. `i` must be
`[0, lines->size]`. If `i = lines->size`, then the new lines are
appended to the buffer. All new lines that are added this way have
default memory capacity.

`gleip_lines_new_back` appends `count` empty lines to the buffer.

`gleip_lines_new_line` adds 1 empty line at `i` in the buffer.

`gleip_lines_new_line_back` appends 1 empty line to the buffer.

`gleip_lines_mv_range` moves `count` lines from `i_src` in `src` to
`i_dst` in `dst`. All following lines in `dst` are shifted by `+count`.
`i_dst ≤ dst->size` and `i_src < src->size`. If `i_dst = dst->size`,
then the lines are moved to the back of `dst`. `count ≤ src->size`. The
`size` of `dst` increases by `count` and the `size` of `src` decreases
by the same amount.

`gleip_lines_mv_range_back` is like `gleip_lines_mv_range` but all lines
are moved to the back of `dst`.

`gleip_lines_mv` moves all lines in `src` to `i_dst` in `dst`.

`gleip_lines_mv_back` moves all lines in `src` to the back of `dst`.

`gleip_lines_mv_line` moves the line at `i_src` in `src` to `i_dst` in
`dst`.

`gleip_lines_mv_line_back` moves the line at `i_src` in `src` to the
back of `dst`.

`gleip_lines_cpy_range` copies `count` lines from `i_src` in `src` to
`i_dst` in `dst`. All following lines in `dst` are shifted by `+count`.
`i_dst ≤ dst->size` and `i_src < src->size`. If `i_dst = dst->size`,
then the lines are copied to the back of `dst`. `count ≤ src->size`. The
`size` of `dst` increases by `count` but `src` is not modified at all.
The memory capacity of all the copies are just big enough to fit their
contents.

`gleip_lines_cpy_range_back` is like `gleip_lines_cpy_range` but all
lines are copied to the back of `dst`.

`gleip_lines_cpy` copies all lines in `src` to `i_dst` in `dst`.

`gleip_lines_cpy_back` copies all lines in `src` to the back of `dst`.

`gleip_lines_cpy_line` copies the line at `i_src` in `src` to `i_dst` in
`dst`.

`gleip_lines_cpy_line_back` copies the line at `i_src` in `src` to the
back of `dst`.

`gleip_lines_free` frees a buffer of growable C-strings and all strings
in `lines->arr` (that is, all new lines that have been allocated in the
buffer, all lines that have been copied or moved to it from another
buffer and all copies and references that have been added to it).

`gleip_lines_alloc_mem` allocates a buffer with memory capacity `mem`,
which must be > 0.

`gleip_lines_alloc` allocates a buffer with default memory capacity (9).

`gleip_lines_alloc_mv_range` moves `count` lines at `i_src` in `src` to
a new buffer, which is returned.

`gleip_lines_alloc_mv_line` moves the line at `i_src` in `src` to a new
buffer, which is returned.

`gleip_lines_alloc_cpy_range` copies `count` lines at `i_src` in `src`
to a new buffer, which is returned.

`gleip_lines_alloc_cpy` copies all in `src` to a new buffer, which is
returned.

`gleip_lines_alloc_cpy_line` copies the line at `i_src` in `src` to a
new buffer, which is returned.



Exit status
-----------
*	Allocation functions (`gleip_lines_alloc*`) return a pointer to
	a buffer of growable C-strings which must be freed by the caller
	with `gleip_lines_free`.
*	Non-allocation functions return a boolean. `true` (1) means
	success and `false` (0) means failure. (1 is always returned for
	`true`.)
*	If a function fails, then it "does nothing", but it may change
	garbage strings and `gleip_lines->mem`. However, strings
	`< size` and `gleip_lines->size` remains as they were before the
	function was called.



Examples
--------
	struct gleip_lines * const lines = gleip_lines_alloc();
	if	(NULL == lines)
	{
		/*
		 * Failure to allocate.
		 */
		return	EXIT_FAILURE;
	}
	if	(!gleip_lines_addcpy_back(lines,
			"Gloria altissimo suorum refugio")
	||	!gleip_lines_addcpy_back(lines, "Pro patria"))
	{
		/*
		 * Failure to add copies (allocate).
		 */
		gleip_lines_free(lines);
		return	EXIT_FAILURE;
	}
	assert	(2 == gleip_lines_size(lines));
	(void)puts		(gleip_lines_get_ro(lines, 0));
	(void)puts		(gleip_lines_get_ro(lines, 1));
	gleip_lines_free	(lines);
	return			EXIT_SUCCESS;



Diagnostics
-----------
Functions can only fail for one reason: failure to allocate or
re-allocate memory. In this case they return false or `NULL`. A true or
non-`NULL` return value always indicates success.



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



See also
--------
`gleipnir_line`(7),
`gleipnir_lineread`(7),
`gleipnir_lang`(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.

