AG_String
— agar C
string specific functions
The functions described here are used to construct and manipulate
C strings (byte strings with a terminating NUL character), and convert text
between different character encodings.
char *
AG_Printf
(const
char *format,
...);
char *
AG_PrintfN
(Uint
buffer, const char
*format, ...);
AG_FmtString *
AG_PrintfP
(const
char *format,
...);
void
AG_FreeFmtString
(AG_FmtString
*fs);
AG_Size
AG_ProcessFmtString
(AG_FmtString
*fs, char *dst,
AG_Size dstSize);
void
AG_RegisterFmtStringExt
(const
char *fmt,
AG_FmtStringExtFn
extFn);
TYPE
AG_FMTSTRING_ARG
(AG_FmtString
*fs);
void
AG_UnregisterFmtStringExt
(const
char *fmt);
The
AG_Printf
()
function performs formatted output conversion (similar to
printf(3),
with Agar-specific extensions). AG_Printf
() returns
a pointer to an internally managed buffer, which will remain valid until the
application or thread terminates (in multithreaded mode, thread-local
storage is used). The caller must not attempt to
free(3)
the returned pointer.
The
AG_PrintfN
()
variant allows multiple buffers to be used. The buffer
argument specifies the buffer index to use (any integer up to
AG_STRING_BUFFER_MAX
is valid).
The
AG_PrintfP
()
function allocates and initializes a new AG_FmtString
structure from the given format string and arguments. Unlike
AG_Printf
() which accepts literal values as
arguments, the arguments to AG_PrintfP
() must be
pointers to specifically typed data. Those arguments will be accessed only
at a later time (when AG_ProcessFmtString
() is
called).
AG_ProcessFmtString
()
processes a format string (previously returned by
AG_PrintfP
()), writing the formatted output to
dst (which should be at least
dstSize bytes in size). If insufficient space is
available in the buffer, the output is truncated.
AG_FreeFmtString
()
releases all resources allocated by a format string.
AG_ProcessFmtString
()
returns the number of characters that would have been copied were
dstSize unlimited. The formatted output is always
NUL-terminated.
Agar's formatting engine supports the following built-in
specifiers:
- %d, %i
- int
- %ld, %li
- long int
- %lld, %lli
- long long int or Sint64
- %o, %u, %x, %X
- unsigned int
- %lu, %lo, %lx
- long unsigned int
- %llu, %llo, %llx
- long long unsigned int or
Uint64
- %c
- char
- %s
- char *
- %f, %g
- float *
- %lf, %lg
- double *
- %[u8]
- Uint8 *
- %[s8]
- Sint8 *
- %[u16]
- Uint16 *
- %[s16]
- Sint16 *
- %[u32]
- Uint32 *
- %[s32]
- Sint32 *
- %[u64]
- Uint64 * (needs AG_HAVE_64BIT)
- %[s64]
- Sint64 * (needs AG_HAVE_64BIT)
- %[objName]
- AG_Object * (Returns object name)
- %[objType]
- AG_Object * (Returns class name)
Specifiers for user-defined formatting routines can be registered
at runtime.
The
AG_RegisterFmtStringExt
()
function registers a new format specifier. If the given
fmt argument is "abc", then occurences of
"%[abc]" in the format string will be processed by the given
callback function. extFn is a callback routine of the
form:
typedef AG_Size (*AG_FmtStringExtFn)(AG_FmtString *fs, char *dst,
AG_Size dstSize);
The callback is expected to write to
fixed-size buffer dst, and return the number of
characters that would have been written were dstSize
unlimited. The callback function can NUL-terminate the string, but it is not
a requirement. A generic pointer to the argument variable can be obtained
from the
AG_FMTSTRING_ARG
()
macro.
The
AG_UnregisterFmtStringExt
()
function removes the given extended format specifier.
char *
AG_Strsep
(char
**stringp, const char
*delim);
The
AG_Strsep
()
function locates, in the string referenced by
*stringp, the first occurrence of any character in the
string delim (or the terminating NUL character) and
replaces it with a NUL. The location of the next character after the
delimiter character (or NULL, if the end of the string was reached) is
stored in *stringp. The original value of
*stringp is returned.
An “empty” field (i.e., a character
in the string delim occurs as the first character of
*stringp) can be detected by comparing the location
referenced by the returned pointer to NUL. If *stringp
is initially NULL
,
AG_Strsep
()
returns NULL
.
char *
AG_Strdup
(const
char *s);
char *
AG_TryStrdup
(const
char *s);
AG_Size
AG_Strlcpy
(char
*dst, const char
*src, AG_Size
dst_size);
AG_Size
AG_Strlcat
(char
*dst, const char
*src, AG_Size
dst_size);
AG_Size
AG_StrlcpyInt
(char
*dst, int number,
AG_Size dst_size);
AG_Size
AG_StrlcatInt
(char
*dst, int number,
AG_Size dst_size);
AG_Size
AG_StrlcpyUint
(char
*dst, Uint number,
AG_Size dst_size);
AG_Size
AG_StrlcatUint
(char
*dst, Uint number,
AG_Size dst_size);
The
AG_Strdup
()
function returns a copy of the given C string. If insufficient memory is
available, a
AG_FatalError(3)
is raised. The AG_TryStrdup
() variant returns NULL
on failure.
The
AG_Strlcpy
()
and AG_Strlcat
() functions copy and concatenate C
strings respectively. They are designed to be safer, more consistent, and
less error prone replacements for
strncpy(3)
and
strncat(3).
Unlike those functions, AG_Strlcpy
() and
AG_Strlcat
() take the full size of the buffer (not
just the length) and guarantee to NUL-terminate the result (as long as
size is larger than 0 or, in the case of
AG_Strlcat
(), as long as there is at least one byte
free in dst). Note that a byte for the NUL should be
included in size.
The
AG_Strlcpy
()
function copies up to size - 1 characters from the
NUL-terminated string src to
dst, NUL-terminating the result. The
AG_Strlcat
() function appends the NUL-terminated
string src to the end of dst. It
will append at most size - strlen(dst) - 1 bytes,
NUL-terminating the result.
The
AG_Strlcpy
()
and AG_Strlcat
() functions return the total length
of the string they tried to create. For AG_Strlcpy
()
that means the length of src. For
AG_Strlcat
() that means the initial length of
dst plus the length of src.
AG_StrlcpyInt
(),
AG_StrlcpyUint
(),
AG_StrlcatInt
(), and
AG_StrlcatUint
() convert an integer to a string
representation (equivalent to a
printf(3)
"%d" or "%u"). The resulting string is copied to (or
concatenated against) the destination buffer.
AG_Char *
AG_ImportUnicode
(const
char *encoding, const
char *src, AG_Size
*pOutLen, AG_Size
*pOutSize);
int
AG_ExportUnicode
(const
char *encoding, char
*dst, const AG_Char
*src, AG_Size
dstSize);
inline AG_Size
AG_LengthUTF8
(const
char *s);
inline int
AG_CharLengthUTF8
(unsigned
char byte);
inline AG_Size
AG_LengthUCS4
(const
AG_Char *ucs);
inline int
AG_LengthUTF8FromUCS4
(const
AG_Char *ucs, AG_Size
*rv);
inline AG_Size
AG_CharLengthUTF8FromUCS4
(AG_Char
ch);
AG_ImportUnicode
()
converts the string src (in specified
encoding) to internal (UCS-4) format. On success, it
returns a newly-allocated UCS-4 buffer. The number of characters in the
string is returned in pOutLen (if not NULL).
Recognized values for encoding include
"US-ASCII" and "UTF-8". If Agar was compiled with
iconv(3)
support then any character set supported by iconv may be specified.
The
AG_ExportUnicode
()
function converts the contents of the given UCS-4 text buffer to the
specified encoding ("US-ASCII and
"UTF-8" are handled internally by Agar, other encodings are
handled through iconv where available). The resulting text is written to the
specified buffer dst, which should be of the specified
size dstSize, in bytes. The written string is always
NUL-terminated.
AG_LengthUTF8
()
counts the number of characters in the given UTF-8 string. On success, it
returns 0 the character count is written to rv. If the
string is not a valid UTF-8 string, the function returns -1.
AG_CharLengthUTF8
()
evaluates whether the given byte is the start of an UTF-8 character sequence
and returns the sequence length in bytes (or 1 if there is none).
AG_LengthUCS4
()
returns the number of characters in the given UCS-4 text buffer (analogous
to
strlen(3)).
The terminating NUL is not included in the returned count.
AG_LengthUTF8FromUCS4
()
returns the number of bytes that would be needed to encode the given UCS-4
string in UTF-8 encoding. On success, it returns 0 and writes the count to
rv. If ucs contains an invalid
Unicode character, it fails and returns -1.
AG_CharLengthUTF8FromUCS4
()
returns the number of bytes that would be needed to encode the given UCS-4
character as an UTF-8 character sequence.
inline int
AG_Strcasecmp
(const
char *s1, const char
*s2);
inline int
AG_Strncasecmp
(const
char *s1, const char
*s2, AG_Size
n);
const char *
AG_Strcasestr
(const
char *big, const char
*little);
void
AG_StrReverse
(char
*s);
The
AG_Strcasecmp
()
and AG_Strncasecmp
() functions peforms
case-insensitive comparison between two C strings s1
and s2. The return value is greater than, equal to, or
less than 0 depending on whether s1 is
lexicographically greater than, equal to, or less than
s2.
The
AG_Strcasestr
()
function is a case-insensitive version of the standard
strstr(3).
It locates the first occurence of the little string in
the big string.
The
AG_StrReverse
()
function reverses all characters in the C string
s.
The following Agar-GUI code creates an
AG_Label(3),
passing a formatted string (in an internally-managed buffer) to the label
constructor:
int myInt = 1234;
AG_LabelNewS(win, 0, AG_Printf("myInt=%d", myInt));
Whenever multiple strings are needed simultaneously,
AG_PrintfN
() allows a buffer index to be
specified:
void MyFn(const char *string1, const char *string2);
MyFn(AG_PrintfN(0, "First string"),
AG_PrintfN(1, "Second string"));
The following code uses AG_Strsep
() to
parse a string, and prints each token in separate line:
char *string = AG_Strdup("abc,def,ghi");
char *pString = string, *token;
while ((token = AG_Strsep(&string, ",")) != NULL) {
printf("%s\n", token);
}
free(pString);
The following code constructs a string with a formatted
number:
char myBuffer[30];
int i = 0;
for (i = 0; i < 10; i++) {
AG_Strlcpy(myBuffer, "Item #", sizeof(myBuffer));
AG_StrlcatInt(myBuffer, i, sizeof(myBuffer));
}
The following code converts a string from LATIN-1 (iso-8859-1)
encoding to Unicode, counts the number of characters, and exports the string
to UTF-8 encoding:
char *dst;
AG_Char *unicode, *s;
int count = 0;
AG_Size dstLen;
if ((unicode = AG_ImportUnicode("LATIN1", input, NULL)) == NULL) {
AG_FatalError(NULL);
}
for (s = &unicode[0]; *s != '\0'; s++) {
count++;
}
if (AG_LengthUTF8FromUCS4(unicode, &dstLen) == -1) {
AG_FatalError(NULL);
}
dst = AG_Malloc(dstLen);
AG_ExportUnicode("UTF-8", dst, unicode, dstLen)
The following GUI code fragment registers an extension to the
AG_Printf(3)
formatting engine, and uses the new format when creating static and polled
labels:
AG_Size
PrintMyVector(AG_FmtString *fs, char *dst, AG_Size dstSize)
{
struct my_vector *my = AG_FMTSTRING_ARG(fs);
return AG_Snprintf(dst, dstSize, "[%f,%f]", my->x, my->y);
}
...
struct my_vector v;
AG_RegisterFmtStringExt("myVec", PrintMyVector);
AG_LabelNewS(win, 0, AG_Printf("Static label: %[myVec]", &v));
AG_LabelNewPolled(win, 0, "Polled label: %[myVec]", &v);
The Agar-Math library (ag_math) upon initialization registers %[V]
for its
M_Vector(3)
type, %[M] for its
M_Matrix(3)
type, and others. For the complete list see
M_String(3).
The AG_String
interface was first
documented in Agar 1.5.0.