AG_STRING(3)

NAME
AG_String - agar C string specific functions

SYNOPSIS

    #include <agar/core.h>

DESCRIPTION
The functions described on this manual page are used to manipulate C strings (i.e., byte strings with a terminating NUL character).

FORMATTED OUTPUT CONVERSION
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.

SEPARATING STRINGS
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.

COPYING AND CONCATENATING STRINGS
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.

UNICODE OPERATIONS
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.

MISCELLANEOUS STRING OPERATIONS
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.

EXAMPLES
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);

SEE ALSO
AG_Error(3), AG_Intro(3), strcmp(3), string(3), strlen(3)

HISTORY
The AG_String interface was first documented in Agar 1.5.0.