[fcformat] Refactor and restructure code for upcoming changes
Also makes it thread-safe.
This commit is contained in:
parent
c493c3b770
commit
27b3e2dddf
165
src/fcformat.c
165
src/fcformat.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue