c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#ifndef VAR_EXPAND_H
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#define VAR_EXPAND_H
4cb2599c5cdf27362a66ac475ce295409c093c92Timo Sirainen
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainenstruct var_expand_table {
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen char key;
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen const char *value;
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen const char *long_key;
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen};
4cb2599c5cdf27362a66ac475ce295409c093c92Timo Sirainen
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainenstruct var_expand_func_table {
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainen const char *key;
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen /* %{key:data}, or data is "" with %{key}.
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen Returns 1 on success, 0 if data is invalid, -1 on temporary error. */
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen int (*func)(const char *data, void *context,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen const char **value_r, const char **error_r);
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainen};
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainen
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen/* Expand % variables in src and append the string in dest.
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen table must end with key = 0. Returns 1 on success, 0 if the format string
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen contained invalid/unknown %variables, -1 if one of the functions returned
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen temporary error. Even in case of errors the dest string is still written as
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen fully as possible. */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenint var_expand(string_t *dest, const char *str,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct var_expand_table *table,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char **error_r);
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainen/* Like var_expand(), but support also callback functions for
e130dc7c712a10215b1e6be56403bbb934826251Timo Sirainen variable expansion. */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenint var_expand_with_funcs(string_t *dest, const char *str,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct var_expand_table *table,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const struct var_expand_func_table *func_table,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen void *func_context, const char **error_r) ATTR_NULL(3, 4, 5);
4cb2599c5cdf27362a66ac475ce295409c093c92Timo Sirainen
ee3cb11d230d549367a1213aefe4598345796256Timo Sirainen/* Returns the actual key character for given string, ie. skip any modifiers
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainen that are before it. The string should be the data after the '%' character.
7a556ac46f1f51ee29bc8aa92b5ffe05b004a8b8Timo Sirainen For %{long_variable}, '{' is returned. */
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenchar var_get_key(const char *str) ATTR_PURE;
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen/* Similar to var_get_key(), but works for long keys as well. For single char
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen keys size=1, while for e.g. %{key} size=3 and idx points to 'k'. */
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainenvoid var_get_key_range(const char *str, unsigned int *idx_r,
b58cb4b59ccd78ee1c3e0df0bc13c300d1bec380Timo Sirainen unsigned int *size_r);
e539ff946adcbc68793adb6d9d84621dce3bf46bTimo Sirainen/* Returns TRUE if key variable is used in the string.
e539ff946adcbc68793adb6d9d84621dce3bf46bTimo Sirainen If key is '\0', it's ignored. If long_key is NULL, it's ignored. */
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainenbool var_has_key(const char *str, char key, const char *long_key) ATTR_PURE;
ee3cb11d230d549367a1213aefe4598345796256Timo Sirainen
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomistatic inline size_t ATTR_PURE
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomivar_expand_table_size(const struct var_expand_table *table)
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi{
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi size_t n = 0;
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi while(table != NULL && (table[n].key != '\0' ||
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi table[n].long_key != NULL))
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi n++;
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi return n;
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi}
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomistruct var_expand_table *
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomivar_expand_merge_tables(pool_t pool, const struct var_expand_table *a,
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi const struct var_expand_table *b);
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi#define t_var_expand_merge_tables(a, b) \
857a9e1f1cf3a2241403bfb201421bb1a66038b1Aki Tuomi (const struct var_expand_table *)var_expand_merge_tables(pool_datastack_create(), (a), (b))
4cb2599c5cdf27362a66ac475ce295409c093c92Timo Sirainen#endif