In addition to the functions required to operate data servers and
objects, Cichlid has several sets of functions and constants which can
be useful in C programs in general. To access these functions in a
server, put a "#define INCLUDE_CICHLID_UTILS" in your
source before you include "cichlid_server.h".
This listing of the utility functions and constants provided is divided up by module.
This module started out as a place for common functions (like
strdup(3)) that aren't part of ANSI C. It has evolved to
also contain a hodge-podge of original functions and macros that don't
fit in anywhere else. All of the functions and macros in this module
have names starting with "na_".
#define na_min(a, b) ...#define na_max(a, b) ...
These macros 'return' the minimum or maximum of "a" and
"b", which should be of the basic numeric types.
#define na_clamp(x, lw, up) ...
This macro takes the value in "x" and clamps it, making
sure it's on the interval [lw, up]. If it
was already on this interval, "x" is returned directly;
otherwise, the new value is returned.
#define na_spread(x, lw, ctr, up) ...
This macro does the opposite of na_clamp; it takes the
value in "x" and makes sure it is not on the
interval (lw, up). If it is, values
greater than or equal to "ctr" will return
"up", otherwise "lw" will be returned.
char *na_strdup(const char *str);
This function duplicates a null-terminated string and returns a
pointer it. Memory for the new string will be allocated with
malloc(3), but the caller is responsible for
free(3)'ing it. If there is insufficient memory for
the new string, a NULL pointer is returned. "str" may
not be NULL.
char *na_strappend(char *str, const char *to_append);
This function appends a copy of the null-terminated string pointed
to by "to_append" to the null-terminated string pointed
to by "str", and returns a pointer to the new string.
"str" must be a pointer to storage as returned
from malloc(3), since this routine uses
realloc(3) to resize it. If this routine succeeds,
"str" is no longer a valid pointer. If it fails, there
is not enough memory; NULL is returned and the memory at
"str" is unchanged.
int na_strcasecmp(const char *s1, const char *s2);
This function compares two strings, much like strcmp(3),
except it converts all letters to lower-case before comparing them.
unsigned int na_strlcat(char *dst, const char *src,
unsigned int dst_size);unsigned int na_strlcpy(char *dst, const char *src,
unsigned int dst_size);
These functions are more sane substitutes for
strncat(3) and strncpy(3). These were
inspired by OpenBSD's libc. The OpenBSD
strlcpy(3) manpage goes into detail.
int na_isreadable(const char *fname);
This is a quick function that tests whether the file named in
"fname" can be opened for reading with
fopen(3). Nonzero ('true') is returned if it is
readable, zero ('false') is returned otherwise.
void *na_force_malloc(unsigned long size);
This is strictly for lazy programmers and quick hacks; it is almost
a malloc(3) work-alike, except that it will never
return NULL -- if there is insufficient memory available, an "out of
memory" message will be printed and exit(3) will be
called.
void na_exit_msg(const char *format, ...);
This takes the exact same arguments as printf(3); it
prints the given message to standard error, and then calls
exit(3). This makes for a cheesy error handler.
void na_exit_nomem(void);
This prints a generic "out of memory" message to standard error and
calls exit(3).
void na_abort_msg(const char *format, ...);
This takes the exact same arguments as printf(3); it
prints the given message to standard error, and then calls
abort(3), in the hopes of giving a core dump to help
debugging. This is useful in code that checks preconditions,
but where an assert(3) won't do, since you always want
the check to occur.
int na_snprintf(char *buff, int size, const char *format,
...);
This is a snprintf(3) emulation for systems that don't
have it. It's currently pretty cheesy in that it will abort if it
detects a buffer overflow, instead of returning the number of bytes
used. Though it's not too neat-o, it beats using
sprintf(3) and accidentally adding one more buffer
overflow to the world.
char *na_chomp(char *str, unsigned int *len);
This chomps off (i.e., removes) all trailing whitespace from the
string pointed to by "str". If "len" is
non-NULL, it must point to a variable containing the length
of the string (as returned by strlen(3)); that value
will be updated to account for changes made to the string. If
"len" is NULL, this function will call
strlen(3) on it's own and horde the results to itself.
void na_rotate_enum(void *value, unsigned int count, unsigned
int rotate_up);
This is an ugly shoe-horn for stepping through the values of an
enumerated type. The enumerated type must start at zero,
it's members must be spaced apart by one, and the values must have
the same size and representation of positive numbers as an
unsigned int. "value" points to the
variable holding an enumerated type; "count" indicates
how many valid members are in the type. The actual values selected
will range from 0...count-1. If
"rotate_up" is nonzero, the value will be incremented,
wrapping back to zero if need be; otherwise, the value will be
decremented, wrapping the other way if needed.
void na_text_dim(const char *str, unsigned int *rows, unsigned
int *cols);
This examines a block of text, pointed to by "str", and
determines the 'dimensions' of it -- the overall number of rows and
columns. The number of rows is taken as the number newlines plus
one; the number of columns is taken as the maximum length of any
line of text. These values will be written out to
"rows" and "cols" if they are non-NULL
pointers. NULL pointers are accepted as a "don't care" option.
struct na_getopt_state { ... };void na_getopt_init(int consume_known, int ignore_unknown,
int *argcp, char **argv,
const char *option_spec, const char **option_arg,
struct na_getopt_state *state);int na_getopt_next(struct na_getopt_state *state);
These two functions are the interface to Cichlid's very own
command-line parsing library. The na_getopt_state
structure contains all state info and options for the parser;
"na_getopt_init" is called to initialize the structure,
and "na_getopt_next" extracts information from the
command line. The user code should not touch the
na_getopt_state structure at all!
To use this library, first declare a variable of type "struct
na_getopt_state". Then, call na_getopt_init
to initialize it, passing the following parameters:
consume_known:ignore_unknown:argcp:&argc).argv:argv). Note that
argv[0] will be ignored.option_spec:option_arg:const char *" pointer, which will
be used to point at the option arguments.state:na_getopt_state
structure.
Now that the parser is initialized, call
"na_getopt_next" in a loop to extract each argument.
Pass it a pointer to the state structure, and watch it's return
value. Defined returned values are:
This is just a header file; it started out as a place to define pi, but has since grown to include a few other constants and macros. It contains:
#define M_PI ...#define M_SQRT2 ...#define M_SQRT3 ...
These are the constant values of pi, sqrt(2), and sqrt(3).
#define HALF_PI ...#define TWO_PI ...
These are stupid little macros are shorthand for M_PI/2.0 and M_PI*2.0. They came up often enough to be useful.
#define DEG_TO_RAD ...#define RAD_TO_DEG ...
These constants convert angular values between degrees and radians.
For instance, to convert "foo" degrees into radians,
one could use "bar = foo * DEG_TO_RAD;"
#define WRAP_RADS ...
This odd macro maps values on [-2*pi, 2*pi] to [-pi, pi] by adding or subtracting 2*pi once, to keep the same direction. This is handy for adding small increments to angles (in radians), and having the values wrap around pi and -pi, instead of climbing bigger and bigger, possibly confusing the trig functions. Note that this does not loop at all.
#define ACUTE_RIGHT(a) ...#define OBTUSE_RIGHT(a) ...
These test whether or not an angular value in radians, on [-pi, pi] is 1) acute or right, or 2) obtuse or right.
This is a general-purpose library for converting text strings
representing numbers to numeric values. These functions all return
nonzero on error. These are all just wrappers for
strtol(3) and strtod(3), but they perform
error checking, range checking, and type conversion.
int str2long(const char *string, int base, long *result);
int str2ulong(const char *string, int base, unsigned long
*result);int str2int(const char *string, int base, int *result);
int str2uint(const char *string, int base, unsigned int
*result);int str2doub(const char *string, double *result);int str2float(const char *string, float *result);
Each of these functions takes a pointer to a null-terminated string; it
is expected to hold only the numeric value, and while leading spaces are
tolerated, trailing spaces are not. The "base"
parameter to the integer functions may range from 2 to 36, or if it's
zero, bases 8, 10, and 16 will be auto-detected from the string -- see
the FreeBSD strtol(3) manpage for more
details. For the floating-point functions, the strings must be in base
10; see the FreeBSD strtod(3) manpage for
more details. If any error is detected, such as invalid characters in
the input, "result" will be set to something screwy, such
as a maximum value for the type, and the function will return nonzero.
This is a quickly-concieved library for taking a writable text string, and splitting it up at the whitespace values, null-terminating the individual strings, and creating an index of pointers to them -- much like creating an "argv" from a command line. There are two variants of this function, one that dynamically allocates the index, the other uses a pre-allocated fixed-size index.
int strsplit_fixed(char *string, char **str_index,
int index_size);
This splits up the given string at white spaces, and makes a mild
attempt at honoring one level of quotation (but not backslash
escapes). Each "word" will be terminated by overwriting the first
character of whitespace with a NUL character; a pointer to the start
of each word will be written to the array of character pointers
pointed to by "str_index". That array is taken to be
of size "index_size" elements; the number of elements
written -- that is, the number of substrings split -- will be
returned. If there are more substrings than available index slots,
the last index pointer will point at the remainder of the input, and
"index_size" will be returned. This function has no
explicit failure modes.
char **strsplit_var(char *string, int *size);
This function works much like strsplit_fixed, except it
allocates it's own index array, which must later be freed manually.
A pointer to the new index array is returned, or NULL if
insufficient memory was available. The index array actually has one
extra pointer at the end; after the pointer to the last string is a
NULL pointer to signal the end of the list. Additionally, if the
"size" parameter is non-NULL, the count of substrings
split will be written there.
The "sysdep" module is for system-dependent functions and definitions, such as timing and sleeping. The idea was to keep all of the OS-specific stuff here, with the exception of the socket I/O code, to keep the majority of the source from getting mired down in #ifdef's.
#if defined(INCLUDE_GL_HDRS) ...#if defined(INCLUDE_GLUT_HDRS) ...
If these symbols are defined, the "sysdep" header will include the
OpenGL headers and/or the GLUT headers, as appropriate. It becomes
inconvenient to include those headers directly in the source files,
because of Win32 namespace damage. Currently, if you're not
compiling on a Win32 system, these act exactly as you'd expect, just
#include'ing the headers; on a Win32 system, they just
#include the GLUT header, which does namespace munging,
and may include the entire "windows.h" header, as well as the OpenGL
headers. It's a mess.
#define SYS_PATH_SEP ...
This expands to a string which is the path separator for filenames on the target OS. This assumes, of course, that there is only one such string, and that the concept even applies at all.
typedef ... ubyte_t;typedef ... u16_t;typedef ... i16_t;typedef ... u32_t;typedef ... i32_t;
These are aliased to appropriate base types for the target OS and
compiler, based on the sizes of the data types. The
"u" and "i" prefixes indicate whether the
base type is signed or unsigned, and the number indicates the bit
width.
#define UBYTET_MAX ...#define U16T_MAX ...#define U32T_MAX ...#define I16T_MIN ...#define I16T_MAX ...#define I32T_MIN ...#define I32T_MAX ...
These constants represent the boundary values -- the limits -- for the size-based typedefs, ala <limits.h>.
u16_t sys_htons(u16_t datum);u16_t sys_ntohs(u16_t datum);u32_t sys_htonl(u32_t datum);u32_t sys_ntohl(u32_t datum);
These are work-alikes for everyone's favorite functions,
ntohs(3), htons(3), ntohl(3),
and htonl(3). These are actually functions, not
macros, though they don't do anything on big-endian systems; the
function-call interface serves to isolate the various name-space
dependencies of different OS's and give a consistent interface.
void sys_random_seed(void);long sys_random_get(void);
These functions provide a simple interface to a pseudo-random number
generator; sys_random_seed seeds the PRNG with a value
derived from the current wall-clock time;
sys_random_get returns a random number.
int sys_time_get(void);int sys_time_seed(void);
These two functions access the local wall clock.
sys_time_get returns a value (in milliseconds) since
the first time the function was called; this is useful for interval
timing, but not for direct conversion to wall clock times or dates.
sys_time_seed returns a time-based value suitable for
seeding a PRNG -- since the first call to sys_time_get
always returns a very small value, it is a poor choice for a seed.
void sys_time_sleep(int msec);
This function attempts to sleep for the indicated number of milliseconds. Currently, it does not check for an under-sleep, and there isn't a well-defined boundary on how long it will actually sleep.
This library provides a searchable database of color name to RGB value mappings. The color database was derived from the XFree86 Version 3.3.2 file /usr/X11R6/lib/X11/rgb.txt. The program "lib/color_test" provides a command-line interface to this library.
const unsigned char *color_lookup(const char *name);
This does a case-insensitive search for a color name that matches
"name", in O(lg n) time. If a match is found, a
pointer to a 3-byte R,G,B triplet is returned; otherwise, NULL is
returned.
const char *color_search(const unsigned char search_rgb[3],
unsigned char *result_rgb,
int *is_exact, int *is_unique);
This does a O(n)-time search for the named color in the database
whose RGB values are closest to the given search values. A pointer
to the name of the nearest match is returned. If
"result_rgb" is not NULL, the RGB triplet of the match
will be written out there. If "is_exact" is non-NULL,
a flag will be written out that is nonzero iff the returned triplet
is an exact match with the search key. If "is_unique"
is non-NULL, a flag will be written out that is nonzero iff the
returned triplet's distance to the search key was the unique
minimum.
int color_get_count(void);
This returns the number of color entries in the database.
const char *color_list_all(int reset,
unsigned char *rgb);
This function walks through the color database. It should first be
called with the "reset" flag nonzero, and it will
return NULL. Then, on each subsequent call, it will return the next
color name in the database, and if "rgb" is a non-NULL
pointer, it will write out the RGB triplet of the color there. This
will return NULL when the end of the database has been reached.
float color_distance(const unsigned char rgb1[3],
const unsigned char rgb2[3]);
This returns the "distance" between two colors in RGB space. The three components to each color are treated as coordinates in orthogonal planes, and the distance is calculated with the usual 3D distance equation. The returned value will be on [0, 255*sqrt(3)] modulo any round-off error.