use std::ffi::{c_char, CStr, CString};
use std::path::{Path, PathBuf};
use gdal_sys::CPLErr;
use crate::errors::*;
pub fn _string(raw_ptr: *const c_char) -> Option<String> {
if raw_ptr.is_null() {
None
} else {
let c_str = unsafe { CStr::from_ptr(raw_ptr) };
Some(c_str.to_string_lossy().into_owned())
}
}
pub fn _string_array(raw_ptr: *mut *mut c_char) -> Vec<String> {
_convert_raw_ptr_array(raw_ptr, _string)
}
pub fn _pathbuf(raw_ptr: *const c_char) -> Option<PathBuf> {
if raw_ptr.is_null() {
None
} else {
let c_str = unsafe { CStr::from_ptr(raw_ptr) };
Some(c_str.to_string_lossy().into_owned().into())
}
}
pub fn _pathbuf_array(raw_ptr: *mut *mut c_char) -> Vec<PathBuf> {
_convert_raw_ptr_array(raw_ptr, _pathbuf)
}
fn _convert_raw_ptr_array<F, R>(raw_ptr: *mut *mut c_char, convert: F) -> Vec<R>
where
F: Fn(*const c_char) -> Option<R>,
{
let mut ret_val = Vec::new();
let mut i = 0;
unsafe {
loop {
let ptr = raw_ptr.add(i);
if ptr.is_null() {
break;
}
let next = ptr.read();
if next.is_null() {
break;
}
if let Some(value) = convert(next) {
ret_val.push(value);
}
i += 1;
}
}
ret_val
}
pub fn _last_cpl_err(cpl_err_class: CPLErr::Type) -> GdalError {
let last_err_no = unsafe { gdal_sys::CPLGetLastErrorNo() };
let last_err_msg = _string(unsafe { gdal_sys::CPLGetLastErrorMsg() });
unsafe { gdal_sys::CPLErrorReset() };
GdalError::CplError {
class: cpl_err_class,
number: last_err_no,
msg: last_err_msg.unwrap_or_default(),
}
}
pub fn _last_null_pointer_err(method_name: &'static str) -> GdalError {
let last_err_msg = _string(unsafe { gdal_sys::CPLGetLastErrorMsg() });
unsafe { gdal_sys::CPLErrorReset() };
GdalError::NullPointer {
method_name,
msg: last_err_msg.unwrap_or_default(),
}
}
pub fn _path_to_c_string(path: &Path) -> Result<CString> {
let path_str = path.to_string_lossy();
CString::new(path_str.as_ref()).map_err(Into::into)
}