[fcformat] Implement 'cescape', 'shescape', and 'xmlescape' converters

This commit is contained in:
Behdad Esfahbod 2009-02-10 04:44:54 -05:00
parent 2017a5eb79
commit ced38254b4
1 changed files with 76 additions and 11 deletions

View File

@ -31,6 +31,7 @@
/* /*
* Some ideas for future syntax extensions: * Some ideas for future syntax extensions:
* *
* - number of values for element using '%{#elt}'
* - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}' * - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}'
* - allow indexing simple tags using '%{elt[idx]}' * - allow indexing simple tags using '%{elt[idx]}'
* - conditional/filtering/deletion on binding (using '(w)'/'(s)' notation) * - conditional/filtering/deletion on binding (using '(w)'/'(s)' notation)
@ -414,18 +415,83 @@ interpret_cond (FcFormatContext *c,
return FcTrue; return FcTrue;
} }
static FcChar8 *
cescape (const FcChar8 *str)
{
FcStrBuf buf;
FcChar8 buf_static[8192];
FcStrBufInit (&buf, buf_static, sizeof (buf_static));
while(*str)
{
switch (*str)
{
case '\\':
case '"':
FcStrBufChar (&buf, '\\');
break;
}
FcStrBufChar (&buf, *str++);
}
return FcStrBufDone (&buf);
}
static FcChar8 *
shescape (const FcChar8 *str)
{
FcStrBuf buf;
FcChar8 buf_static[8192];
FcStrBufInit (&buf, buf_static, sizeof (buf_static));
FcStrBufChar (&buf, '\'');
while(*str)
{
if (*str == '\'')
FcStrBufString (&buf, (const FcChar8 *) "'\\''");
else
FcStrBufChar (&buf, *str);
str++;
}
FcStrBufChar (&buf, '\'');
return FcStrBufDone (&buf);
}
static FcChar8 *
xmlescape (const FcChar8 *str)
{
FcStrBuf buf;
FcChar8 buf_static[8192];
FcStrBufInit (&buf, buf_static, sizeof (buf_static));
while(*str)
{
switch (*str)
{
case '&': FcStrBufString (&buf, (const FcChar8 *) "&"); break;
case '<': FcStrBufString (&buf, (const FcChar8 *) "&lt;"); break;
case '>': FcStrBufString (&buf, (const FcChar8 *) "&gt;"); break;
default: FcStrBufChar (&buf, *str); break;
}
str++;
}
return FcStrBufDone (&buf);
}
static FcChar8 * static FcChar8 *
convert (FcFormatContext *c, convert (FcFormatContext *c,
const FcChar8 *str) const FcChar8 *str)
{ {
if (!read_word (c)) if (!read_word (c))
return NULL; return NULL;
else if (0 == strcmp ((const char *) c->word, "downcase")) #define CONVERTER(name, func) \
return FcStrDowncase (str); else if (0 == strcmp ((const char *) c->word, name))\
else if (0 == strcmp ((const char *) c->word, "basename")) return func (str)
return FcStrBasename (str); CONVERTER ("downcase", FcStrDowncase);
else if (0 == strcmp ((const char *) c->word, "dirname")) CONVERTER ("basename", FcStrBasename);
return FcStrDirname (str); CONVERTER ("dirname", FcStrDirname);
CONVERTER ("cescape", cescape);
CONVERTER ("shescape", shescape);
CONVERTER ("xmlescape", xmlescape);
message ("unknown converter \"%s\"", message ("unknown converter \"%s\"",
c->word); c->word);
@ -579,16 +645,15 @@ FcChar8 *
FcPatternFormat (FcPattern *pat, const FcChar8 *format) FcPatternFormat (FcPattern *pat, const FcChar8 *format)
{ {
FcStrBuf buf; FcStrBuf buf;
FcChar8 buf_static[8192];
FcFormatContext c; FcFormatContext c;
FcBool ret; FcBool ret;
FcStrBufInit (&buf, 0, 0); FcStrBufInit (&buf, buf_static, sizeof (buf_static));
if (!FcFormatContextInit (&c, format)) if (!FcFormatContextInit (&c, format))
return NULL; return NULL;
ret = interpret_expr (&c, pat, &buf, '\0'); ret = interpret_expr (&c, pat, &buf, '\0');
if (buf.failed)
ret = FcFalse;
FcFormatContextDone (&c); FcFormatContextDone (&c);
if (ret) if (ret)