use crate::cerror::ErrorList;
use crate::map_cerr;
use super::Matrix;
use super::{cast_const, cast_mut, cstr};
use graphannis::{
corpusstorage::{FrequencyTable, QueryAttributeDescription},
errors::Result,
graph::{Annotation, Edge, NodeID},
model::AnnotationComponent,
};
use libc::{c_char, c_void, size_t};
use std::ffi::CString;
#[unsafe(no_mangle)]
#[allow(clippy::from_raw_with_void_ptr)]
pub unsafe extern "C" fn annis_free(ptr: *mut c_void) {
if ptr.is_null() {
return;
}
let ptr = unsafe { Box::from_raw(ptr) };
std::mem::drop(ptr);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn annis_str_free(s: *mut c_char) {
if s.is_null() {
return;
}
let s = unsafe { CString::from_raw(s) };
drop(s);
}
pub type IterPtr<T> = Box<dyn Iterator<Item = Result<T>>>;
fn iter_next<T>(ptr: *mut Box<dyn Iterator<Item = Result<T>>>, err: *mut *mut ErrorList) -> *mut T {
let it: &mut Box<dyn Iterator<Item = Result<T>>> = cast_mut(ptr);
if let Some(v) = it.next()
&& let Some(v) = map_cerr(v, err)
{
return Box::into_raw(Box::new(v));
}
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_iter_nodeid_next(
ptr: *mut IterPtr<NodeID>,
err: *mut *mut ErrorList,
) -> *mut NodeID {
iter_next(ptr, err)
}
pub fn vec_size<T>(ptr: *const Vec<T>) -> size_t {
let v: &Vec<T> = cast_const(ptr);
v.len()
}
pub fn vec_get<T>(ptr: *const Vec<T>, i: size_t) -> *const T {
let v: &Vec<T> = cast_const(ptr);
if i < v.len() {
return &v[i] as *const T;
}
std::ptr::null()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_str_size(ptr: *const Vec<CString>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_str_get(ptr: *const Vec<CString>, i: size_t) -> *const c_char {
let strvec: &Vec<CString> = cast_const(ptr);
if i < strvec.len() {
strvec[i].as_ptr()
} else {
std::ptr::null()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_str_new() -> *mut Vec<CString> {
let result: Vec<CString> = Vec::new();
Box::into_raw(Box::new(result))
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_str_push(ptr: *mut Vec<CString>, v: *const c_char) {
let strvec: &mut Vec<CString> = cast_mut(ptr);
let v: &str = &cstr(v);
if let Ok(cval) = CString::new(v) {
strvec.push(cval);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_annotation_ns(ptr: *const Annotation) -> *mut c_char {
let anno: &Annotation = cast_const(ptr);
CString::new(anno.key.ns.as_str())
.unwrap_or_default()
.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_annotation_name(ptr: *const Annotation) -> *mut c_char {
let anno: &Annotation = cast_const(ptr);
CString::new(anno.key.name.as_str())
.unwrap_or_default()
.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_annotation_val(ptr: *const Annotation) -> *mut c_char {
let anno: &Annotation = cast_const(ptr);
CString::new(anno.val.as_str())
.unwrap_or_default()
.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_annotation_size(ptr: *const Vec<Annotation>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_annotation_get(
ptr: *const Vec<Annotation>,
i: size_t,
) -> *const Annotation {
vec_get(ptr, i)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_edge_size(ptr: *const Vec<Edge>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_edge_get(ptr: *const Vec<Edge>, i: size_t) -> *const Edge {
vec_get(ptr, i)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_component_size(ptr: *const Vec<AnnotationComponent>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_component_get(
ptr: *const Vec<AnnotationComponent>,
i: size_t,
) -> *const AnnotationComponent {
vec_get(ptr, i)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_qattdesc_size(ptr: *const Vec<QueryAttributeDescription>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_qattdesc_get_component_nr(
ptr: *const Vec<QueryAttributeDescription>,
i: size_t,
) -> usize {
let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
let desc: &QueryAttributeDescription = cast_const(desc_ptr);
desc.alternative
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_qattdesc_get_aql_fragment(
ptr: *const Vec<QueryAttributeDescription>,
i: size_t,
) -> *mut c_char {
let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
let desc: &QueryAttributeDescription = cast_const(desc_ptr);
let cstr: CString = CString::new(desc.query_fragment.as_str()).unwrap_or_default();
cstr.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_qattdesc_get_variable(
ptr: *const Vec<QueryAttributeDescription>,
i: size_t,
) -> *mut c_char {
let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
let desc: &QueryAttributeDescription = cast_const(desc_ptr);
let cstr: CString = CString::new(desc.variable.as_str()).unwrap_or_default();
cstr.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_vec_qattdesc_get_anno_name(
ptr: *const Vec<QueryAttributeDescription>,
i: size_t,
) -> *mut c_char {
let desc_ptr: *const QueryAttributeDescription = vec_get(ptr, i);
let desc: &QueryAttributeDescription = cast_const(desc_ptr);
if let Some(anno_name) = &desc.anno_name {
let cstr: CString = CString::new(anno_name.as_str()).unwrap_or_default();
cstr.into_raw()
} else {
std::ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_matrix_str_nrows(ptr: *const Matrix<CString>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_matrix_str_ncols(ptr: *const Matrix<CString>) -> size_t {
let v: &Vec<Vec<CString>> = cast_const(ptr);
if !v.is_empty() {
return v[0].len();
}
0
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_matrix_str_get(
ptr: *const Matrix<CString>,
row: size_t,
col: size_t,
) -> *const c_char {
let strmatrix: &Vec<Vec<CString>> = cast_const(ptr);
if row < strmatrix.len() && col < strmatrix[row].len() {
return strmatrix[row][col].as_ptr();
}
std::ptr::null()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_freqtable_str_nrows(ptr: *const FrequencyTable<CString>) -> size_t {
vec_size(ptr)
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_freqtable_str_ncols(ptr: *const FrequencyTable<CString>) -> size_t {
let v: &FrequencyTable<CString> = cast_const(ptr);
if !v.is_empty() {
return v[0].values.len();
}
0
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_freqtable_str_get(
ptr: *const FrequencyTable<CString>,
row: size_t,
col: size_t,
) -> *const c_char {
let ft: &FrequencyTable<CString> = cast_const(ptr);
if row < ft.len() && col < ft[row].values.len() {
return ft[row].values[col].as_ptr();
}
std::ptr::null()
}
#[unsafe(no_mangle)]
pub extern "C" fn annis_freqtable_str_count(
ptr: *const FrequencyTable<CString>,
row: size_t,
) -> size_t {
let ft: &FrequencyTable<CString> = cast_const(ptr);
if row < ft.len() {
return ft[row].count;
}
0
}