Perform expansion of a template string and return the result as a newly * allocated sds. * * Template variables are specified using curly brackets, e.g. {variable}. * An opening bracket can be quoted by repeating it twice. */
| 1172 | * An opening bracket can be quoted by repeating it twice. |
| 1173 | */ |
| 1174 | sds sdstemplate(const char *template, sdstemplate_callback_t cb_func, void *cb_arg) |
| 1175 | { |
| 1176 | sds res = sdsempty(); |
| 1177 | const char *p = template; |
| 1178 | |
| 1179 | while (*p) { |
| 1180 | /* Find next variable, copy everything until there */ |
| 1181 | const char *sv = strchr(p, '{'); |
| 1182 | if (!sv) { |
| 1183 | /* Not found: copy till rest of template and stop */ |
| 1184 | res = sdscat(res, p); |
| 1185 | break; |
| 1186 | } else if (sv > p) { |
| 1187 | /* Found: copy anything up to the begining of the variable */ |
| 1188 | res = sdscatlen(res, p, sv - p); |
| 1189 | } |
| 1190 | |
| 1191 | /* Skip into variable name, handle premature end or quoting */ |
| 1192 | sv++; |
| 1193 | if (!*sv) goto error; /* Premature end of template */ |
| 1194 | if (*sv == '{') { |
| 1195 | /* Quoted '{' */ |
| 1196 | p = sv + 1; |
| 1197 | res = sdscat(res, "{"); |
| 1198 | continue; |
| 1199 | } |
| 1200 | |
| 1201 | /* Find end of variable name, handle premature end of template */ |
| 1202 | const char *ev = strchr(sv, '}'); |
| 1203 | if (!ev) goto error; |
| 1204 | |
| 1205 | /* Pass variable name to callback and obtain value. If callback failed, |
| 1206 | * abort. */ |
| 1207 | sds varname = sdsnewlen(sv, ev - sv); |
| 1208 | sds value = cb_func(varname, cb_arg); |
| 1209 | sdsfree(varname); |
| 1210 | if (!value) goto error; |
| 1211 | |
| 1212 | /* Append value to result and continue */ |
| 1213 | res = sdscat(res, value); |
| 1214 | sdsfree(value); |
| 1215 | p = ev + 1; |
| 1216 | } |
| 1217 | |
| 1218 | return res; |
| 1219 | |
| 1220 | error: |
| 1221 | sdsfree(res); |
| 1222 | return NULL; |
| 1223 | } |
| 1224 | |
| 1225 | #ifdef REDIS_TEST |
| 1226 | #include <stdio.h> |