libdarts_sys/lib.rs
1use libc::{c_void, c_char, c_int, size_t};
2
3/// Type of double array instance.
4pub type DartsT = *mut c_void;
5/// Type of double array trie key.
6pub type DartsKeyType = c_char;
7/// Type of double array trie value.
8pub type DartsValueType = c_int;
9
10/// Enables applications to get the lengths of the
11/// matched keys in addition to the values.
12#[repr(C)]
13#[derive(Debug, Copy, Clone)]
14pub struct DartsResultPairType {
15 pub value: DartsValueType,
16 pub length: size_t,
17}
18
19#[link(name = "darts")]
20extern "C" {
21 /// Constructs an instance of double array trie.
22 pub fn darts_new() -> DartsT;
23
24 /// Frees an allocated double array trie.
25 pub fn darts_delete(darts: DartsT);
26
27 /// Returns the internal error. It could be NULL if there is no error.
28 pub fn darts_error(darts: DartsT) -> *const c_char;
29
30 /// Returns version string of Darts.
31 pub fn darts_version() -> *const c_char;
32
33 /// Calls [`darts_clear`] in order to free memory allocated to the
34 /// old array and then sets a new array. This function is useful to set a memory-
35 /// mapped array.
36 ///
37 /// Note that the array set by this function is not freed in
38 /// [`darts_clear`] and [`darts_delete`].
39 ///
40 /// darts_set_array() can also set the size of the new array but the size is not
41 /// used in search methods. So it works well even if the size is 0 or omitted.
42 /// Remember that [`darts_size`] and [darts_total_size] returns 0 in such a case.
43 pub fn darts_set_array(darts: DartsT, ptr: *const c_void, size: size_t);
44
45 /// Returns a pointer to the array of units.
46 pub fn darts_array(darts: DartsT) -> *const c_void;
47
48 /// Frees memory allocated to units and then initializes member
49 /// variables with 0 and NULLs. Note that this does not free memory if
50 /// the array of units was set by [`darts_set_array`].
51 pub fn darts_clear(darts: DartsT);
52
53 /// Returns the size of each unit.
54 pub fn darts_unit_size(darts: DartsT) -> size_t;
55
56 /// Returns the number of units. It can be 0 if [`darts_set_array`] is used.
57 pub fn darts_size(darts: DartsT) -> size_t;
58
59 /// Returns the number of bytes allocated to the array of units.
60 /// It can be 0 if [`darts_set_array`] is used.
61 pub fn darts_total_size(darts: DartsT) -> size_t;
62
63 /// Exists for compatibility. It always returns the number of
64 /// units because it takes long time to count the number of non-zero units.
65 pub fn darts_nonzero_size(darts: DartsT) -> size_t;
66
67 /// Constructs a dictionary from given key-value pairs. If `lengths`
68 /// is NULL, `keys` is handled as an array of zero-terminated strings. If
69 /// `values` is NULL, the index in `keys` is associated with each key, i.e.
70 /// the ith key has (i - 1) as its value.
71 ///
72 /// Note that the key-value pairs must be arranged in key order and the values
73 /// must not be negative. Also, if there are duplicate keys, only the first
74 /// pair will be stored in the resultant dictionary.
75 ///
76 /// `progress_func` is a pointer to a callback function. If it is not NULL,
77 /// it will be called in this function so that the caller can check the progress of
78 /// dictionary construction.
79 ///
80 /// The return value is 0, and it indicates the success of the
81 /// operation. Otherwise, get error message from darts_error().
82 ///
83 /// Uses another construction algorithm if `values` is not NULL. In
84 /// this case, Darts-clone uses a Directed Acyclic Word Graph (DAWG) instead
85 /// of a trie because a DAWG is likely to be more compact than a trie.
86 pub fn darts_build(
87 darts: DartsT,
88 num_keys: size_t,
89 keys: *const *const DartsKeyType,
90 lengths: *const size_t,
91 values: *const DartsValueType,
92 progress_func: ::std::option::Option<
93 unsafe extern "C" fn(arg1: size_t, arg2: size_t) -> c_int,
94 >,
95 ) -> c_int;
96
97 /// Reads an array of units from the specified file. And if it goes
98 /// well, the old array will be freed and replaced with the new array read
99 /// from the file. `offset` specifies the number of bytes to be skipped before
100 /// reading an array. `size` specifies the number of bytes to be read from the
101 /// file. If the `size' is 0, the whole file will be read.
102 ///
103 /// Returns 0 iff the operation succeeds. Otherwise,
104 /// get error message from [`darts_error`].
105 pub fn darts_open(
106 darts: DartsT,
107 file_name: *const c_char,
108 mode: *const c_char,
109 offset: size_t,
110 size: size_t,
111 ) -> c_int;
112
113 /// Writes the array of units into the specified file. `offset'
114 /// specifies the number of bytes to be skipped before writing the array.
115 /// Returns 0 iff the operation succeeds. Otherwise, returns a non-zero value.
116 pub fn darts_save(
117 darts: DartsT,
118 file_name: *const c_char,
119 mode: *const c_char,
120 offset: size_t,
121 ) -> c_int;
122
123 /// Tests whether the given key exists or not, and
124 /// if it exists, its value and length are returned. Otherwise, the
125 /// value and the length of return value are set to -1 and 0 respectively.
126 ///
127 /// Note that if `length` is 0, `key` is handled as a zero-terminated string.
128 /// `node_pos` specifies the start position of matching. This argument enables
129 /// the combination of darts_exact_match_search and [`darts_traverse`]. For example, if you
130 /// want to test "xyzA", "xyzBC", and "xyzDE", you can use [`darts_traverse`] to get
131 /// the node position corresponding to "xyz" and then you can use
132 /// darts_exact_match_search to test "A", "BC", and "DE" from that position.
133 ///
134 /// Note that the length of `result` indicates the length from the `node_pos`.
135 /// In the above example, the lengths are { 1, 2, 2 }, not { 4, 5, 5 }.
136 pub fn darts_exact_match_search(
137 darts: DartsT,
138 key: *const DartsKeyType,
139 length: size_t,
140 node_pos: size_t,
141 ) -> DartsValueType;
142
143 /// [`darts_exact_match_search`] but returns a [`DartsResultPairType`] instead.
144 pub fn darts_exact_match_search_pair(
145 darts: DartsT,
146 key: *const DartsKeyType,
147 length: size_t,
148 node_pos: size_t,
149 ) -> DartsResultPairType;
150
151 /// Searches for keys which match a prefix of the
152 /// given string. If `length` is 0, `key` is handled as a zero-terminated string.
153 /// The values and the lengths of at most `max_num_results` matched keys are
154 /// stored in `results`. Returns the number of matched
155 /// keys. Note that the return value can be larger than `max_num_results` if
156 /// there are more than `max_num_results` matches. If you want to get all the
157 /// results, allocate more spaces and call this again.
158 /// `node_pos` works as well as in [`darts_exact_match_search`].
159 pub fn darts_common_prefix_search(
160 darts: DartsT,
161 key: *const DartsKeyType,
162 results: *mut DartsResultPairType,
163 max_num_results: size_t,
164 length: size_t,
165 node_pos: size_t,
166 ) -> size_t;
167
168 /// Searches for the longest key which matches a prefix of the given string,
169 /// and if it exists, its value and length are set to `result`. Otherwise,
170 /// the value and the length of `result` are set to -1 and 0 respectively.
171 /// Note that if `length` is 0, `key` is handled as a zero-terminated string.
172 /// `node_pos` works as well as in [`darts_exact_match_search`].
173 pub fn darts_common_longest_prefix_search(
174 darts: DartsT,
175 key: *const DartsKeyType,
176 length: size_t,
177 node_pos: size_t,
178 ) -> DartsValueType;
179
180 /// [`darts_common_longest_prefix_search`] but returns a [`DartsResultPairType`] instead.
181 pub fn darts_common_longest_prefix_search_pair(
182 darts: DartsT,
183 key: *const DartsKeyType,
184 length: size_t,
185 node_pos: size_t,
186 ) -> DartsResultPairType;
187
188 /// In Darts-clone, a dictionary is a deterministic finite-state automaton
189 /// (DFA) and this tests transitions on the DFA. The initial state is
190 /// `node_pos` and the function chooses transitions labeled `key[key_pos]`,
191 /// `key[key_pos + 1]`, ... in order. If there is not a transition labeled
192 /// `key[key_pos + i]`, the function terminates the transitions at that state and
193 /// returns -2. Otherwise, the function ends without a termination and returns
194 /// -1 or a nonnegative value, -1 indicates that the final state was not an
195 /// accept state. When a nonnegative value is returned, it is the value
196 /// associated with the final accept state. That is, the function returns the
197 /// value associated with the given key if it exists. Note that the function
198 /// updates `node_pos` and `key_pos` after each transition.
199 pub fn darts_traverse(
200 darts: DartsT,
201 key: *const DartsKeyType,
202 node_pos: *mut size_t,
203 key_pos: *mut size_t,
204 length: size_t,
205 ) -> DartsValueType;
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn is_works() {
214 let dic = unsafe { darts_new() };
215 assert_ne!(dic, std::ptr::null_mut());
216 unsafe { darts_delete(dic); }
217 }
218}