]> git.wh0rd.org - fontconfig.git/commitdiff
[fcformat] Add element filtering and deletion
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 10 Feb 2009 04:08:08 +0000 (23:08 -0500)
committerBehdad Esfahbod <behdad@behdad.org>
Sun, 15 Feb 2009 21:40:26 +0000 (13:40 -0800)
The filtering, '%{+elt1,elt2,elt3{subexpr}}' will evaluate subexpr
with a pattern only having the listed elements from the surrounding
pattern.

The deletion, '%{-elt1,elt2,elt3{subexpr}}' will evaluate subexpr
with a the surrounding pattern sans the listed elements.

doc/fcpattern.fncs
fc-list/fc-list.c
fc-match/fc-match.c
fc-query/fc-query.c
fc-scan/fc-scan.c
src/fcformat.c

index 22a89ad689fae16b8c7160b6fc9a0983872b5a0e..35ef68bdfbf9eb04da21ff638250c398bd270262 100644 (file)
@@ -413,5 +413,5 @@ pattern, use the format "%{family} %{style}\n".
 There can be an option width specifier after the percent sign and before
 the opening brace.  The width modifier acts similar to those in printf.
 The return value refers to newly allocated memory which should be freed by the
-caller using free().
+caller using free(), or NULL if <parameter>format</parameter> is invalid.
 @@
index 470b4b9323156b7d92fa5ac822d481179077f07b..cbcc3c0de0ab8aaf175a11c69abe5c3e49bdf85b 100644 (file)
@@ -178,8 +178,11 @@ main (int argc, char **argv)
                FcChar8 *s;
 
                s = FcPatternFormat (fs->fonts[j], format);
-               printf ("%s", s);
-               free (s);
+               if (s)
+               {
+                   printf ("%s", s);
+                   free (s);
+               }
            }
            else
            {
index 6f3d2dc81dc4303d152990816d7110314aa34d0c..86ff25387b09e02b4a085927ee99dc8092126027 100644 (file)
@@ -214,7 +214,11 @@ main (int argc, char **argv)
                FcChar8 *s;
 
                s = FcPatternFormat (font, format);
-               free (s);
+               if (s)
+               {
+                   printf ("%s", s);
+                   free (s);
+               }
            }
            else if (os)
            {
index 8c5672c6a7c04c3aa818f84d69b96ea0b0e0f09e..4d707bc1a5fc1af4d6cb4970a90623063ef1e1f8 100644 (file)
@@ -162,8 +162,11 @@ main (int argc, char **argv)
                    FcChar8 *s;
 
                    s = FcPatternFormat (pat, format);
-                   printf ("%s", s);
-                   free (s);
+                   if (s)
+                   {
+                       printf ("%s", s);
+                       free (s);
+                   }
                }
                else
                {
index 573f7ef5343f85f7d3bc5c338c63b61c04c6b007..1f023fb3faf0711c088ce38e3cc044c0e8dd58f4 100644 (file)
@@ -165,8 +165,11 @@ main (int argc, char **argv)
            FcChar8 *s;
 
            s = FcPatternFormat (pat, format);
-           printf ("%s", s);
-           free (s);
+           if (s)
+           {
+               printf ("%s", s);
+               free (s);
+           }
        }
        else
        {
index 30c5a8d3bb3c935ff245ac02116c4b0f91ca90f8..31f3a744af1f9bf9caba2b036316dd90e02ee13e 100644 (file)
@@ -33,7 +33,7 @@ message (const char *fmt, ...)
 {
     va_list    args;
     va_start (args, fmt);
-    fprintf (stderr, "Fontconfig: Pattern format error:");
+    fprintf (stderr, "Fontconfig: Pattern format error: ");
     vfprintf (stderr, fmt, args);
     fprintf (stderr, ".\n");
     va_end (args);
@@ -48,13 +48,15 @@ typedef struct _FcFormatContext
     FcChar8       *scratch;
 } FcFormatContext;
 
-static void
+static FcBool
 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);
+
+    return c->scratch != NULL;
 }
 
 static void
@@ -147,60 +149,36 @@ read_elt_name_to_scratch (FcFormatContext *c)
     return FcTrue;
 }
 
-static void
+static FcBool
 interpret (FcFormatContext *c,
           FcPattern       *pat,
           FcStrBuf        *buf,
           FcChar8          term);
 
-static void
-interpret_percent (FcFormatContext *c,
+static FcBool
+interpret_subexpr (FcFormatContext *c,
                   FcPattern       *pat,
                   FcStrBuf        *buf)
 {
-    int           width, before;
-    FcChar8      *p;
-    FcPatternElt *e;
+    return expect_char (c, '{') &&
+          interpret (c, pat, buf, '}') &&
+          expect_char (c, '}');
+}
 
-    FcPattern    *subpat = pat;
+static FcBool
+interpret_simple_tag (FcFormatContext *c,
+                     FcPattern       *pat,
+                     FcStrBuf        *buf)
+{
+    FcPatternElt *e;
     FcBool        add_colon = FcFalse;
     FcBool        add_elt_name = FcFalse;
 
-    if (!expect_char (c, '%'))
-       return;
-
-    if (consume_char (c, '%')) /* "%%" */
-    {
-       FcStrBufChar (buf, '%');
-       return;
-    }
-
-    /* parse an optional width specifier */
-    width = strtol ((const char *) c->format, (char **) &c->format, 10);
-
-    before = buf->len;
-
-    if (!expect_char (c, '{'))
-       goto bail;
-
-    if (consume_char (c, '{'))
-    {
-       /* it's just a subexpression.  no tag involved */
-       interpret (c, pat, buf, '}');
-       expect_char (c, '}');
-       goto filter;
-    }
-
-    switch (*c->format) {
-    case ':':
+    if (consume_char (c, ':'))
        add_colon = FcTrue;
-       consume_char (c, ':');
-       break;
-    }
 
-parse_tag:
     if (!read_elt_name_to_scratch (c))
-        goto bail;
+       return FcFalse;
 
     if (consume_char (c, '='))
        add_elt_name = FcTrue;
@@ -223,7 +201,131 @@ parse_tag:
        FcNameUnparseValueList (buf, l, '\0');
     }
 
-filter:
+    return FcTrue;
+}
+
+static FcBool
+interpret_filter (FcFormatContext *c,
+                 FcPattern       *pat,
+                 FcStrBuf        *buf)
+{
+    FcObjectSet  *os;
+    FcPattern    *subpat;
+
+    if (!expect_char (c, '+'))
+       return FcFalse;
+
+    os = FcObjectSetCreate ();
+    if (!os)
+       return FcFalse;
+
+    do
+    {
+       if (!read_elt_name_to_scratch (c) ||
+           !FcObjectSetAdd (os, (const char *) c->scratch))
+       {
+           FcObjectSetDestroy (os);
+           return FcFalse;
+       }
+    }
+    while (consume_char (c, ','));
+
+    subpat = FcPatternFilter (pat, os);
+    FcObjectSetDestroy (os);
+
+    if (!subpat ||
+       !interpret_subexpr (c, subpat, buf))
+       return FcFalse;
+
+    FcPatternDestroy (subpat);
+    return FcTrue;
+}
+
+static FcBool
+interpret_delete (FcFormatContext *c,
+                 FcPattern       *pat,
+                 FcStrBuf        *buf)
+{
+    FcPattern    *subpat;
+
+    if (!expect_char (c, '-'))
+       return FcFalse;
+
+    subpat = FcPatternDuplicate (pat);
+    if (!subpat)
+       return FcFalse;
+
+    do
+    {
+       if (!read_elt_name_to_scratch (c))
+       {
+           FcPatternDestroy (subpat);
+           return FcFalse;
+       }
+
+       FcPatternDel (subpat, (const char *) c->scratch);
+    }
+    while (consume_char (c, ','));
+
+    if (!interpret_subexpr (c, subpat, buf))
+       return FcFalse;
+
+    FcPatternDestroy (subpat);
+    return FcTrue;
+}
+
+static FcBool
+interpret_percent (FcFormatContext *c,
+                  FcPattern       *pat,
+                  FcStrBuf        *buf)
+{
+    int           width, before;
+
+    if (!expect_char (c, '%'))
+       return FcFalse;
+
+    if (consume_char (c, '%')) /* "%%" */
+    {
+       FcStrBufChar (buf, '%');
+       return FcTrue;
+    }
+
+    /* parse an optional width specifier */
+    width = strtol ((const char *) c->format, (char **) &c->format, 10);
+
+    before = buf->len;
+
+    if (!expect_char (c, '{'))
+       return FcFalse;
+
+    switch (*c->format) {
+
+    case '{':
+       /* subexpression */
+       if (!interpret_subexpr (c, pat, buf))
+           return FcFalse;
+       break;
+
+    case '+':
+       /* filtering pattern elements */
+       if (!interpret_filter (c, pat, buf))
+           return FcFalse;
+       break;
+
+    case '-':
+       /* deleting pattern elements */
+       if (!interpret_delete (c, pat, buf))
+           return FcFalse;
+       break;
+
+    default:
+       /* simple tag */
+       if (!interpret_simple_tag (c, pat, buf))
+           return FcFalse;
+       break;
+
+    }
+
     /* handle filters, if any */
     /* XXX */
 
@@ -257,11 +359,7 @@ filter:
        }
     }
 
-    expect_char (c, '}');
-
-bail:
-    if (subpat != pat)
-       FcPatternDestroy (subpat);
+    return expect_char (c, '}');
 }
 
 static char escaped_char(const char ch)
@@ -278,7 +376,7 @@ static char escaped_char(const char ch)
     }
 }
 
-static void
+static FcBool
 interpret (FcFormatContext *c,
           FcPattern       *pat,
           FcStrBuf        *buf,
@@ -294,11 +392,13 @@ interpret (FcFormatContext *c,
                FcStrBufChar (buf, escaped_char (*c->format++));
            continue;
        case '%':
-           interpret_percent (c, pat, buf);
+           if (!interpret_percent (c, pat, buf))
+               return FcFalse;
            continue;
        }
        FcStrBufChar (buf, *c->format++);
     }
+    return FcTrue;
 }
 
 FcChar8 *
@@ -306,14 +406,24 @@ FcPatternFormat (FcPattern *pat, const FcChar8 *format)
 {
     FcStrBuf buf;
     FcFormatContext c;
+    FcBool ret;
 
     FcStrBufInit (&buf, 0, 0);
-    FcFormatContextInit (&c, format);
+    if (!FcFormatContextInit (&c, format))
+       return NULL;
 
-    interpret (&c, pat, &buf, '\0');
+    ret = interpret (&c, pat, &buf, '\0');
+    if (buf.failed)
+       ret = FcFalse;
 
     FcFormatContextDone (&c);
-    return FcStrBufDone (&buf);
+    if (ret)
+       return FcStrBufDone (&buf);
+    else
+    {
+       FcStrBufDestroy (&buf);
+       return NULL;
+    }
 }
 
 #define __fcformat__