[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:
*
* - number of values for element using '%{#elt}'
* - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}'
* - allow indexing simple tags using '%{elt[idx]}'
* - conditional/filtering/deletion on binding (using '(w)'/'(s)' notation)
@ -414,18 +415,83 @@ interpret_cond (FcFormatContext *c,
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 *
convert (FcFormatContext *c,
const FcChar8 *str)
{
if (!read_word (c))
return NULL;
else if (0 == strcmp ((const char *) c->word, "downcase"))
return FcStrDowncase (str);
else if (0 == strcmp ((const char *) c->word, "basename"))
return FcStrBasename (str);
else if (0 == strcmp ((const char *) c->word, "dirname"))
return FcStrDirname (str);
#define CONVERTER(name, func) \
else if (0 == strcmp ((const char *) c->word, name))\
return func (str)
CONVERTER ("downcase", FcStrDowncase);
CONVERTER ("basename", FcStrBasename);
CONVERTER ("dirname", FcStrDirname);
CONVERTER ("cescape", cescape);
CONVERTER ("shescape", shescape);
CONVERTER ("xmlescape", xmlescape);
message ("unknown converter \"%s\"",
c->word);
@ -578,17 +644,16 @@ interpret_expr (FcFormatContext *c,
FcChar8 *
FcPatternFormat (FcPattern *pat, const FcChar8 *format)
{
FcStrBuf buf;
FcStrBuf buf;
FcChar8 buf_static[8192];
FcFormatContext c;
FcBool ret;
FcBool ret;
FcStrBufInit (&buf, 0, 0);
FcStrBufInit (&buf, buf_static, sizeof (buf_static));
if (!FcFormatContextInit (&c, format))
return NULL;
ret = interpret_expr (&c, pat, &buf, '\0');
if (buf.failed)
ret = FcFalse;
FcFormatContextDone (&c);
if (ret)