Add new match and match_object functions
diff --git a/src/ets_lru.erl b/src/ets_lru.erl
index dc68fb8..7311081 100644
--- a/src/ets_lru.erl
+++ b/src/ets_lru.erl
@@ -20,6 +20,8 @@
 
     insert/3,
     lookup/2,
+    match/3,
+    match_object/3,
     remove/2,
     clear/1,
 
@@ -78,6 +80,23 @@
 remove(LRU, Key) ->
     gen_server:call(LRU, {remove, Key}).
 
+%% @doc match/3 provides an efficient way to retrieve parts of the
+%% keys and values without copying or requiring circumvention of the
+%% ets_lru API. The KeySpec and ValueSpec parameters are used as part
+%% of one larger match spec so keep in mind that all capturing
+%% placeholders will be aliased between the key and value parts.
+-spec match(atom() | pid(), term(), term()) -> [[any()]].
+match(LRU, KeySpec, ValueSpec) ->
+    gen_server:call(LRU, {match, KeySpec, ValueSpec}).
+
+%% @doc match_object/3 provides an efficient way to retrieve multiple
+%% values using match conditions. The KeySpec and ValueSpec parameters
+%% are used as part of one larger match spec so keep in mind that all
+%% capturing placeholders will be aliased between the key and value
+%% parts.
+-spec match_object(atom() | pid(), term(), term()) -> [any()].
+match_object(LRU, KeySpec, ValueSpec) ->
+    gen_server:call(LRU, {match_object, KeySpec, ValueSpec}).
 
 clear(LRU) ->
     gen_server:call(LRU, clear).
@@ -122,6 +141,20 @@
     end,
     {reply, Reply, St, 0};
 
+handle_call({match_object, KeySpec, ValueSpec}, _From, St) ->
+    Pattern = #entry{key=KeySpec, val=ValueSpec, _='_'},
+    Entries = ets:match_object(St#st.objects, Pattern),
+    Values = lists:map(fun(#entry{key=Key,val=Val}) ->
+        accessed(Key, St),
+        Val
+    end, Entries),
+    {reply, Values, St, 0};
+
+handle_call({match, KeySpec, ValueSpec}, _From, St) ->
+    Pattern = #entry{key=KeySpec, val=ValueSpec, _='_'},
+    Values = ets:match(St#st.objects, Pattern),
+    {reply, Values, St, 0};
+
 handle_call({insert, Key, Val}, _From, St) ->
     NewATime = erlang:now(),
     Pattern = #entry{key=Key, atime='$1', _='_'},
diff --git a/test/06-match.t b/test/06-match.t
new file mode 100644
index 0000000..907ae78
--- /dev/null
+++ b/test/06-match.t
@@ -0,0 +1,44 @@
+#!/usr/bin/env escript
+
+-define(WITH_LRU(F), tutil:with_lru(fun(LRU) -> F(LRU) end)).
+
+main([]) ->
+    code:add_pathz("test"),
+    code:add_pathz("ebin"),
+    tutil:run(6, fun() -> test() end).
+
+test() ->
+    ?WITH_LRU(test_match_zero_values),
+    ?WITH_LRU(test_match_one_value),
+    ?WITH_LRU(test_match_many_values),
+    ?WITH_LRU(test_match_zero_objects),
+    ?WITH_LRU(test_match_one_object),
+    ?WITH_LRU(test_match_many_objects),
+    ok.
+
+test_match_zero_values(LRU) ->
+    etap:is(ets_lru:match(LRU, a, '$1'), [], "Empty match").
+
+test_match_one_value(LRU) ->
+    ets_lru:insert(LRU, b, {x,y}),
+    Values = ets_lru:match(LRU, b, {'$1', '$2'}),
+    etap:is(Values, [[x,y]], "Single match").
+
+test_match_many_values(LRU) ->
+    ets_lru:insert(LRU, boston, {state, "MA"}),
+    ets_lru:insert(LRU, new_york, {state, "NY"}),
+    Values = ets_lru:match(LRU, '_', {state, '$1'}),
+    etap:is(lists:sort(Values), [["MA"],["NY"]], "Multiple match").
+
+test_match_zero_objects(LRU) ->
+    etap:is(ets_lru:match_object(LRU, a, '$1'), [], "Empty match_object").
+
+test_match_one_object(LRU) ->
+    ets_lru:insert(LRU, ans, 42),
+    etap:is(ets_lru:match_object(LRU, ans, '$1'), [42], "Single match_object").
+
+test_match_many_objects(LRU) ->
+    ets_lru:insert(LRU, {color, blue}, a),
+    ets_lru:insert(LRU, {color, red}, b),
+    Values = ets_lru:match_object(LRU, {color, '_'}, '_'),
+    etap:is(lists:sort(Values), [a, b], "Multiple match_object").