1%% This file is part of khash released under the MIT license. 2%% See the LICENSE file for more information. 3%% Copyright 2013 Cloudant, Inc <support@cloudant.com> 4 5-module(khash). 6-on_load(init/0). 7 8 9-export([ 10 new/0, 11 new/1, 12 from_list/1, 13 from_list/2, 14 to_list/1, 15 clear/1, 16 lookup/2, 17 get/2, 18 get/3, 19 put/3, 20 del/2, 21 size/1, 22 iter/1, 23 iter_next/1, 24 fold/3 25]). 26 27 28-define(NOT_LOADED, not_loaded(?LINE)). 29 30 31-type kv() :: {any(), any()}. 32-type khash() :: term(). 33-type khash_iter() :: term(). 34-type option() :: []. 35 36 37-spec new() -> {ok, khash()}. 38new() -> 39 new([]). 40 41 42-spec new([option()]) -> {ok, khash()}. 43new(_Options) -> 44 ?NOT_LOADED. 45 46 47-spec from_list([kv()]) -> {ok, khash()}. 48from_list(KVList) -> 49 from_list(KVList, []). 50 51 52-spec from_list([kv()], [option()]) -> {ok, khash()}. 53from_list(KVList, Options) -> 54 {ok, Hash} = ?MODULE:new(Options), 55 lists:foreach(fun({Key, Val}) -> 56 ?MODULE:put(Hash, Key, Val) 57 end, KVList), 58 {ok, Hash}. 59 60 61-spec to_list(khash()) -> [kv()]. 62to_list(_Hash) -> 63 ?NOT_LOADED. 64 65 66-spec clear(khash()) -> ok. 67clear(_Hash) -> 68 ?NOT_LOADED. 69 70 71-spec lookup(khash(), any()) -> {value, any()} | not_found. 72lookup(Hash, Key) -> 73 lookup_int(Hash, erlang:phash2(Key), Key). 74 75 76-spec get(khash(), any()) -> any(). 77get(Hash, Key) -> 78 get(Hash, Key, undefined). 79 80 81-spec get(khash(), any(), any()) -> any(). 82get(Hash, Key, Default) -> 83 get_int(Hash, erlang:phash2(Key), Key, Default). 84 85 86-spec put(khash(), any(), any()) -> ok. 87put(Hash, Key, Value) -> 88 put_int(Hash, erlang:phash2(Key), Key, Value). 89 90 91-spec del(khash(), any()) -> ok. 92del(Hash, Key) -> 93 del_int(Hash, erlang:phash2(Key), Key). 94 95 96-spec size(khash()) -> non_neg_integer(). 97size(_Hash) -> 98 ?NOT_LOADED. 99 100 101-spec iter(khash()) -> {ok, khash_iter()}. 102iter(_Hash) -> 103 ?NOT_LOADED. 104 105 106-spec iter_next(khash_iter()) -> 107 kv() | end_of_table | {error, expired_iterator}. 108iter_next(_Iter) -> 109 ?NOT_LOADED. 110 111 112-spec fold(khash(), fun(), any()) -> any(). 113fold(Hash, FoldFun, Acc) -> 114 {ok, Iter} = ?MODULE:iter(Hash), 115 fold_int(Iter, FoldFun, Acc). 116 117 118fold_int(Iter, FoldFun, Acc) -> 119 case ?MODULE:iter_next(Iter) of 120 {Key, Value} -> 121 NewAcc = FoldFun(Key, Value, Acc), 122 fold_int(Iter, FoldFun, NewAcc); 123 end_of_table -> 124 Acc 125 end. 126 127 128init() -> 129 PrivDir = case code:priv_dir(?MODULE) of 130 {error, _} -> 131 EbinDir = filename:dirname(code:which(?MODULE)), 132 AppPath = filename:dirname(EbinDir), 133 filename:join(AppPath, "priv"); 134 Path -> 135 Path 136 end, 137 erlang:load_nif(filename:join(PrivDir, "khash"), 0). 138 139 140lookup_int(_Hash, _HashValue, _Key) -> 141 ?NOT_LOADED. 142 143 144get_int(_Hash, _HashValue, _Key, _Default) -> 145 ?NOT_LOADED. 146 147 148put_int(_Hash, _HashValue, _Key, _Value) -> 149 ?NOT_LOADED. 150 151 152del_int(_Hash, _HashValue, _Key) -> 153 ?NOT_LOADED. 154 155 156not_loaded(Line) -> 157 erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}). 158