]> git.wh0rd.org - fontconfig.git/commitdiff
[fcformat] Refactor and restructure code for upcoming changes
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 10 Feb 2009 00:13:07 +0000 (19:13 -0500)
committerBehdad Esfahbod <behdad@behdad.org>
Sun, 15 Feb 2009 21:40:26 +0000 (13:40 -0800)
Also makes it thread-safe.

src/fcformat.c

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