##
##  OSSP val - Value Access
##  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
##  Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/>
##  Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/>
##
##  This file is part of OSSP val, a value access library which
##  can be found at http://www.ossp.org/pkg/lib/val/.
##
##  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.
##
##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
##  SUCH DAMAGE.
##
##  val.pod: library manual page
##

=pod

=head1 NAME

B<OSSP val> - Value Access

=head1 SYNOPSIS

=over 4

=item B<Constants>

C<VAL_MAXNAME>,
C<VAL_TYPE_VAL>,
C<VAL_TYPE_PTR>,
C<VAL_TYPE_CHAR>,
C<VAL_TYPE_SHORT>,
C<VAL_TYPE_INT>,
C<VAL_TYPE_LONG>,
C<VAL_TYPE_FLOAT>,
C<VAL_TYPE_DOUBLE>
C<VAL_OK>,
C<VAL_ERR_ARG>,
C<VAL_ERR_USE>,
C<VAL_ERR_MEM>,
C<VAL_ERR_HSH>,
C<VAL_ERR_INT>,
C<VAL_ERR_SYS>.

=item B<Data Types>

C<val_t>,
C<val_cb_t>,
C<val_rc_t>.

=item B<Functions>

C<val_create>,
C<val_destroy>,
C<val_reg>,
C<val_unreg>,
C<val_query>,
C<val_set>,
C<val_get>,
C<val_vset>,
C<val_vget>,
C<val_apply>.

=back

=head1 DESCRIPTION

B<OSSP val> is a flexible name to value mapping library for ISO-C
variables. It allows one to access ISO-C variables through name strings,
although the ISO-C language does neither provide such a dedicated
facility nor an evaluation construct (which could be used to implement
such a facility easily).

In general, this is used for accessing ISO-C variables without having to
know the actual symbol/address. The typical use cases are in combination
with flexible configuration parsing and supporting loosely-coupled
DSO-based module architectures.

=head1 STRUCTURED NAMES

Whenever the API calls for a name, it supports structured names where
elements are separated by a dot. It is assumed that the leading elements
are references to other C<val_t> structures and only the very last
element is a reference to an actual variable.

=head1 APPLICATION PROGRAMMING INTERFACE (API)

=head2 API CONSTANTS

The following constants exist in the B<OSSP val> API:

=over 4

=item C<VAL_MAXNAME>

The maximum length of a variable name. For structured variables this includes
the concatenation of all elements within a path and their separating dots.

=item C<VAL_TYPE_>I<ID>

Type of value when registering a variable using B<val_reg>() or querying
for the type using B<val_query>(). Most are self-explanatory because
directly correspond to the basic ISO-C data types. C<VAL_TYPE_VAL> is used
to mount a C<val_t> structure into an existing C<val_t> structure to
support structured names (see example section for details).

The following particular types exist: C<VAL_TYPE_VAL> (C<val_t
*>), C<VAL_TYPE_PTR> (C<void *>), C<VAL_TYPE_CHAR> (C<char>),
C<VAL_TYPE_SHORT> (C<short int>), C<VAL_TYPE_INT> (C<int>),
C<VAL_TYPE_LONG> (C<long int>), C<VAL_TYPE_FLOAT> (C<float>),
C<VAL_TYPE_DOUBLE> (C<double float>).

=item C<VAL_OK>, C<VAL_ERR_>I<ID>

Return codes (of type C<val_rc_t>) for every API function. Signals success
(C<VAL_OK>), invalid argument passed to function, bad usage of a function,
memory usage reached C<VAL_MAXNAME> limit, error in internal hash function to
be examined through C<errno>, internal error in storage as result from
structure corruption, or system errors including out of memory to be examined
through C<errno>.

The following particular return codes exist: C<VAL_OK>, C<VAL_ERR_ARG>,
C<VAL_ERR_USE>, C<VAL_ERR_MEM>, C<VAL_ERR_HSH>, C<VAL_ERR_INT>,
C<VAL_ERR_SYS>.

=back

=head2 API DATA TYPES

The following data types exist in the B<OSSP val> API:

=over 4

=item C<val_t>

Opaque handle data type created by B<val_create>() and passed to all
other functions to reference the the same group of values.

=item C<val_cb_t>

Function data type for the callback to be used with B<val_apply>().

=item C<val_rc_t>

Data type returned by every function. See B<API CONSTANTS> C<VAL_OK> and
C<VAL_ERR_>I<ID>.

=back

=head2 API FUNCTIONS

The following functions exist in the B<OSSP val> API:

=over 4

=item val_rc_t B<val_create>(val_t **I<pval>);

Creates a new value access structure and updates the given pointer
I<pval> to reference it.

=item val_rc_t B<val_destroy>(val_t *I<val>);

Destroys the value access structure referenced by I<val>.

=item val_rc_t B<val_reg>(val_t *I<val>, const char *I<name>, int I<type>, const char *I<desc>, void *I<storage>);

Registers a value under I<name> of type I<type> in I<val>. An optional
description or C<NULL> can be passed through I<desc> which can be
queried through B<val_query>() and is also passed to the callback of
B<val_apply>(). The value that belongs to the given I<name> is expected
to be found at I<storage>. Passing C<NULL> as I<storage> will create
an internal data storage in I<val> so it can only be accessed through
B<val_get>(), B<val_set>() or after the actual storage address was
queried using B<val_query>().

=item val_rc_t B<val_unreg>(val_t *I<val>, const char *I<name>);

Unregisters the value under I<name> from I<val>.

=item val_rc_t B<val_query>(val_t *I<val>, const char *I<name>, int *I<ptype>, char **I<pdesc>, void **I<pstorage>);

Queries a value I<name> in I<val> and returns its type, description and
storage address. All of I<ptype>, I<pdesc> and I<pstorage> are optional
and C<NULL> can be passed in if this information is not needed. Passing
C<NULL> to all query result pointers just checks for existence of the
value I<name> in I<val>.

=item val_rc_t B<val_set>(val_t *I<val>, const char *I<name>, ...);

Sets the value I<name> in I<val> to the data passed in as the variable
argument (expected to be of the I<type> specified at B<val_reg>() time).
Unless the actual storage address was queried using B<val_query>() this
operation is mandatory for internally stored data. If external storage
is used, not the value but a pointer to it is stored in the library, so
the value is allowed to be be modified without explicit notice to the
library.

=item val_rc_t B<val_get>(val_t *I<val>, const char *I<name>, ...);

Gets the value I<name> in I<val> and stores it wherever the passed variable
argument points to. The storage location is expected to be of the I<type>
specified at B<val_reg>() time.

=item val_rc_t B<val_vset>(val_t *I<val>, const char *I<name>, va_list I<ap>);

Exactly like B<val_set>() but uses a C<va_list> for the variable arguments.

=item val_rc_t B<val_vget>(val_t *I<val>, const char *I<name>, va_list I<ap>);

Exactly like B<val_get>() but uses a C<va_list> for the variable arguments.

=item val_rc_t B<val_apply>(val_t *I<val>, const char *I<name>, int I<depth>, val_cb_t I<cb>, void *I<ctx>);

Iterates over all values in I<val>, starting with I<name>, which can be
either a data storage or I<val_t> reference, down to a given recursion
I<depth>. If I<name> is set to the empty string the search starts
immediately at I<val>. For every value, the callback I<cb>() is executed.
The callback has to be a function with the following prototype:

val_rc_t cb(void *I<ctx>, const char *I<name>, int I<type>, const char *I<desc>, void *I<storage>);

The I<ctx> is the passed-through context I<ctx> of B<val_apply>().
The I<name> is the structured name relative to the I<val> passed to
B<val_apply>(), I<type> signals the type of value I<storage> points to
and I<desc> is the text which was optionally passed to B<val_reg>().

=back

=head1 SEE ALSO

B<OSSP var> (Variable Expansion)

=head1 EXAMPLES

A few simple examples on how to use B<OSSP val> are following. For
easier reading all error checks are omitted. In a production program you
have to check every val_xxx() call against C<VAL_OK>, of course.

=head2 Simple Internal Value

Source:

 #include <stdio.h>
 #include "val.h"

 int main(void)
 {
     val_rc_t rc;
     val_t *v;
     int tmp;

     val_create(&v);
     val_reg(v, "foo", VAL_TYPE_INT, "foo variable", NULL);
     val_set(v, "foo", 123);
     val_get(v, "foo", &tmp);
     printf("foo=%d\n", tmp);
     val_destroy(v);
     return 0;
 }

Output:

  foo=123

=head2 Simple External Value

Source:

 #include <stdio.h>
 #include "val.h"

 int main(void)
 {
     val_rc_t rc;
     val_t *v;
     int foo;
     int tmp;

     val_create(&v);
     val_reg(v, "foo", VAL_TYPE_INT, "foo variable", (void *)&foo);
     foo = 123;
     val_get(v, "foo", &tmp);
     printf("1. foo=%d tmp=%d\n", foo, tmp);
     val_set(v, "foo", 456);
     val_get(v, "foo", &tmp);
     printf("2. foo=%d tmp=%d\n", foo, tmp);
     example = 789;
     val_get(v, "foo", &tmp);
     printf("3. foo=%d tmp=%d\n", foo, tmp);
     val_destroy(v);
     return 0;
 }

Output:

 1. foo=123 tmp=123
 2. foo=456 tmp=456
 3. foo=789 tmp=789

=head2 Structured Internal Values

Source:

 #include <stdio.h>
 #include "val.h"

 int main(void)
 {
     val_rc_t rc;
     val_t *v1, *v2;
     int tmp;

     val_create(&v1);
     val_create(&v2);
     val_reg(v1, "bar", VAL_TYPE_VAL, "v2", (void *)&v2);
     val_reg(v1, "bar.foo", VAL_TYPE_INT, "foo variable", NULL);
     val_set(v2, "foo", 123);
     val_get(v2, "foo", &tmp);
     printf("1. foo=%d\n", tmp);
     val_get(v1, "bar.foo", &tmp);
     printf("2. bar.foo=%d\n", tmp);
     val_set(v1, "bar.foo", 456);
     val_get(v2, "foo", &tmp);
     printf("3. foo=%d\n", tmp);
     val_destroy(v2);
     val_destroy(v1);
     return 0;
 }

Output:

 1. foo=123
 2. bar.foo=123
 3. foo=456

=head1 HISTORY

B<OSSP val> was invented in January 2002 by Thomas Lotterer
E<lt>thomas@lotterer.netE<gt> and Ralf S. Engelschall
E<lt>rse@engelschall.comE<gt> for use in the B<OSSP> project. Its
creation was prompted by the requirement to locate values for B<OSSP
var> based expansions in B<OSSP lmtp2nntp>.

=head1 AUTHORS

 Thomas Lotterer     <thomas@lotterer.net>
 Ralf S. Engelschall <rse@engelschall.com>

=cut

