@need 3200

@node Eight-bit Characters and Strings
@chapter Eight-bit Characters and Strings

The functions in this section operate on 8-bit characters (values
of type @code{char} or @code{t_uchar}) and strings of such characters.


@strong{NOTE:} Internationalized character and string functions are not
included with this release.  Future releases will include such
functions in addition to those documented here.

@menu
* Character Classes::
* Character Names::
* String Functions::
@end menu

@need 3200

@node Character Classes
@section Character Classes

The character-class macros assign each byte to various categories of
characters such as upper-case and lower-case letters.


These functions are based on the ASCII character set.  They are not
locale-sensative.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_upper}@maindex char_is_upper
@*
@example
@group
int char_is_upper (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is an upper case letter, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_lower}@maindex char_is_lower
@*
@example
@group
int char_is_lower (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a lower case letter, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_alpha}@maindex char_is_alpha
@*
@example
@group
int char_is_alpha (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is an upper or lower case letter, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_digit}@maindex char_is_digit
@*
@example
@group
int char_is_digit (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a decimal digit, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_alnum}@maindex char_is_alnum
@*
@example
@group
int char_is_alnum (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is an upper or lower case letter or digit, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_control}@maindex char_is_control
@*
@example
@group
int char_is_control (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a control character, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_printable}@maindex char_is_printable
@*
@example
@group
int char_is_printable (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a printable character, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_space}@maindex char_is_space
@*
@example
@group
int char_is_space (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a space character, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_graph}@maindex char_is_graph
@*
@example
@group
int char_is_graph (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a non-space printable character, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_c_id}@maindex char_is_c_id
@*
@example
@group
int char_is_c_id (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is an alpha-numeric character or '_', @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_xdigit}@maindex char_is_xdigit
@*
@example
@group
int char_is_xdigit (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a hexadecimal digit, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_odigit}@maindex char_is_odigit
@*
@example
@group
int char_is_odigit (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is an octal digit, @code{0} otherwise.

@sp 1
@need 1750
@noindent
@b{* Macro} @code{char_is_punct}@maindex char_is_punct
@*
@example
@group
int char_is_punct (t_uchar x);
@end group
@group
@end group
@end example

Return @code{1} if @code{x} is a punctuation character, @code{0} otherwise.




@need 3200

@node Character Names
@section Character Names
@sp 1
@need 1750
@noindent
@b{* Variable} @code{char_name}@vaindex char_name
@*
@example
@group
extern t_uchar * char_name[256];
@end group
@group
@end group
@end example

@code{char_name} contains the C names of each character (suitable for
use in C character constants or strings).  For example:

@example
@group
     char_name['\0']         is      "\\000"
     char_name['\n']         is      "\\n"
     char_name['\\']         is      "\\\\"
     char_name['a']          is      "a"
@end group
@group
@end group
@end example



@need 3200

@node String Functions
@section String Functions

These functions operate on @code{strings}, defined to be arrays of
't_uchar' terminated by (and not otherwise containing)
the null character (@code{(t_uchar)0}).


The functionality described in this function overlaps with some
of the functions in the standard C library defined by Posix,
but there are differences.  Read the documentation carefully if
you are replacing uses of Posix functions with Hackerlab functions.

@menu
* String Length::
* Computing Hash Values From Strings::
* Simple String Searching and Parsing::
* String Comparisons::
* String Comparisons Ignoring Case::
* String Copying::
* String Concatenation::
* String Allocators::
* Vararg String Functions::
@end menu

@need 3200

@node String Length
@subsection String Length
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_length}@fuindex str_length
@*
@example
@group
size_t str_length (const t_uchar * x);
@end group
@group
@end group
@end example

Return the length of the 0-terminated string @code{x}.  The length does
not include the 0-byte itself.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_length_n}@fuindex str_length_n
@*
@example
@group
size_t str_length_n (const t_uchar * x, size_t n);
@end group
@group
@end group
@end example

Return the length of the 0-terminated string @code{x} but not more than
@code{n}.  The length does not include the 0-byte itself.


If @code{x} is longer than @code{n} bytes, return @code{n}.




@need 3200

@node Computing Hash Values From Strings
@subsection Computing Hash Values From Strings
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_hash_n}@fuindex str_hash_n
@*
@example
@group
unsigned long str_hash_n (const t_uchar * chr, size_t len);
@end group
@group
@end group
@end example

Compute an @code{unsigned long} hash value for a string.




@need 3200

@node Simple String Searching and Parsing
@subsection Simple String Searching and Parsing
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_chr_index}@fuindex str_chr_index
@*
@example
@group
t_uchar * str_chr_index (const t_uchar * s, int c);
@end group
@group
@end group
@end example

Return the position in 0-terminated string @code{s} of the first
occurence of @code{c}.  Return @code{0} if @code{c} does not occur in @code{s}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_chr_rindex}@fuindex str_chr_rindex
@*
@example
@group
t_uchar * str_chr_rindex (const t_uchar * s, int c);
@end group
@group
@end group
@end example

Return the position in 0-terminated string @code{s} of the last
occurence of @code{c}.  Return @code{0} if @code{c} does not occur in @code{s}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_chr_index_n}@fuindex str_chr_index_n
@*
@example
@group
t_uchar * str_chr_index_n (const t_uchar * s, size_t n, int c);
@end group
@group
@end group
@end example

Return the position in length @code{n} string @code{s} of the first occurence
of @code{c}.  Return @code{0} if @code{c} does not occur in @code{s}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_chr_rindex_n}@fuindex str_chr_rindex_n
@*
@example
@group
t_uchar * str_chr_rindex_n (const t_uchar * s, size_t n, int c);
@end group
@group
@end group
@end example

Return the position in length @code{n} string @code{s} of the last occurence
of @code{c}.  Return @code{0} if @code{c} does not occur in @code{s}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_separate}@fuindex str_separate
@*
@example
@group
t_uchar * str_separate (t_uchar ** stringp, t_uchar * delims);
@end group
@group
@end group
@end example

Find the first occurence of a character from @code{delims} in @code{*stringp},
replace that character with @code{0}, set @code{*stringp} the address of the next
character after that, and return the value that @code{*stringp} had on entry.


If no delimeter is found in @code{*stringp}, set @code{*stringp} to @code{0} and return
the value on entry of @code{*stringp}.


If @code{*stringp} is @code{0}, return @code{0}.


If @code{delims} is @code{0}, set @code{*stringp} to @code{0}, and return the value of @code{*stringp}
on entry.




@need 3200

@node String Comparisons
@subsection String Comparisons
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cmp}@fuindex str_cmp
@*
@example
@group
int str_cmp (const t_uchar * a, const t_uchar * b);
@end group
@group
@end group
@end example

Compare strings @code{a} and @code{b} returning @code{-1} if @code{a} is lexically first,
@code{0} if the two strings are equal, @code{1} if @code{b} is lexically first.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cmp_n}@fuindex str_cmp_n
@*
@example
@group
int str_cmp_n (const t_uchar * a,
               size_t a_l,
               const t_uchar * b,
               size_t b_l);
@end group
@group
@end group
@end example

Compare strings @code{a} (length @code{a_l}) and @code{b} (length @code{b_l}) returning
@code{-1} if @code{a} is lexically first, @code{0} if the two strings are equal, @code{1} if
@code{b} is lexically first.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cmp_prefix}@fuindex str_cmp_prefix
@*
@example
@group
int str_cmp_prefix (const t_uchar * prefix, const t_uchar * s);
@end group
@group
@end group
@end example

Compare strings @code{prefix} and @code{s}.  If @code{prefix} is a prefix of @code{s},
return @code{0}.  Otherwise, if @code{prefix} is lexically first, return @code{-1};
if @code{s} is lexically first, return @code{1}.




@need 3200

@node String Comparisons Ignoring Case
@subsection String Comparisons Ignoring Case
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_casecmp}@fuindex str_casecmp
@*
@example
@group
int str_casecmp (const t_uchar * a, const t_uchar * b);
@end group
@group
@end group
@end example

Compare strings @code{a} and @code{b} ignoring case, returning @code{-1} if @code{a} is
lexically first, @code{0} if the two strings are equal, @code{1} if @code{b} is
lexically first.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_casecmp_n}@fuindex str_casecmp_n
@*
@example
@group
int str_casecmp_n (const t_uchar * a, size_t a_l,
                   const t_uchar * b, size_t b_l);
@end group
@group
@end group
@end example

Compare strings @code{a} (length @code{a_l}) and @code{b} (length @code{b_l}) ignoring
case returning @code{-1} if @code{a} is lexically first, @code{0} if the two strings
are equal, @code{1} if @code{b} is lexically first.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_casecmp_prefix}@fuindex str_casecmp_prefix
@*
@example
@group
int str_casecmp_prefix (const t_uchar * prefix, const t_uchar * s);
@end group
@group
@end group
@end example

Compare strings @code{prefix} and @code{s}, ignoring case.  If @code{prefix} is a
prefix of @code{s}, return @code{0}.  Otherwise, if @code{prefix} is lexically
first, return @code{-1}; if @code{s} is lexically first, return @code{1}.




@need 3200

@node String Copying
@subsection String Copying
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cpy}@fuindex str_cpy
@*
@example
@group
t_uchar * str_cpy (t_uchar * to, const t_uchar * from);
@end group
@group
@end group
@end example

Copy the 0-terminated string @code{from} to @code{to}.  @code{from} and @code{to}
should not overlap.


Returns @code{to}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cpy_n}@fuindex str_cpy_n
@*
@example
@group
t_uchar * str_cpy_n (t_uchar * to,
                     const t_uchar * from,
                     size_t n);
@end group
@group
@end group
@end example

Copy up-to @code{n} characters from @code{from} to @code{to}.  


Add a final @code{0} to @code{to}.


@strong{Warning:} This function is different from @code{strncpy}.  @code{strncpy}
always stores exactly @code{n} characters in @code{to}, padding the result
with @code{0} if a @code{0} character is encountered in @code{from} before @code{n}
characters are written.  This function stores up to @code{n+1} characters:
up to @code{n} non-0 characters from @code{from}, plus a final @code{0}.


Returns @code{to}.




@need 3200

@node String Concatenation
@subsection String Concatenation
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cat}@fuindex str_cat
@*
@example
@group
t_uchar * str_cat (t_uchar * to, const t_uchar * from);
@end group
@group
@end group
@end example

Append the 0-terminated string @code{from} to the 0-terminated string
@code{to}.  The strings should not overlap.  


Returns @code{to}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cat_n}@fuindex str_cat_n
@*
@example
@group
t_uchar * str_cat_n (t_uchar * to,
                     const t_uchar * from,
                     size_t n);
@end group
@group
@end group
@end example

Append at most @code{n} characters of the 0-terminated string @code{from} to
the 0-terminated string @code{to}.  The strings should not overlap.
Add a final @code{0} (thus writing up to @code{n + 1} characters in @code{to},
starting from the position of the final @code{0} in @code{to} on entry).


Returns @code{to}.




@need 3200

@node String Allocators
@subsection String Allocators
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_save}@fuindex str_save
@*
@example
@group
t_uchar * strsav (alloc_limits limits, const t_uchar * str);
@end group
@group
@end group
@end example

Allocate a copy of the 0-terminated string @code{str}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_save_n}@fuindex str_save_n
@*
@example
@group
t_uchar * str_save_n (alloc_limits limits,
                      const t_uchar * str,
                      size_t len);
@end group
@group
@end group
@end example

Allocate a copy of the n-byte string @code{str}.
Add one byte to the new string and store @code{0} in that byte.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_alloc_cat}@fuindex str_alloc_cat
@*
@example
@group
t_uchar * str_alloc_cat (alloc_limits limits,
                         const t_uchar * str1,
                         const t_uchar * str2);
@end group
@group
@end group
@end example

Allocate a new string large enough to hold the concatenation of
0-terminated strings @code{str1} and @code{str2} (including a final @code{0}).
Initialize the new string with the concatenation of @code{str1} and
@code{str2}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_alloc_cat_n}@fuindex str_alloc_cat_n
@*
@example
@group
t_uchar * str_alloc_cat_n (alloc_limits limits,
                           const t_uchar * str1,
                           const t_uchar * str2,
                           size_t n);
@end group
@group
@end group
@end example

Allocate a new 0-terminated string large enough to hold the
concatenation of 0-terminated strings @code{str1} and @code{str2},
considering at most @code{n} characters from @code{str2}.


Initialize the new string with the concatenation of @code{str1} and
up to @code{n} characters of @code{str2}.  Append a final @code{0}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_realloc_cat}@fuindex str_realloc_cat
@*
@example
@group
t_uchar * str_realloc_cat (alloc_limits limits,
                           t_uchar * str1,
                           const t_uchar * str2);
@end group
@group
@end group
@end example

Reallocate @code{str1`} to be large enough to hold the concatenation of
0-terminated strings @code{str1} and @code{str2} (including a final @code{0}).
Initialize the new string with the concatenation of @code{str1} and
@code{str2}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_realloc_cat_n}@fuindex str_realloc_cat_n
@*
@example
@group
t_uchar * str_realloc_cat_n (alloc_limits limits,
                             t_uchar * str1,
                             const t_uchar * str2,
                             size_t n);
@end group
@group
@end group
@end example

Reallocate @code{str} to be large enough to hold the
concatenation of 0-terminated strings @code{str1} and @code{str2},
considering at most @code{n} characters from @code{str2}.


Initialize the new string with the concatenation of @code{str1} and
up to @code{n} characters of @code{str2}.  Append a final @code{0}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)




@need 3200

@node Vararg String Functions
@subsection Vararg String Functions
@sp 1
@need 1750
@noindent
@b{* Function} @code{str_cat_many}@fuindex str_cat_many
@*
@example
@group
t_uchar * str_cat_many (t_uchar * to, ...);
@end group
@group
@end group
@end example

Append 0-terminated strings to the 0-terminated string @code{to}. The
strings should not overlap. The last argument should be the value
@code{str_end}.


Returns @code{to}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_alloc_cat_many}@fuindex str_alloc_cat_many
@*
@example
@group
t_uchar * str_alloc_cat_many (alloc_limits limits, ...);
@end group
@group
@end group
@end example

Allocate a new string large enough to hold the concatenation of
0-terminated strings (including a final @code{0}). Initialize the new string
with the concatenation of the given strings. The last argument should
be the value @code{str_end}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)

@sp 1
@need 1750
@noindent
@b{* Function} @code{str_realloc_cat_many}@fuindex str_realloc_cat_many
@*
@example
@group
t_uchar * str_realloc_cat_many (alloc_limits limits,
                                t_uchar * str1,
                                ...)
@end group
@group
@end group
@end example

Reallocate @code{str1} to be large enough to hold the concatenation of
0-terminated strings (including a final @code{0}). Initialize the new string
with the concatenation of the strings. The last argument should be the
value @code{str_end}.


Allocate storage according to @code{limits}.  (See @ref{Allocation With Limitations}.)










