/************************************************************************* * * $Id: doc_register.h,v 1.3 2008/10/12 12:09:51 breese Exp $ * * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ /** @addtogroup UserDefined User-defined Formatted Printing Functions. Functions for using customized formatting specifiers. @b SYNOPSIS @verbatim cc ... -ltrio -lm #include #include @endverbatim @b DESCRIPTION This documentation is incomplete. @b User-defined @b Specifier The user-defined specifier consists of a start character (\074 = '<'), an optional namespace string followed by a namespace separator (\072 = ':'), a format string, an optional skipping separator (\174 = '|'), and an end character (\076 = '>'). The namespace string can consist of alphanumeric characters, and is used to define a named reference (see below). The namespace is case-sensitive. If no namespace is specified, then we use an unnamed reference (see below). The format can consist of any character except the end character ('>'), the namespace separator (':'), the skipping separator ('|'), and the nil character (\000). Any modifier can be used together with the user-defined specifier. There are two formats for invoking a user-defined specifier. The first format is an extension of the normal printf/scanf formatting. It uses the percent character (\045 = '%') followed by optional qualifiers and a specifier. For example: @verbatim trio_printf("%\n", my_handle, my_data); @endverbatim Some C compilers can issue a warning if there is a mismatch between specifiers and arguments. Unfortunately, these warnings does not work with the first format for user-defined specifiers. Therefore the second format has been introduced. The second format can only be applied to user-defined specifiers. The second format starts with a dollar character (\044 = '$') instead of the percent character, and is followed by optional qualifiers and the user-defined specifier. If the specifier contains a pipe character (\174 = '|'), then everything between the pipe character and the end character ('>') is ignored. The ignored part can be used to list the normal specifiers that the C compiler uses to determine mismatches. For example: @verbatim trio_printf("$\n", my_handle, my_data); @endverbatim @b Registering A user-defined specifier must be registered before it can be used. Unregistered user-defined specifiers are ignored. The @ref trio_register function is used to register a user-defined specifier. It takes two argument, a callback function and a namespace, and it returns a handle. The handle must be used to unregister the specifier later. The following example registers a user-define specifier with the "my_namespace" namespace: @verbatim my_handle = trio_register(my_callback, "my_namespace"); @endverbatim There can only be one user-defined specifier with a given namespace. There can be an unlimited number (subject to maximum length of the namespace) of different user-defined specifiers. Passing NULL as the namespace argument results in an anonymous reference. There can be an unlimited number of anonymous references. @b REFERENCES There are two ways that a registered callback can be called. Either the user-defined specifier must contain the registered namespace in the format string, or the handle is passed as an argument to the formatted printing function. If the namespace is used, then a user-defined pointer must be passed as an argument: @verbatim trio_printf("%\n", my_data); @endverbatim If the handle is used, then the user-defined specifier must not contain a namespace. Instead the handle must be passed as an argument, followed by a user-defined pointer: @verbatim trio_printf("%\n", my_handle, my_data); @endverbatim The two examples above are equivalent. There must be exactly one user-defined pointer per user-defined specifier. This pointer can be used within the callback function with the @ref trio_get_argument getter function (see below). The format string is optional. It can be used within the callback function with the @ref trio_get_format getter function. @b Anonymous @b References Anonymous references are specified by passing NULL as the namespace. The handle must be passed as an argument followed by a user-defined pointer. No namespace can be specified. @verbatim anon_handle = trio_register(callback, NULL); trio_printf("%\n", anon_handle, my_data); @endverbatim @b Restrictions @li The length of the namespace string cannot exceed 63 characters. @li The length of the user-defined format string cannot exceed 255 characters. @li User-defined formatting cannot re-define existing specifiers. This restriction was imposed because the existing formatting specifiers have a well-defined behaviour, and any re-definition would apply globally to an application (imagine a third-party library changing the behaviour of a specifier that is crusial to your application). @b CALLBACK @b FUNCTION The callback function will be called if a matching user-defined specifier is found within the formatting string. The callback function takes one input parameter, an opaque reference which is needed by the private functions. It returns an @c int, which is currently ignored. The prototype is @verbatim int (*trio_callback_t)(void *ref); @endverbatim See the Example section for full examples. @b PRINTING @b FUNCTIONS The following printing functions must only be used inside a callback function. These functions will print to the same output medium as the printf function which invoked the callback function. For example, if the user-defined specifier is used in an sprintf function, then these print functions will output their result to the same string. @b Elementary @b Printing There are a number of function to print elementary data types. @li @ref trio_print_int Print a signed integer. For example: @verbatim trio_print_int(42); @endverbatim @li @ref trio_print_uint Print an unsigned integer. @li @ref trio_print_double Print a floating-point number. @li @ref trio_print_string Print a string. For example: @verbatim trio_print_string("Hello World"); trio_print_string(trio_get_format()); @endverbatim @li @ref trio_print_pointer Print a pointer. @b Formatted @b Printing The functions @ref trio_print_ref, @ref trio_vprint_ref, and @ref trio_printv_ref outputs a formatted string just like its printf equivalents. @verbatim trio_print_ref(ref, "There are %d towels\n", 42); trio_print_ref(ref, "%\n", recursive_writer, trio_get_argument(ref)); @endverbatim @b GETTER @b AND @b SETTER @b FUNCTIONS The following getter and setter functions must only be used inside a callback function. They can either operate on the modifiers or on special data. @b Modifiers The value of a modifier, or a boolean indication of its presence or absence, can be found or set with the getter and setter functions. The generic prototypes of the these getter and setter functions are @verbatim int trio_get_???(void *ref); void trio_set_???(void *ref, int); @endverbatim where @c ??? refers to a modifier. For example, to get the width of the user-defined specifier use @verbatim int width = trio_get_width(ref); @endverbatim @b Special @b Data Consider the following user-defined specifier, in its two possible referencing presentations. @verbatim trio_printf("%\n", namespace_writer, argument); trio_printf("%\n", argument); @endverbatim @ref trio_get_format will get the @p format string, and @ref trio_get_argument} will get the @p argument parameter. There are no associated setter functions. @b EXAMPLES The following examples show various types of user-defined specifiers. Although each specifier is demonstrated in isolation, they can all co-exist within the same application. @b Time @b Example Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside the user-defined specifier. @verbatim static int time_print(void *ref) { const char *format; time_t *data; char buffer[256]; format = trio_get_format(ref); if ((format) && (strcmp(format, "time") == 0)) { data = trio_get_argument(ref); if (data == NULL) return -1; strftime(buffer, sizeof(buffer), "%H:%M:%S", localtime(data)); trio_print_string(ref, buffer); } return 0; } @endverbatim @verbatim int main(void) { void *handle; time_t now = time(NULL); handle = trio_register(time_print, "my_time"); trio_printf("%