cgul_varsub.h File Reference

perform variable substituion More...

#include "cgul_common.h"
#include "cgul_exception.h"
#include "cgul_string.h"
#include "cgul_convspec.h"
Include dependency graph for cgul_varsub.h:
This graph shows which files directly or indirectly include this file:

Typedefs

typedef int(* cgul_varsub_formatted__lookup_t) (cgul_exception_t *cex, const char *varname, cgul_convspec_t cs, cgul_string_t dst, void *data)
 

Functions

CGUL_EXPORT void cgul_varsub (cgul_exception_t *cex, const char *src, cgul_string_t dst, cgul_varsub__lookup_t f, void *data)
 
CGUL_EXPORT void cgul_varsub_formatted (cgul_exception_t *cex, const char *src, cgul_string_t dst, cgul_varsub_formatted__lookup_t f, void *data)
 

Variables

CGUL_BEGIN_C typedef int(* cgul_varsub__lookup_t )(cgul_exception_t *cex, const char *varname, cgul_string_t dst, void *data)
 

Detailed Description

Perform variable substitution on a string.

Author
Paul Serice

Typedef Documentation

§ cgul_varsub_formatted__lookup_t

typedef int(* cgul_varsub_formatted__lookup_t) (cgul_exception_t *cex, const char *varname, cgul_convspec_t cs, cgul_string_t dst, void *data)

This typedef defines the lookup function used by cgul_varsub_formatted() to substitute the variable varname with its value using an optional printf()-style conversion specification cs. The lookup function should not try to delete cs.

If cgul_varsub_formatted() does not find a conversion specification or if it detects that there is a problem with the conversion specification, it will set cs to NULL. Thus, the lookup function must check to make sure cs is not NULL before attempting to dereference it.

cgul_varsub_formatted() considers conversion specifications like "%*s", "%.*s", or "%*.*s" to be invalid because they serve no good purpose in this context, and they have negative security implications. The lookup function will be called with cs set to NULL if they are detected.

Thus to validate cs, the lookup function primarily needs to verify that the type of the conversion specification matches the type of the value that is being appended. After this is verified, it should then be safe to call cgul_convspec__serialize() to convert cs to a format string that can then be used with cgul_string__append_sprintf() in order to append varname to dst.

Note that the dst that is passed into the lookup function is the same dst that is passed into cgul_varsub_formatted(). By altering dst, the lookup function is directly altering the result that will be returned to the caller.

The lookup function should return 1 if the lookup was performed and substituted for varname. On the other hand, if the lookup failed, 0 should be returned so cgul_varsub_formatted() will know to insert varname into dst literally.

If an error occurs during the execution of the lookup function, it should use cex to throw a c-style exception.

Parameters
[in,out]cexc-style exception
[in]varnamevariable name
[in]csconversion specification or NULL
[in,out]dstdestination string
[in]dataclient data
Returns
whether the lookup was successful
See also
cgul_varsub_formatted()

Function Documentation

§ cgul_varsub()

CGUL_EXPORT void cgul_varsub ( cgul_exception_t cex,
const char *  src,
cgul_string_t  dst,
cgul_varsub__lookup_t  f,
void *  data 
)

This function performs variable substitution on the string src appending the result to dst. If an error occurs, an exception is thrown. If an exception is thrown, dst will contain a partial result.

The syntax for variable names embedded in src should follow the same syntax that is used by the Bourne shell. For example if name="Mr. President", "Hello, $name!" or "Hello, ${name}!" will yield "Hello, Mr. President!" after basic variable substitution is performed.

Any character can be escaped by prefixing it with the backslash character. The following conventional escape sequences produce the conventional results:

    "\a", "\b", "\t", "\n", "\v", "\f", "\r", "\\", "\$"

The client is responsible for providing the lookup function f that maps variable names to values. f is free to treat the variable names creatively. By placing the variable names in braces, it is possible to embed extra information in the source string src because the name is everything between the braces and is not limited to alphanumeric or underscore characters. f just needs to be written to handle the extra information. (See cgul_varsub_formatted() for an example of how to take advantage of this feature.)

When using braces to demarcate variable names, it is worth knowing that braces nest, and escape sequences are enabled. If you escape a brace, it will be treated like any other character at the current brace level. An escaped brace will not increase or decrease the current brace level, and it will not match any other brace.

data will be passed to f as the client data. Typically, data will hold the data needed by f to perform the lookup.

See tests/main_varsub.c for a simple example of how to write a lookup function f. See the private cgul_varsub_formatted__lookup_cb() for a more advanced example of how to write a lookup function f that takes advantage of the ability to embed extra information in the variable names.

Parameters
[in,out]cexc-style exception
[in]srcsource string
[out]dstdestination string
[in]flookup function
[in]dataclient data
See also
cgul_varsub_formatted()
cgul_varsub__lookup_t

Referenced by cgul_varsub_cxx().

§ cgul_varsub_formatted()

CGUL_EXPORT void cgul_varsub_formatted ( cgul_exception_t cex,
const char *  src,
cgul_string_t  dst,
cgul_varsub_formatted__lookup_t  f,
void *  data 
)

This function performs variable substitution on the string src appending the result to dst. If an optional printf()-style conversion specification is embedded in the variable name, it will be used to format the variable when appending to dst. If an error occurs, an exception is thrown. If an exception is thrown, dst will contain a partial result.

As explained in the comments for cgul_varsub(), it understands the Bourne shell convention of placing braces around the name of a variable. When braces are used, everything between the braces is treat as the literal name of the variable including non-alphanumeric characters. This makes it possible to embed an optional printf()-style conversion specification in the name of the variable.

This function registers a local callback with cgul_varsub() so that cgul_varsub() can parse the source string src. Each time cgul_varsub() detects a variable name, the local callback is invoked. The local callback then splits the string into the real variable name and an option printf()-style conversion specification which is then passed to f.

For example, if src is set to "${key:%32s}", cgul_varsub() will call the local callback with the variable name set to "key:%32s". The local callback will split the string into the real variable name ("key") and its conversion specification ("%32s"). The local callback will then call f passing in the real variable name and its conversion specification.

If the optional conversion specification is missing or invalid, f will be called with the conversion specification set to NULL. Conversion specifications like "%*s", "%.*s", or "%*.*s" are considered to be invalid because they serve no good purpose in this context, and they have negative security implications.

Any character can be escaped by prefixing it with the backslash character. The following conventional escape sequences produce the conventional results:

    "\a", "\b", "\t", "\n", "\v", "\f", "\r", "\\", "\$"

data will be passed to f as the client data. Typically, data will hold the data needed by f to perform the lookup.

See tests/main_varsub_formatted.c for an example of how to write the lookup function f.

Parameters
[in,out]cexc-style exception
[in]srcsource string
[out]dstdestination string
[in]flookup function
[in]dataclient data
See also
cgul_varsub()
cgul_varsub_formatted__lookup_t

Referenced by cgul_varsub_formatted_cxx().

Variable Documentation

§ cgul_varsub__lookup_t

CGUL_BEGIN_C typedef int(* cgul_varsub__lookup_t) (cgul_exception_t *cex, const char *varname, cgul_string_t dst, void *data)

This typedef defines the lookup function used by cgul_varsub() to substitute a variable with its value. When cgul_varsub() encounters a variable, it passes the name of the variable to the lookup function in varname. The lookup function should then append the value associated with varname to the destination string dst.

Note that the dst that is passed into the lookup function is the same dst that is passed into cgul_varsub(). By altering dst, the lookup function is directly altering the result that will be returned to the caller.

The lookup function should return 1 if the lookup was performed and substituted for varname. On the other hand, if the lookup failed, 0 should be returned so cgul_varsub() will know to insert varname into dst literally.

If an error occurs during the execution of the lookup function, it should use cex to throw a c-style exception.

Parameters
[in,out]cexc-style exception
[in]varnamevariable name
[in,out]dstdestination string
[in]dataclient data
Returns
whether the lookup was successful
See also
cgul_varsub()

Referenced by cgul_varsub_cxx().