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    /// 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    /// In Darts-clone, a dictionary is a deterministic finite-state automaton
169    /// (DFA) and this tests transitions on the DFA. The initial state is
170    /// `node_pos` and the function chooses transitions labeled `key[key_pos]`,
171    /// `key[key_pos + 1]`, ... in order. If there is not a transition labeled
172    /// `key[key_pos + i]`, the function terminates the transitions at that state and
173    /// returns -2. Otherwise, the function ends without a termination and returns
174    /// -1 or a nonnegative value, -1 indicates that the final state was not an
175    /// accept state. When a nonnegative value is returned, it is the value
176    /// associated with the final accept state. That is, the function returns the
177    /// value associated with the given key if it exists. Note that the function
178    /// updates `node_pos` and `key_pos` after each transition.
179    pub fn darts_traverse(
180        darts: DartsT,
181        key: *const DartsKeyType,
182        node_pos: *mut size_t,
183        key_pos: *mut size_t,
184        length: size_t,
185    ) -> DartsValueType;
186}
187
188#[cfg(test)]
189mod tests {
190    use super::*;
191
192    #[test]
193    fn is_works() {
194        let dic = unsafe { darts_new() };
195        assert_ne!(dic, std::ptr::null_mut());
196        unsafe { darts_delete(dic); }
197    }
198}