module CBinding_Utility
  use, intrinsic :: iso_c_binding
  implicit none
  private
  
  public :: c_f_logical
  public :: c_f_string, f_c_string, f_c_string_chars, f_c_string_ptr
  
  interface f_c_string
    module procedure f_c_string_ptr
    module procedure f_c_string_chars
  end interface f_c_string

contains

function c_f_logical( &
  & c_logical &
  & ) result( f_logical )

  logical(c_bool), intent(in) :: c_logical
  logical :: f_logical

  if ( c_logical ) then
    f_logical = .true.
  else
    f_logical = .false.
  end if


end function c_f_logical

subroutine c_f_string( &
  & c_string, f_string &
  & )

  character(len=1, kind=c_char), intent(in) :: c_string(*)
  character(len=*), intent(out) :: f_string

  integer :: i

  i = 1
  do while (c_string(i) /= c_null_char .and. i < len(f_string) )
    f_string(i:i) = c_string(i)
    i=i+1
  end do

  if( i < len(f_string) ) f_string(i:) = ' '

end subroutine c_f_string

subroutine f_c_string_chars( &
  & f_string, c_string &
  & ) 
  
  character(*), intent(in) :: f_string
  character(*), intent(inout) :: c_string
  
  integer :: strlen, cstrlen, i
  
  strlen = len_trim(f_string)
  cstrlen = len(c_string)
  
  if ( strlen > cstrlen ) then
    stop
  end if
  
  forall (i=1:strlen) 
    c_string(i:i) = f_string(i:i)
  end forall
  
  c_string(strlen+1:strlen+1) = c_null_char
  
end subroutine f_c_string_chars

subroutine f_c_string_ptr( &
  & f_string, c_string, c_string_len &
  & )

  character(len=*), intent(in) :: f_string
  type(c_ptr), intent(in) :: c_string
  integer, intent(in), optional :: c_string_len

  character(len=1, kind=c_char), pointer :: p_chars(:)
  integer :: i, strlen

  strlen = len_trim(f_string)
  
  if(present(c_string_len)) then
     if(c_string_len <= 0 ) return

     strlen = min(strlen, c_string_len-1)
  end if
  
  if(.not. c_associated(c_string)) then
     return
  end if
  
  call c_f_pointer(c_string, p_chars, [strlen+1])

  forall(i=1:strlen)
     p_chars(i) = f_string(i:i)
  end forall

  p_chars(strlen+1) = c_null_char

end subroutine f_c_string_ptr

end module CBinding_Utility
