Code

Correcting extraction of "url(...)" for paint
authorjoncruz <joncruz@users.sourceforge.net>
Sun, 13 May 2007 07:04:40 +0000 (07:04 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Sun, 13 May 2007 07:04:40 +0000 (07:04 +0000)
src/extract-uri-test.h
src/extract-uri.cpp

index d506286217de9c5a537ffa099183b3bf0ee1c519..aa96fa24939cbbf96eae439035afa7bf126dd6e7 100644 (file)
@@ -9,27 +9,66 @@
 class ExtractURITest : public CxxTest::TestSuite
 {
 public:
+    void checkOne( char const* str, char const* expected )
+    {
+        gchar* result = extract_uri( str );
+        TS_ASSERT_EQUALS( ( result == NULL ), ( expected == NULL ) );
+        if ( result && expected ) {
+            TS_ASSERT_EQUALS( std::string(result), std::string(expected) );
+        } else if ( result ) {
+            TS_FAIL( std::string("Expected null, found (") + result + ")" );
+        } else if ( expected ) {
+            TS_FAIL( std::string("Expected (") + expected + "), found null" );
+        }
+        g_free( result );
+    }
+
     void testBase()
     {
         char const* cases[][2] = {
             { "url(#foo)", "#foo" },
-            { "url  foo  ", "foo" },
+            { "url  foo  ", NULL },
             { "url", NULL },
             { "url ", NULL },
             { "url()", NULL },
             { "url ( ) ", NULL },
-            { "url foo bar ", "foo bar" }
+            { "url foo bar ", NULL },
         };
 
         for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ )
         {
-            char const* result = extract_uri( cases[i][0] );
+            checkOne( cases[i][0], cases[i][1] );
+        }
+    }
 
-            TS_ASSERT_EQUALS( ( result == NULL ), ( cases[i][1] == NULL ) );
-            if ( result )
-            {
-                TS_ASSERT_EQUALS( std::string(result), std::string(cases[i][1]) );
-            }
+    void testWithTrailing()
+    {
+        char const* cases[][2] = {
+            { "url(#foo) bar", "#foo" },
+            { "url() bar", NULL },
+            { "url ( ) bar ", NULL }
+        };
+
+        for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ )
+        {
+            checkOne( cases[i][0], cases[i][1] );
+        }
+    }
+
+    void testQuoted()
+    {
+        char const* cases[][2] = {
+            { "url('#foo')", "#foo" },
+            { "url(\"#foo\")", "#foo" },
+            { "url('#f o o')", "#f o o" },
+            { "url(\"#f o o\")", "#f o o" },
+            { "url('#fo\"o')", "#fo\"o" },
+            { "url(\"#fo'o\")", "#fo'o" },
+        };
+
+        for ( size_t i = 0; i < G_N_ELEMENTS(cases); i++ )
+        {
+            checkOne( cases[i][0], cases[i][1] );
         }
     }
 
index dd6549c8f8b9fd660e1fe93d401bd44b4d90a220..0461f1101caa845aa90fa19f7ece885a89ee745b 100644 (file)
@@ -2,30 +2,68 @@
 #include <glib.h>
 
 // FIXME: kill this ugliness when we have a proper CSS parser
+
+// Functions as per 4.3.4 of CSS 2.1
+// http://www.w3.org/TR/CSS21/syndata.html#uri
 gchar *extract_uri(gchar const *s)
 {
+    gchar* result = 0;
     gchar const *sb = s;
     g_assert( strncmp(sb, "url", 3) == 0 );
     sb += 3;
 
+    // This first whitespace technically is not allowed.
+    // Just left in for now for legacy behavior.
     while ( ( *sb == ' ' ) ||
-            ( *sb == '(' ) )
+            ( *sb == '\t' ) )
     {
         sb++;
     }
 
-    gchar const *se = sb + strlen(sb);
-    while ( ( se[-1] == ' ' ) ||
-            ( se[-1] == ')' ) )
-    {
-        se--;
-    }
+    if ( *sb == '(' ) {
+        sb++;
+        while ( ( *sb == ' ' ) ||
+                ( *sb == '\t' ) )
+        {
+            sb++;
+        }
+
+        gchar delim = ')';
+        if ( (*sb == '\'' || *sb == '"') ) {
+            delim = *sb;
+            sb++;
+        }
+        gchar const* se = sb + 1;
+        while ( *se && (*se != delim) ) {
+            se++;
+        }
 
-    if ( sb < se ) {
-        return g_strndup(sb, se - sb);
-    } else {
-        return NULL;
+        // we found the delimiter
+        if ( *se ) {
+            if ( delim == ')' ) {
+                // back up for any trailing whitespace
+                se--;
+                while ( ( se[-1] == ' ' ) ||
+                        ( se[-1] == '\t' ) )
+                {
+                    se--;
+                }
+                result = g_strndup(sb, se - sb + 1);
+            } else {
+                gchar const* tail = se + 1;
+                while ( ( *tail == ' ' ) ||
+                        ( *tail == '\t' ) )
+                {
+                    tail++;
+                }
+                if ( *tail == ')' ) {
+                    result = g_strndup(sb, se - sb);
+                }
+            }
+        }
     }
+
+    return result;
 }
 
 /*