graphannis_capi/
data.rs

1use crate::cerror::ErrorList;
2use crate::map_cerr;
3
4use super::Matrix;
5use super::{cast_const, cast_mut, cstr};
6use graphannis::{
7    corpusstorage::{FrequencyTable, QueryAttributeDescription},
8    errors::Result,
9    graph::{Annotation, Edge, NodeID},
10    model::AnnotationComponent,
11};
12use libc::{c_char, c_void, size_t};
13use std::ffi::CString;
14
15/// Frees the internal object given as `ptr` argument.
16///
17/// # Safety
18///
19/// This functions dereferences the `ptr` pointer and is therefore unsafe.
20#[unsafe(no_mangle)]
21#[allow(clippy::from_raw_with_void_ptr)]
22pub unsafe extern "C" fn annis_free(ptr: *mut c_void) {
23    if ptr.is_null() {
24        return;
25    }
26    // take ownership and destroy the pointer
27    // TODO: this is problematic (https://rust-lang.github.io/rust-clippy/master/index.html#/from_raw_with_void_ptr). Introduce type aware _free functions.
28    let ptr = unsafe { Box::from_raw(ptr) };
29    std::mem::drop(ptr);
30}
31
32/// Frees the string given as `s` argument.
33///
34/// # Safety
35///
36/// This functions dereferences the `s` pointer and is therefore unsafe.
37#[unsafe(no_mangle)]
38pub unsafe extern "C" fn annis_str_free(s: *mut c_char) {
39    if s.is_null() {
40        return;
41    }
42    // take ownership and destruct
43    let s = unsafe { CString::from_raw(s) };
44    drop(s);
45}
46
47pub type IterPtr<T> = Box<dyn Iterator<Item = Result<T>>>;
48
49fn iter_next<T>(ptr: *mut Box<dyn Iterator<Item = Result<T>>>, err: *mut *mut ErrorList) -> *mut T {
50    let it: &mut Box<dyn Iterator<Item = Result<T>>> = cast_mut(ptr);
51    if let Some(v) = it.next()
52        && let Some(v) = map_cerr(v, err)
53    {
54        return Box::into_raw(Box::new(v));
55    }
56    std::ptr::null_mut()
57}
58
59/// Returns a pointer to the next node ID for the iterator given by the `ptr` argument
60/// or `NULL` if iterator is empty.
61///
62/// - `err` - Pointer to a list of errors. If any error occured, this list will be non-empty.
63#[unsafe(no_mangle)]
64pub extern "C" fn annis_iter_nodeid_next(
65    ptr: *mut IterPtr<NodeID>,
66    err: *mut *mut ErrorList,
67) -> *mut NodeID {
68    iter_next(ptr, err)
69}
70
71pub fn vec_size<T>(ptr: *const Vec<T>) -> size_t {
72    let v: &Vec<T> = cast_const(ptr);
73    v.len()
74}
75
76pub fn vec_get<T>(ptr: *const Vec<T>, i: size_t) -> *const T {
77    let v: &Vec<T> = cast_const(ptr);
78    if i < v.len() {
79        return &v[i] as *const T;
80    }
81    std::ptr::null()
82}
83
84/// Returns the number of elements of the string vector.
85#[unsafe(no_mangle)]
86pub extern "C" fn annis_vec_str_size(ptr: *const Vec<CString>) -> size_t {
87    vec_size(ptr)
88}
89
90/// Get a read-only reference to the string at position `i` of the vector.
91#[unsafe(no_mangle)]
92pub extern "C" fn annis_vec_str_get(ptr: *const Vec<CString>, i: size_t) -> *const c_char {
93    // custom implementation for string vectors, don't return a referance to CString but a char pointer
94    let strvec: &Vec<CString> = cast_const(ptr);
95    if i < strvec.len() {
96        strvec[i].as_ptr()
97    } else {
98        std::ptr::null()
99    }
100}
101
102/// Create a new string vector.
103#[unsafe(no_mangle)]
104pub extern "C" fn annis_vec_str_new() -> *mut Vec<CString> {
105    let result: Vec<CString> = Vec::new();
106    Box::into_raw(Box::new(result))
107}
108
109/// Add an element to the string vector.
110#[unsafe(no_mangle)]
111pub extern "C" fn annis_vec_str_push(ptr: *mut Vec<CString>, v: *const c_char) {
112    let strvec: &mut Vec<CString> = cast_mut(ptr);
113    let v: &str = &cstr(v);
114    if let Ok(cval) = CString::new(v) {
115        strvec.push(cval);
116    }
117}
118
119/// Get the namespace of the given annotation object.
120#[unsafe(no_mangle)]
121pub extern "C" fn annis_annotation_ns(ptr: *const Annotation) -> *mut c_char {
122    let anno: &Annotation = cast_const(ptr);
123    CString::new(anno.key.ns.as_str())
124        .unwrap_or_default()
125        .into_raw()
126}
127
128/// Get the name of the given annotation object.
129#[unsafe(no_mangle)]
130pub extern "C" fn annis_annotation_name(ptr: *const Annotation) -> *mut c_char {
131    let anno: &Annotation = cast_const(ptr);
132    CString::new(anno.key.name.as_str())
133        .unwrap_or_default()
134        .into_raw()
135}
136
137/// Get the value of the given annotation object.
138#[unsafe(no_mangle)]
139pub extern "C" fn annis_annotation_val(ptr: *const Annotation) -> *mut c_char {
140    let anno: &Annotation = cast_const(ptr);
141    CString::new(anno.val.as_str())
142        .unwrap_or_default()
143        .into_raw()
144}
145
146/// Returns the number of elements of the annotation vector.
147#[unsafe(no_mangle)]
148pub extern "C" fn annis_vec_annotation_size(ptr: *const Vec<Annotation>) -> size_t {
149    vec_size(ptr)
150}
151
152/// Get a read-only reference to the annotation at position `i` of the vector.
153#[unsafe(no_mangle)]
154pub extern "C" fn annis_vec_annotation_get(
155    ptr: *const Vec<Annotation>,
156    i: size_t,
157) -> *const Annotation {
158    vec_get(ptr, i)
159}
160
161/// Returns the number of elements of the edge vector.
162#[unsafe(no_mangle)]
163pub extern "C" fn annis_vec_edge_size(ptr: *const Vec<Edge>) -> size_t {
164    vec_size(ptr)
165}
166
167/// Get a read-only reference to the edge at position `i` of the vector.
168#[unsafe(no_mangle)]
169pub extern "C" fn annis_vec_edge_get(ptr: *const Vec<Edge>, i: size_t) -> *const Edge {
170    vec_get(ptr, i)
171}
172
173/// Returns the number of elements of the component vector.
174#[unsafe(no_mangle)]
175pub extern "C" fn annis_vec_component_size(ptr: *const Vec<AnnotationComponent>) -> size_t {
176    vec_size(ptr)
177}
178
179/// Get a read-only reference to the component at position `i` of the vector.
180#[unsafe(no_mangle)]
181pub extern "C" fn annis_vec_component_get(
182    ptr: *const Vec<AnnotationComponent>,
183    i: size_t,
184) -> *const AnnotationComponent {
185    vec_get(ptr, i)
186}
187
188/// Returns the number of elements of the query attribute description vector.
189#[unsafe(no_mangle)]
190pub extern "C" fn annis_vec_qattdesc_size(ptr: *const Vec<QueryAttributeDescription>) -> size_t {
191    vec_size(ptr)
192}
193
194/// Get a read-only reference to the query attribute description at position `i` of the vector.
195#[unsafe(no_mangle)]
196pub extern "C" fn annis_vec_qattdesc_get_component_nr(
197    ptr: *const Vec<QueryAttributeDescription>,
198    i: size_t,
199) -> usize {
200    let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
201    let desc: &QueryAttributeDescription = cast_const(desc_ptr);
202    desc.alternative
203}
204
205/// Create a string representing the AQL fragment part of the query attribute description.
206///
207/// The resulting char* must be freeed with annis_str_free!
208#[unsafe(no_mangle)]
209pub extern "C" fn annis_vec_qattdesc_get_aql_fragment(
210    ptr: *const Vec<QueryAttributeDescription>,
211    i: size_t,
212) -> *mut c_char {
213    let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
214    let desc: &QueryAttributeDescription = cast_const(desc_ptr);
215    let cstr: CString = CString::new(desc.query_fragment.as_str()).unwrap_or_default();
216    cstr.into_raw()
217}
218
219/// Create a string representing the variable part of the query attribute description.
220///
221/// The resulting char* must be freeed with annis_str_free!
222#[unsafe(no_mangle)]
223pub extern "C" fn annis_vec_qattdesc_get_variable(
224    ptr: *const Vec<QueryAttributeDescription>,
225    i: size_t,
226) -> *mut c_char {
227    let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
228    let desc: &QueryAttributeDescription = cast_const(desc_ptr);
229    let cstr: CString = CString::new(desc.variable.as_str()).unwrap_or_default();
230    cstr.into_raw()
231}
232
233/// Create a string representing the annotation name part of the query attribute description.
234///
235/// The resulting char* must be freeed with annis_str_free!
236#[unsafe(no_mangle)]
237pub extern "C" fn annis_vec_qattdesc_get_anno_name(
238    ptr: *const Vec<QueryAttributeDescription>,
239    i: size_t,
240) -> *mut c_char {
241    let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
242    let desc: &QueryAttributeDescription = cast_const(desc_ptr);
243    if let Some(anno_name) = &desc.anno_name {
244        let cstr: CString = CString::new(anno_name.as_str()).unwrap_or_default();
245        cstr.into_raw()
246    } else {
247        std::ptr::null_mut()
248    }
249}
250
251/// Returns the number of rows of the string matrix.
252#[unsafe(no_mangle)]
253pub extern "C" fn annis_matrix_str_nrows(ptr: *const Matrix<CString>) -> size_t {
254    vec_size(ptr)
255}
256
257/// Returns the number of columns of the string matrix.
258#[unsafe(no_mangle)]
259pub extern "C" fn annis_matrix_str_ncols(ptr: *const Matrix<CString>) -> size_t {
260    let v: &Vec<Vec<CString>> = cast_const(ptr);
261    if !v.is_empty() {
262        return v[0].len();
263    }
264    0
265}
266
267/// Get a read-only reference to the string at the at position (`row`, `col`) of the matrix.
268#[unsafe(no_mangle)]
269pub extern "C" fn annis_matrix_str_get(
270    ptr: *const Matrix<CString>,
271    row: size_t,
272    col: size_t,
273) -> *const c_char {
274    // custom implementation for string matrix, don't return a referance to CString but a char pointer
275    let strmatrix: &Vec<Vec<CString>> = cast_const(ptr);
276    if row < strmatrix.len() && col < strmatrix[row].len() {
277        return strmatrix[row][col].as_ptr();
278    }
279    std::ptr::null()
280}
281
282/// Returns the number of rows of the frequency table.
283#[unsafe(no_mangle)]
284pub extern "C" fn annis_freqtable_str_nrows(ptr: *const FrequencyTable<CString>) -> size_t {
285    vec_size(ptr)
286}
287
288/// Returns the number of columns of the frequency table.
289#[unsafe(no_mangle)]
290pub extern "C" fn annis_freqtable_str_ncols(ptr: *const FrequencyTable<CString>) -> size_t {
291    let v: &FrequencyTable<CString> = cast_const(ptr);
292    if !v.is_empty() {
293        return v[0].values.len();
294    }
295    0
296}
297
298/// Get a read-only reference to the string at the at position (`row`, `col`) of the frequency table.
299#[unsafe(no_mangle)]
300pub extern "C" fn annis_freqtable_str_get(
301    ptr: *const FrequencyTable<CString>,
302    row: size_t,
303    col: size_t,
304) -> *const c_char {
305    // custom implementation for string matrix, don't return a referance to CString but a char pointer
306    let ft: &FrequencyTable<CString> = cast_const(ptr);
307    if row < ft.len() && col < ft[row].values.len() {
308        return ft[row].values[col].as_ptr();
309    }
310    std::ptr::null()
311}
312
313/// Get the count of the `row` of the frequency table.
314#[unsafe(no_mangle)]
315pub extern "C" fn annis_freqtable_str_count(
316    ptr: *const FrequencyTable<CString>,
317    row: size_t,
318) -> size_t {
319    let ft: &FrequencyTable<CString> = cast_const(ptr);
320    if row < ft.len() {
321        return ft[row].count;
322    }
323    0
324}