Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
sf_fmt(3)		     Library Functions Manual		       sf_fmt(3)

NAME
     format_init,   format_free,  format_metarule,  formatf,  format_lastresult,
     format_lastsize, format_detach -- template formatting functions.

SYNOPSIS
     #include <strfunc.h>

     fmt_base *
     format_init();

     void
     format_free(fmt_base *base);

     int
     format_metarule(fmt_base *base, char leftBrace, char rightBrace,
	 char **(*function)(char *found, void *optKeyPassed));

     char *
     formatf(fmt_base *base, char *template, void *optKeyToPass);

     char *
     format_lastresult(fmt_base *base, size_t *optSize);

     size_t
     format_lastsize(fmt_base *base);

     char *
     format_detach(fmt_base *base, size_t *optReturnSize);

DESCRIPTION
     It is widely used for programs to read a template and display the data  ac-
     cording to it.

     Those  functions  forms a powerful solution to work with a kind of "active"
     templates. The term "active" means that some operations, like a test of ex-
     istence of a keyword, or equality tests, can be placed directly to the tem-
     plate and no special handling needed in an application to support it.  str-
     func(3) library will automagically do the dirty work for you.

     The internal language of defining the template is powerful yet simple.  Be-
     fore we run into detailed explanation, let's talk about programming.

     First, programmer needed to initialize the formatting  engine  by	defining
     the formatting rules. Formatting rules are stored inside the special struc-
     ture  fmt_base.   format_init()  creates an empty structure and returns the
     pointer to it. One may define a numerous formatting bases and randomly  use
     them.  Formatting	base may be freed using format_free(fmt_base *).  Please
     note that format_init() will never return the NULL pointer.

     Second, there is a need to fill this empty structure with	some  formatting
     rules using the format_metarule() function. Formatting rules are defined by
     specifiyng  a braces and the function which will handle the data inside the
     braces.

     Say, we have a template "abc${def}ghi". Programmer  should  call  the  for-
     mat_metarule(fb, '{', '}', handler), where fb is the pointer to the format-
     ting  base  returned by format_init().  If two braces are equal, the result
     is undefined.  handler is the function which should be defined as

     char ** handler(char *found, void *optKeyPassed).

     It is possible to define a number of such a rules for the single  fmt_base.
     The handler function should return the pointer to the internal char ** data
     when  it  is  possible,  and  NULL pointer otherwise. Please NOTE that this
     pointer is never modified or freed and probably it should be the  semi-sta-
     tic structure inside the handler function.

     When you're finished to fill the fmt_base with the rules, the function for-
     matf()  can be used multiple times to convert the specified template to the
     destination text. The optional optKeyToPass argument may  be  specified  to
     pass some additional data, if necessary.

     formatf()	will  place the output to the buffer located in the fmt_base and
     return a pointer to it. The pointer will never be NULL, and is  not  to  be
     freed.  If  you  need this buffer to be completely yours and do not want to
     strdup(3) it, there is a function called format_detach(fmt_base  *,  size_t
     *optReturnSize) to achive this.

     Two  other functions, char * format_lastresult(fmt_base *, size_t *optSize)
     and size_t format_lastsize(fmt_base *),  are  to  be  used  to  obtain  the
     pointer to the buffer and its size without invoking formatf() once more.

ACTIVE TEMPLATE DEFINITION
     If  a  template  is not containing the special tokens it will considered as
     plain text and returned unmodified.

     Special token and the whole template are defined in the following BNF:

	   <template>  :=  *(*<string> *<token> *<string>)

	   <token>     :=  <simple> | <join> | <index> | <choice> | <equality>

	   <simple>    :=  '$' <LB> <param> <RB>

	   <join>      :=  '$' <LB> <param> '+' <delimiter> <RB>

	   <index>     :=  '$' <LB> <param> '[' <number> ']' <RB>

	   <choice>    :=  '$' <LB> <param> '?' <iftrue> ':' <iffalse> <RB>

	   <equality>  :=  '$' <LB> <param> { "==" | "!=" } *<string> '?' <iftrue> ':' <iffalse> <RB>

	   <LB>        :=  <the second argument of format_metarule()>

	   <RB>        :=  <the third argument of format_metarule()>

	   <param>     := <string>

	   <delimiter> := <string>

	   <iftrue>    := <template>

	   <iffalse>   := <template>

	   <string>    :=  *<CHAR>

	   <number>    :=  1*<character from '0' to '9'>

     The word param defined above, will be passed as the first argument  to  the
     handler function.

ACTIVE TEMPLATE EXAMPLE
     The  following is an example of the typical template. It may be placed to a
     file, then read and passed to formatf().  It is also can be defined as  the
     argument's value within the configuration file read by cfgread(3).

	   Login: ${login[0]}
	   Password: ${password}
	   Username: ${name?${name}:Unknown name}
	   Comments: ${comment+, }
	   $<status==Busy?User is busy>

     You  can see the index token "${login[0]}", the simple token "${password}",
     the join token right after the "Comments: ",  and	equality  token  is  the
     whole  last string. Please note that the last token is formed using the an-
     gle braces: you should specify an additional  handler  function  to  handle
     this case. Refer to the PROGRAMMING EXAMPLE section.

     Simple  tokens are used to display the data returned by the handler() func-
     tion almost without the modification. One exception from this rule  exists:
     if  handler return multiple values they are joined together with the string
     ", " as the separator.

     Join tokens are used to join the multiple values. As mentioned  above,  the
     handler  function	return the string array. In this case all values will be
     joined together separated by the specified delimiter. For this  primer  the
     delimiter is ", " (comma followed by single space).

     Index  token used to get the specified value from the string array returned
     by handler.  Values are counted from zero, so zero index will represent the
     first available string.

     Choice token used to give	the  dynamic  behavior	to  the  templates.  The
     <iftrue>  section will be placed to the output buffer if the handler return
     the valid non-NULL pointer to the non-empty array. This form can be used to
     rule the output if the expected parameter is not present or empty.

     Equality token used to test the array returned by the handler  against  the
     string  value.  The <iftrue> section will be placed to the output buffer if
     this string match at least one of the array's elements. All comparisons are
     canse-insensitive.

PROGRAMMING EXAMPLE
     Here's how to implement the above template example's parsing.

     #include <strfunc.h>

     char **handler1(char *found, void *optKeyPassed);
     char **handler2(char *found, void *optKeyPassed);

     int
     main() {
	     fmt_base *fb;
	     char *template = "Login: ${login[0]}\nPassword: ${password}\nUsername: ${name?${name}:Unknown name}\nComments: ${comment+, }\n$<status==Busy?User is busy>\n";
	     char *s;

	     /* Create empty structure */
	     fb = format_init();

	     /* Add one formatting rule */
	     format_metarule(fb, '{', '}', handler1);

	     /* Add another formatting rule to parse angle braces */
	     format_metarule(fb, '<', '>', handler1);

	     /* Format the template */
	     s = formatf(fb, template, NULL);

	     /* Print out the result */
	     printf("%s", s);

	     /* Free the formatting structure */
	     format_free(fb);

	     return 0;
     };

     char **
     handler1(char *found, void *optKeyPassed) {
	     static char *arr[3] = { NULL, NULL, NULL };

	     (void)optKeyPassed;

	     arr[1] = NULL;

	     if(strcasecmp(found, "login") == 0) {
		     arr[0] = "john";
		     return arr;
	     };

	     if(strcasecmp(found, "name") == 0) {
		     arr[0] = "John Smith";
		     return arr;
	     };

	     if(strcasecmp(found, "password") == 0) {
		     arr[0] = "123";
		     return arr;
	     };

	     if(strcasecmp(found, "comment") == 0) {
		     arr[0] = "Comment value #1";
		     arr[1] = "Comment value #2";
		     return arr;
	     };

	     return NULL;
     };

     char **
     handler2(char *found, void *optKeyPassed) {
	     static char *arr[] = { NULL, NULL };

	     (void)optKeyPassed;

	     if(strcasecmp(found, status) == 0) {
		     arr[0] = "busy";
		     return arr;
	     };

	     return NULL;
     };

SEE ALSO
     strfunc(3), cfgread(3).

AUTHORS
     Lev Walkin <vlm@lionet.info>

FreeBSD ports 15.quarterly	 October 1, 2000		       sf_fmt(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=format_lastresult&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help