<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -140,10 +140,27 @@ operators are supported:
 * Arithmetic: &lt;tt&gt;+&lt;/tt&gt;, &lt;tt&gt;-&lt;/tt&gt;, &lt;tt&gt;*&lt;/tt&gt;, &lt;tt&gt;/&lt;/tt&gt;, &lt;tt&gt;%&lt;/tt&gt;
 * Comparison: &lt;tt&gt;&lt;&lt;/tt&gt;, &lt;tt&gt;&lt;=&lt;/tt&gt;, &lt;tt&gt;&gt;&lt;/tt&gt;, &lt;tt&gt;&gt;=&lt;/tt&gt;
 * Equality: &lt;tt&gt;=&lt;/tt&gt; for equality, &lt;tt&gt;!=&lt;/tt&gt; for inequality
+* String matching: &lt;tt&gt;=&lt;/tt&gt; for case-sensitive matching, &lt;tt&gt;~&lt;/tt&gt; for case-insensitive
 * Logic: &lt;tt&gt;&amp;&lt;/tt&gt; for boolean AND, &lt;tt&gt;|&lt;/tt&gt; boolean OR (not bitwise)
 * Subexpressions are delimited using parentheses &lt;tt&gt;(&lt;/tt&gt; and &lt;tt&gt;)&lt;/tt&gt;
 
 
+=== String matching
+
+The &lt;tt&gt;=&lt;/tt&gt; and &lt;tt&gt;~&lt;/tt&gt; operators, when used with strings, perform case-sensitive
+and case-insensitive matching respectively. Within a string, &lt;tt&gt;*&lt;/tt&gt; matches zero or
+more characters of any type, and &lt;tt&gt;?&lt;/tt&gt; matches a single character.
+
+  Siren.query &quot;$[? @ = 'b*']&quot;, %w[foo bar baz]
+  #=&gt; [&quot;bar&quot;, &quot;baz&quot;]
+  
+  Siren.query &quot;$[? @ = 'b?']&quot;, %w[foo bar baz]
+  #=&gt; []
+  
+  Siren.query &quot;$[? @ ~ 'BA?']&quot;, %w[foo bar baz]
+  #=&gt; [&quot;bar&quot;, &quot;baz&quot;]
+
+
 === Field access filter
 
 A field access filter selects a named field from an object. Fields are accessed using the
@@ -217,7 +234,7 @@ predicate expression, and return them as a flat array.
   ]
   
   Siren.query &quot;$..[? @ % 4 = 0]&quot;, data
-  #=&gt; [8, 4 ,12]
+  #=&gt; [8, 4, 12]
 
 
 === Mapping filter</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ require 'rubygems'
 require 'hoe'
 require './lib/siren.rb'
 
-Hoe.new('siren', Siren::VERSION) do |p|
+Hoe.spec('siren') do |p|
   # p.rubyforge_name = 'sirenx' # if different than lowercase project name
   p.developer('James Coglan', 'jcoglan@googlemail.com')
   p.extra_deps = %w[treetop eventful]</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -771,18 +771,24 @@ module Siren
               r0 = r4
               r0.extend(Comparator)
             else
-              r5 = _nt_lt
+              r5 = _nt_match
               if r5
                 r0 = r5
                 r0.extend(Comparator)
               else
-                r6 = _nt_gt
+                r6 = _nt_lt
                 if r6
                   r0 = r6
                   r0.extend(Comparator)
                 else
-                  self.index = i0
-                  r0 = nil
+                  r7 = _nt_gt
+                  if r7
+                    r0 = r7
+                    r0.extend(Comparator)
+                  else
+                    self.index = i0
+                    r0 = nil
+                  end
                 end
               end
             end
@@ -816,6 +822,27 @@ module Siren
       return r0
     end
 
+    def _nt_match
+      start_index = index
+      if node_cache[:match].has_key?(index)
+        cached = node_cache[:match][index]
+        @index = cached.interval.end if cached
+        return cached
+      end
+
+      if input.index(&quot;~&quot;, index) == index
+        r0 = instantiate_node(Match,input, index...(index + 1))
+        @index += 1
+      else
+        terminal_parse_failure(&quot;~&quot;)
+        r0 = nil
+      end
+
+      node_cache[:match][start_index] = r0
+
+      return r0
+    end
+
     def _nt_not_equal
       start_index = index
       if node_cache[:not_equal].has_key?(index)</diff>
      <filename>lib/siren/json_query.rb</filename>
    </modified>
    <modified>
      <diff>@@ -57,13 +57,17 @@ module Siren
     end
     
     rule comparator
-      (not_equal / lte / gte / equal / lt / gt) &lt;Comparator&gt;
+      (not_equal / lte / gte / equal / match / lt / gt) &lt;Comparator&gt;
     end
     
     rule equal
       &quot;=&quot; &lt;Equal&gt;
     end
     
+    rule match
+      &quot;~&quot; &lt;Match&gt;
+    end
+    
     rule not_equal
       &quot;!=&quot; &lt;NotEqual&gt;
     end</diff>
      <filename>lib/siren/json_query.tt</filename>
    </modified>
    <modified>
      <diff>@@ -245,7 +245,17 @@ module Siren
     
     module Equal
       def value(expr1, expr2)
-        expr1 == expr2
+        return expr1 == expr2 unless expr2.respond_to?(:gsub)
+        expr2 = expr2.gsub('*', '.*').gsub('?', '.')
+        expr1 =~ %r{^#{expr2}$}
+      end
+    end
+    
+    module Match
+      def value(expr1, expr2)
+        return expr1 == expr2 unless expr2.respond_to?(:gsub)
+        expr2 = expr2.gsub('*', '.*').gsub('?', '.')
+        expr1 =~ %r{^#{expr2}$}i
       end
     end
     </diff>
      <filename>lib/siren/json_query_nodes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -129,6 +129,23 @@ class SirenTest &lt; Test::Unit::TestCase
         {:key =&gt; [9,5,7], :val =&gt; 1..8})
   end
   
+  def test_wildcards
+    assert_equal [&quot;Sayings of the Century&quot;, &quot;The Lord of the Rings&quot;],
+        Siren.query(&quot;$.store.book[? @.title = '* of the *'][= title]&quot;, fixtures(:store))
+    
+    assert_equal [],
+        Siren.query(&quot;$.store.book[? @.title = '* Of the *'][= title]&quot;, fixtures(:store))
+    
+    assert_equal [&quot;Sayings of the Century&quot;, &quot;The Lord of the Rings&quot;],
+        Siren.query(&quot;$.store.book[? @.title ~ '* Of the *'][= title]&quot;, fixtures(:store))
+        
+    assert_equal [&quot;Sayings of the Century&quot;],
+        Siren.query(&quot;$.store.book[? @.title = '??????? of the ???????'][= title]&quot;, fixtures(:store))
+        
+    assert_equal [],
+        Siren.query(&quot;$.store.book[? @.title = '? of the ?'][= title]&quot;, fixtures(:store))
+  end
+  
   def test_bookstore
     assert_equal &quot;The Lord of the Rings&quot;,
         Siren.query(&quot;$.store.book[@.length - 1]&quot;, fixtures(:store))[&quot;title&quot;]</diff>
      <filename>test/test_siren.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e26f42055f7a3d04166d934ab1b58a9f464d1349</id>
    </parent>
  </parents>
  <author>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </author>
  <url>http://github.com/jcoglan/siren/commit/9633de832a8206ea5e7599e00bf4594dedff9deb</url>
  <id>9633de832a8206ea5e7599e00bf4594dedff9deb</id>
  <committed-date>2009-07-06T09:42:29-07:00</committed-date>
  <authored-date>2009-07-06T09:42:29-07:00</authored-date>
  <message>Implementing the string matching operators with wildcards.</message>
  <tree>24ee8343646bb36df964fabe412e04abbd1822ea</tree>
  <committer>
    <name>James Coglan</name>
    <email>jcoglan@googlemail.com</email>
  </committer>
</commit>
