AG_String
—
agar C string specific functions
The functions described on this manual page are used to manipulate C strings
(i.e., byte strings with a terminating NUL character).
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);
size_t
AG_ProcessFmtString
(AG_FmtString
*fs, char *dst,
size_t 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 *
- %llf, %llg
- long double * (needs AG_HAVE_LONG_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. For example, the ag_math library, upon initialization, registers
%[V] for its
M_Vector(3)
type, %[M] for its
M_Matrix(3)
type, etc. (see
M_String(3)
for a complete list).
The AG_RegisterFmtStringExt
() function
registers a new "%[foo]" style specifier. The
extFn calback functions should be of the form:
typedef size_t (*AG_FmtStringExtFn)(AG_FmtString *fs, char *dst,
size_t 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);
size_t
AG_Strlcpy
(char
*dst, const char
*src, size_t
dst_size);
size_t
AG_Strlcat
(char
*dst, const char
*src, size_t
dst_size);
size_t
AG_StrlcpyInt
(char
*dst, int number,
size_t dst_size);
size_t
AG_StrlcatInt
(char
*dst, int number,
size_t dst_size);
size_t
AG_StrlcpyUint
(char
*dst, Uint number,
size_t dst_size);
size_t
AG_StrlcatUint
(char
*dst, Uint number,
size_t 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.
The AG_StrlcpyInt
(),
AG_StrlcpyUint
(),
AG_StrlcatInt
(), and
AG_StrlcatUint
() functions efficiently convert a
numerical integer to a string and respectively copy or concatenate that
string to the given buffer, in the same manner as
AG_Strlcpy
() and
AG_Strlcat
(). Whenever possible, constructing a
string using only AG_Strlcpy
(),
AG_Strlcat
() and
AG_StrlcatInt
() is always more efficient than using
the standard
printf(3)
formatting engine.
Uint32 *
AG_ImportUnicode
(const
char *encoding, const char
*src, size_t
*pOutLen, size_t
*pOutSize);
int
AG_ExportUnicode
(const
char *encoding, char
*dst, const Uint32
*src, size_t
dstSize);
int
AG_LengthUTF8
(const
char *s, size_t
*rv);
int
AG_CharLengthUTF8
(unsigned
char byte);
size_t
AG_LengthUCS4
(const
Uint32 *ucs);
int
AG_LengthUTF8FromUCS4
(const
Uint32 *ucs, size_t
*rv);
size_t
AG_CharLengthUTF8FromUCS4
(Uint32
ch);
The AG_ImportUnicode
() function converts
the given string src (assumed to be in the specified
encoding) to UCS-4 format. On success, the function
returns a newly-allocated UCS-4 text buffer. If
pOutLen is non-NULL, the total number of characters is
returned in it. Acceptable values for encoding include
"US-ASCII" and "UTF-8". If Agar was compiled with
support for the
iconv(3)
library, any character set supported by iconv may be specified. Agar always
handles the US-ASCII and UTF-8 encodings internally, even if iconv is
unavailable.
The AG_ExportUnicode
() function converts
the contents of the given UCS-4 text buffer to the specified
encoding (again, "US-ASCII and "UTF-8"
are handled internally by Agar, other encodings may be specified if iconv is
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.
The AG_LengthUTF8
() function counts the
number of characters in the given UTF-8 string. On success, the function
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. Returns the sequence
length in bytes (or 1 if there is none).
The AG_LengthUCS4
() function returns the
number of characters in the given UCS-4 text buffer (similarly to
strlen(3)).
The terminating NUL is not included in the count.
The AG_LengthUTF8FromUCS4
() function
returns the number of bytes that would be needed to encode the given UCS-4
string in UTF-8 encoding. On success, the function returns 0 and writes the
count to rv. If ucs contains an
invalid Unicode character, the function fails and returns -1.
The AG_CharLengthUTF8FromUCS4
() function
returns the number of bytes that would be needed to encode the given UCS-4
character as an UTF-8 character sequence.
int
AG_Strcasecmp
(const
char *s1, const char
*s2);
int
AG_Strncasecmp
(const
char *s1, const char
*s2, size_t n);
const char *
AG_Strcasestr
(const
char *big, const char
*little);
void
AG_StrReverse
(char
*s);
The AG_Strcasecmp
() and
AG_Strncasecmp
() functions peforms comparison
between two C strings s1 and s2
like the standard
strcmp(3)
and
strncmp(3),
except that the comparison is done in a case-insensitive way. Returns an
integer greater than, equal to, or less than 0, depending on whether
s1 is lexicographically greater than, equal to, or
less than s2 after translation of each corresponding
character to lower-case.
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 the
characters in the given C string.
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 efficiently constructs a string from a
substring and an integer:
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 to Unicode,
counts the number of Unicode characters, and exports the string to
UTF-8:
char *dst;
Uint32 *unicode, *s;
int count = 0;
size_t dstLen;
if ((unicode = AG_ImportUnicode("ISO-8859-1", input, NULL))
== NULL) {
AG_FatalError(NULL);
}
for (s = &unicode[0]; *s != ' '; s++) {
count++;
}
if (AG_LengthUTF8FromUCS4(unicode, &dstLen) == -1) {
AG_FatalError(NULL);
}
dst = AG_Malloc(dstLen);
AG_ExportUnicode("UTF-8", dst, unicode, dstLen)
The following code fragment registers an extension to the
AG_Printf(3)
formatting engine, and uses the new format when creating static and polled
labels:
size_t
PrintMyVector(AG_FmtString *fs, char *dst, size_t 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 AG_String
interface was first documented in Agar
1.5.0.