[fcformat] Refactor and restructure code for upcoming changes

Also makes it thread-safe.
This commit is contained in:
Behdad Esfahbod 2009-02-09 19:13:07 -05:00
parent c493c3b770
commit 27b3e2dddf
1 changed files with 96 additions and 69 deletions

View File

@ -40,58 +40,96 @@ message (const char *fmt, ...)
} }
static FcChar8 *scratch1; typedef struct _FcFormatContext
static FcChar8 *scratch2; {
static const FcChar8 *format_orig; const FcChar8 *format_orig;
const FcChar8 *format;
int format_len;
FcChar8 *scratch;
} FcFormatContext;
static const FcChar8 * static void
interpret_percent (FcPattern *pat, FcFormatContextInit (FcFormatContext *c,
FcStrBuf *buf, const FcChar8 *format)
const FcChar8 *format) {
c->format_orig = c->format = format;
c->format_len = strlen ((const char *) format);
c->scratch = malloc (c->format_len + 1);
}
static void
FcFormatContextDone (FcFormatContext *c)
{
if (c)
{
free (c->scratch);
}
}
static FcBool
consume_char (FcFormatContext *c,
FcChar8 term)
{
if (*c->format != term)
{
message ("Pattern format error: expected '%c' at %d",
term, c->format - c->format_orig + 1);
return FcFalse;
}
c->format++;
return FcTrue;
}
static void
interpret_percent (FcFormatContext *c,
FcPattern *pat,
FcStrBuf *buf)
{ {
int width, before; int width, before;
FcChar8 *p;
FcPatternElt *e;
if (!consume_char (c, '%'))
return;
if (*c->format == '%') /* "%%" */
{
FcStrBufChar (buf, *c->format++);
return;
}
/* parse an optional width specifier */ /* parse an optional width specifier */
width = strtol (format, (char **) &format, 10); width = strtol ((const char *) c->format, (char **) &c->format, 10);
before = buf->len; before = buf->len;
switch (*format) { if (!consume_char (c, '{'))
case '{': return;
p = (FcChar8 *) strpbrk ((const char *) c->format, "}" /* "=?:}" */);
if (!p)
{ {
FcChar8 *p; message ("Pattern format missing closing brace for opening brace at %d",
FcPatternElt *e; c->format-1 - c->format_orig + 1);
return;
format++; /* skip over '{' */
p = (FcChar8 *) strpbrk ((const char *) format, "}");
if (!p)
{
message ("Pattern format missing closing brace");
break;
}
/* extract the element name */
memcpy (scratch1, format, p - format);
scratch1[p - format] = '\0';
e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) scratch1));
if (e)
{
FcValueListPtr l;
l = FcPatternEltValues(e);
FcNameUnparseValueList (buf, l, '\0');
}
p++; /* skip over '}' */
format = p;
break;
} }
default: /* extract the element name */
message ("Pattern format has invalid character after '%%' at %d", memcpy (c->scratch, c->format, p - c->format);
format - format_orig); c->scratch[p - c->format] = '\0';
break; c->format = p;
e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) c->scratch));
if (e)
{
FcValueListPtr l;
l = FcPatternEltValues(e);
FcNameUnparseValueList (buf, l, '\0');
} }
/* handle filters, if any */
/* XXX */
/* align to width */ /* align to width */
if (!buf->failed) if (!buf->failed)
{ {
@ -122,7 +160,7 @@ interpret_percent (FcPattern *pat,
} }
} }
return format; consume_char (c, '}');
} }
static char escaped_char(const char ch) static char escaped_char(const char ch)
@ -139,54 +177,43 @@ static char escaped_char(const char ch)
} }
} }
static const FcChar8 * static void
interpret (FcPattern *pat, interpret (FcFormatContext *c,
FcStrBuf *buf, FcPattern *pat,
const FcChar8 *format, FcStrBuf *buf,
FcChar8 term) FcChar8 term)
{ {
const FcChar8 *end; for (; *c->format && *c->format != term;)
for (end = format; *end && *end != term;)
{ {
switch (*end) switch (*c->format)
{ {
case '\\': case '\\':
end++; /* skip over '\\' */ c->format++; /* skip over '\\' */
FcStrBufChar (buf, escaped_char (*end++)); if (*c->format)
FcStrBufChar (buf, escaped_char (*c->format++));
continue; continue;
case '%': case '%':
end++; /* skip over '%' */ interpret_percent (c, pat, buf);
if (*end == '%')
break;
end = interpret_percent (pat, buf, end);
continue; continue;
} }
FcStrBufChar (buf, *end); FcStrBufChar (buf, *c->format++);
end++;
} }
if (*end != term) if (*c->format != term)
message ("Pattern format ended while looking for '%c'", term); message ("Pattern format ended while looking for '%c'", term);
return end;
} }
FcChar8 * FcChar8 *
FcPatternFormat (FcPattern *pat, const FcChar8 *format) FcPatternFormat (FcPattern *pat, const FcChar8 *format)
{ {
int len;
FcStrBuf buf; FcStrBuf buf;
FcFormatContext c;
FcStrBufInit (&buf, 0, 0); FcStrBufInit (&buf, 0, 0);
len = strlen ((const char *) format); FcFormatContextInit (&c, format);
scratch1 = malloc (len);
scratch2 = malloc (len);
format_orig = format;
interpret (pat, &buf, format, '\0'); interpret (&c, pat, &buf, '\0');
free (scratch1); FcFormatContextDone (&c);
free (scratch2);
return FcStrBufDone (&buf); return FcStrBufDone (&buf);
} }