C++ wrapper for cgul_varsub
More...
#include "cgul_convspec_cxx.h"
#include "cgul_exception_cxx.h"
#include "cgul_string_cxx.h"
#include "cgul_varsub.h"
Typedefs | |
typedef int(* | cgul_varsub_cxx__lookup_t) (const char *varname, cgul_string_cxx *dst, void *data) |
typedef int(* | cgul_varsub_formatted_cxx__lookup_t) (const char *varname, cgul_convspec_cxx *cs, cgul_string_cxx *dst, void *data) |
Functions | |
int | cgul_varsub_cxx__callback_adaptor (cgul_exception_t *cex, const char *varname, cgul_string_t dst, void *data) |
int | cgul_varsub_formatted_cxx__callback_adaptor (cgul_exception_t *cex, const char *varname, cgul_convspec_t cs, cgul_string_t dst, void *data) |
void | cgul_varsub_cxx (const char *src, cgul_string_cxx *dst, cgul_varsub_cxx__lookup_t f, void *data) |
void | cgul_varsub_formatted_cxx (const char *src, cgul_string_cxx *dst, cgul_varsub_formatted_cxx__lookup_t f, void *data) |
C++ wrapper for cgul_varsub
.
typedef int(* cgul_varsub_cxx__lookup_t) (const char *varname, cgul_string_cxx *dst, void *data) |
This typedef defines the lookup function used by cgul_varsub_cxx()
to substitute a variable with its value. When cgul_varsub_cxx()
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_cxx()
. 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_cxx()
will know to insert varname
into dst
literally.
If an error occurs during the execution of the lookup function, it should be handled in the lookup function. If the lookup function lets a C++ exception escape, it will be quashed by cgul_varsub_cxx__callback_adaptor()
to avoid having the C++ exception stomp on the C stack.
[in] | varname | variable name |
[in,out] | dst | destination string |
[in] | data | client data |
typedef int(* cgul_varsub_formatted_cxx__lookup_t) (const char *varname, cgul_convspec_cxx *cs, cgul_string_cxx *dst, void *data) |
This typedef defines the lookup function used by cgul_varsub_formatted_cxx()
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_cxx()
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_cxx()
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 cs->serialize()
to convert cs
to a format string that can then be used with dst->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_cxx()
. 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_cxx()
will know to insert varname
into dst
literally.
If an error occurs during the execution of the lookup function, it should be handled in the lookup function. If the lookup function lets a C++ exception escape, it will be quashed by cgul_varsub_formatted_cxx__callback_adaptor()
to avoid having the C++ exception stomp on the C stack.
[in] | varname | variable name |
[in] | cs | conversion specification or NULL |
[in,out] | dst | destination string |
[in] | data | client data |
|
inline |
The adoptor used by cgul_varsub_cxx()
as the direct callback for the C cgul_varsub()
function. It in turn calls the user's C++ callback.
[in] | cex | c-style exception |
[in] | varname | variable name |
[in,out] | dst | destination string |
[in] | data | client data |
Referenced by cgul_varsub_cxx().
|
inline |
The adoptor used by cgul_varsub_formatted_cxx()
as the direct callback for the C cgul_varsub_formatted()
function. It in turn calls the user's C++ callback.
[in,out] | cex | c-style exception |
[in] | varname | variable name |
[in] | cs | conversion specification or NULL |
[in,out] | dst | destination string |
[in] | data | client data |
Referenced by cgul_varsub_formatted_cxx().
|
inline |
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_cxx()
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_cxx.cc for a simple example of how to write a lookup function f
.
[in] | src | source string |
[out] | dst | destination string |
[in] | f | lookup function |
[in] | data | client data |
References cgul_varsub(), cgul_varsub__lookup_t, cgul_varsub_cxx__callback_adaptor(), and cgul_string_cxx::get_obj().
|
inline |
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 underlying cgul_varsub_formatted()
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 (eventually) 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 (eventually) cause f
to be passed 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_cxx.cc for an example of how to write the lookup function f
.
[in] | src | source string |
[out] | dst | destination string |
[in] | f | lookup function |
[in] | data | client data |
References cgul_varsub_formatted(), cgul_varsub_formatted_cxx__callback_adaptor(), and cgul_string_cxx::get_obj().