-
Notifications
You must be signed in to change notification settings - Fork 100
/
ec_dictionary.erl
153 lines (135 loc) · 5.4 KB
/
ec_dictionary.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
%%% vi:ts=4 sw=4 et
%%%-------------------------------------------------------------------
%%% @author Eric Merritt <ericbmerritt@gmail.com>
%%% @copyright 2011 Erlware, LLC.
%%% @doc
%%% A module that supports association of keys to values. A map cannot
%%% contain duplicate keys; each key can map to at most one value.
%%%
%%% This interface is a member of the Erlware Commons Library.
%%% @end
%%%-------------------------------------------------------------------
-module(ec_dictionary).
%% API
-export([new/1,
has_key/2,
get/2,
get/3,
add/3,
remove/2,
has_value/2,
size/1,
to_list/1,
from_list/2,
keys/1]).
-export_type([dictionary/2,
key/1,
value/1]).
%%%===================================================================
%%% Types
%%%===================================================================
-record(dict_t,
{callback,
data}).
%% This should be opaque, but that kills dialyzer so for now we export it
%% however you should not rely on the internal representation here
-type dictionary(_K, _V) :: #dict_t{}.
-type key(T) :: T.
-type value(T) :: T.
-callback new() -> any().
-callback has_key(key(any()), any()) -> boolean().
-callback get(key(any()), any()) -> any().
-callback add(key(any()), value(any()), T) -> T.
-callback remove(key(any()), T) -> T.
-callback has_value(value(any()), any()) -> boolean().
-callback size(any()) -> non_neg_integer().
-callback to_list(any()) -> [{key(any()), value(any())}].
-callback from_list([{key(any()), value(any())}]) -> any().
-callback keys(any()) -> [key(any())].
%%%===================================================================
%%% API
%%%===================================================================
%% @doc create a new dictionary object from the specified module. The
%% module should implement the dictionary behaviour.
%%
%% @param ModuleName The module name.
-spec new(module()) -> dictionary(_K, _V).
new(ModuleName) when is_atom(ModuleName) ->
#dict_t{callback = ModuleName, data = ModuleName:new()}.
%% @doc check to see if the dictionary provided has the specified key.
%%
%% @param Dict The dictory object to check
%% @param Key The key to check the dictionary for
-spec has_key(key(K), dictionary(K, _V)) -> boolean().
has_key(Key, #dict_t{callback = Mod, data = Data}) ->
Mod:has_key(Key, Data).
%% @doc given a key return that key from the dictionary. If the key is
%% not found throw a 'not_found' exception.
%%
%% @param Dict The dictionary object to return the value from
%% @param Key The key requested
%% when the key does not exist @throws not_found
-spec get(key(K), dictionary(K, V)) -> value(V).
get(Key, #dict_t{callback = Mod, data = Data}) ->
Mod:get(Key, Data).
%% @doc given a key return that key from the dictionary. If the key is
%% not found then the default value is returned.
%%
%% @param Dict The dictionary object to return the value from
%% @param Key The key requested
%% @param Default The value that will be returned if no value is found
%% in the database.
-spec get(key(K), value(V), dictionary(K, V)) -> value(V).
get(Key, Default, #dict_t{callback = Mod, data = Data}) ->
Mod:get(Key, Default, Data).
%% @doc add a new value to the existing dictionary. Return a new
%% dictionary containing the value.
%%
%% @param Dict the dictionary object to add too
%% @param Key the key to add
%% @param Value the value to add
-spec add(key(K), value(V), dictionary(K, V)) -> dictionary(K, V).
add(Key, Value, #dict_t{callback = Mod, data = Data} = Dict) ->
Dict#dict_t{data = Mod:add(Key, Value, Data)}.
%% @doc Remove a value from the dictionary returning a new dictionary
%% with the value removed.
%%
%% @param Dict the dictionary object to remove the value from
%% @param Key the key of the key/value pair to remove
-spec remove(key(K), dictionary(K, V)) -> dictionary(K, V).
remove(Key, #dict_t{callback = Mod, data = Data} = Dict) ->
Dict#dict_t{data = Mod:remove(Key, Data)}.
%% @doc Check to see if the value exists in the dictionary
%%
%% @param Dict the dictionary object to check
%% @param Value The value to check if exists
-spec has_value(value(V), dictionary(_K, V)) -> boolean().
has_value(Value, #dict_t{callback = Mod, data = Data}) ->
Mod:has_value(Value, Data).
%% @doc return the current number of key value pairs in the dictionary
%%
%% @param Dict the object return the size for.
-spec size(dictionary(_K, _V)) -> integer().
size(#dict_t{callback = Mod, data = Data}) ->
Mod:size(Data).
%% @doc Return the contents of this dictionary as a list of key value
%% pairs.
%%
%% @param Dict the base dictionary to make use of.
-spec to_list(Dict::dictionary(K, V)) -> [{key(K), value(V)}].
to_list(#dict_t{callback = Mod, data = Data}) ->
Mod:to_list(Data).
%% @doc Create a new dictionary, of the specified implementation using
%% the list provided as the starting contents.
%%
%% @param ModuleName the type to create the dictionary from
%% @param List The list of key value pairs to start with
-spec from_list(module(), [{key(K), value(V)}]) -> dictionary(K, V).
from_list(ModuleName, List) when is_list(List) ->
#dict_t{callback = ModuleName, data = ModuleName:from_list(List)}.
%% @doc Return the keys of this dictionary as a list
%%
%% @param Dict the base dictionary to make use of.
-spec keys(Dict::dictionary(K, _V)) -> [key(K)].
keys(#dict_t{callback = Mod, data = Data}) ->
Mod:keys(Data).