From b3339874a338c7092361869fa0b4d427d2975d70 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Mon, 25 May 2020 12:18:10 -0400 Subject: [PATCH] add fortran 90 function interface and demo code --- fortran90/zmatlib.f90 | 116 ++++++++++++++++++++++++++++++++++++++++++ test/f90/Makefile | 7 +++ test/f90/testzmat.f90 | 35 +++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 fortran90/zmatlib.f90 create mode 100644 test/f90/Makefile create mode 100644 test/f90/testzmat.f90 diff --git a/fortran90/zmatlib.f90 b/fortran90/zmatlib.f90 new file mode 100644 index 0000000..3a43965 --- /dev/null +++ b/fortran90/zmatlib.f90 @@ -0,0 +1,116 @@ +!------------------------------------------------------------------------------ +! ZMat - A portable C-library and MATLAB/Octave toolbox for inline data compression +!------------------------------------------------------------------------------ +! +! module: zmatlib +! +!> @author Qianqian Fang +! +!> @brief An interface to call the zmatlib C-library +! +! DESCRIPTION: +!> ZMat provides an easy-to-use interface for stream compression and decompression. +!> +!> It can be compiled as a MATLAB/Octave mex function (zipmat.mex/zmat.m) and compresses +!> arrays and strings in MATLAB/Octave. It can also be compiled as a lightweight +!> C-library (libzmat.a/libzmat.so) that can be called in C/C++/FORTRAN etc to +!> provide stream-level compression and decompression. +!> +!> Currently, zmat/libzmat supports 6 different compression algorthms, including +!> - zlib and gzip : the most widely used algorithm algorithms for .zip and .gz files +!> - lzma and lzip : high compression ratio LZMA based algorithms for .lzma and .lzip files +!> - lz4 and lz4hc : real-time compression based on LZ4 and LZ4HC algorithms +!> - base64 : base64 encoding and decoding +! +!> @section slicense License +!> GPL v3, see LICENSE.txt for details +!------------------------------------------------------------------------------ + +module zmatlib + use iso_c_binding, only: c_char,c_size_t,c_int,c_ptr, c_f_pointer + implicit none + +!------------------------------------------------------------------------------ +!> @brief Compression/encoding methods +! +! DESCRIPTION: +!> 0: zmZlib +!> 1: zmGzip +!> 2: zmBase64 +!> 3: zmLzip +!> 4: zmLzma +!> 5: zmLz4 +!> 6: zmLz4hc +!------------------------------------------------------------------------------ + + integer(c_int), parameter :: zmZlib=0, zmGzip=1, zmBase64=2, zmLzip=3, zmLzma=4, zmLz4=5, zmLz4hc=6 + + interface + +!------------------------------------------------------------------------------ +!> @brief Main interface to perform compression/decompression +! +!> @param[in] inputsize: input stream buffer length +!> @param[in] inputstr: input stream buffer pointer +!> @param[in] outputsize: output stream buffer length +!> @param[in] outputbuf: output stream buffer pointer +!> @param[in] ret: encoder/decoder specific detailed error code (if error occurs) +!> @param[in] iscompress: 0: decompression, 1: use default compression level; +!> negative interger: set compression level (-1, less, to -9, more compression) +!> @return return the coarse grained zmat error code; detailed error code is in ret. +!------------------------------------------------------------------------------ + + integer(c_int) function zmat_run(inputsize, inputbuf, outputsize, outputbuf, zipid, ret, level) bind(C) + use iso_c_binding, only: c_char,c_size_t,c_int,c_ptr + integer(c_size_t), value :: inputsize + integer(c_int), value :: zipid, level + integer(c_size_t), intent(out) :: outputsize + integer(c_int), intent(out) :: ret + character(kind=c_char), intent(in) :: inputbuf(*) + type(c_ptr),intent(out) :: outputbuf + end function zmat_run + +!------------------------------------------------------------------------------ +!> @brief Simplified interface to perform compression, same as zmat_run(...,1) +! +!> @param[in] inputsize: input stream buffer length +!> @param[in] inputstr: input stream buffer pointer +!> @param[in] outputsize: output stream buffer length +!> @param[in] outputbuf: output stream buffer pointer +!> @param[in] ret: encoder/decoder specific detailed error code (if error occurs) +!> @return return the coarse grained zmat error code; detailed error code is in ret. +!------------------------------------------------------------------------------ + + integer(c_int) function zmat_encode(inputsize, inputbuf, outputsize, outputbuf, zipid, ret) bind(C) + use iso_c_binding, only: c_char,c_size_t,c_int,c_ptr + integer(c_size_t), value :: inputsize + integer(c_int), value :: zipid + integer(c_size_t), intent(out) :: outputsize + integer(c_int), intent(out) :: ret + character(kind=c_char), intent(in) :: inputbuf(*) + type(c_ptr),intent(out) :: outputbuf + end function zmat_encode + +!------------------------------------------------------------------------------ +!> @brief Simplified interface to perform decompression, same as zmat_run(...,0) +! +!> @param[in] inputsize: input stream buffer length +!> @param[in] inputstr: input stream buffer pointer +!> @param[in] outputsize: output stream buffer length +!> @param[in] outputbuf: output stream buffer pointer +!> @param[in] ret: encoder/decoder specific detailed error code (if error occurs) +!> @return return the coarse grained zmat error code; detailed error code is in ret. +!------------------------------------------------------------------------------ + + integer(c_int) function zmat_decode(inputsize, inputbuf, outputsize, outputbuf, zipid, ret) bind(C) + use iso_c_binding, only: c_char,c_size_t,c_int,c_ptr + integer(c_size_t), value :: inputsize + integer(c_int), value :: zipid + integer(c_size_t), intent(out) :: outputsize + integer(c_int), intent(out) :: ret + character(kind=c_char), intent(in) :: inputbuf(*) + type(c_ptr),intent(out) :: outputbuf + end function zmat_decode + + end interface +end module diff --git a/test/f90/Makefile b/test/f90/Makefile new file mode 100644 index 0000000..8775753 --- /dev/null +++ b/test/f90/Makefile @@ -0,0 +1,7 @@ +F90 :=gfortran + +all: + $(F90) -g -Wall -pedantic -c ../../fortran90/zmatlib.f90 + $(F90) -g -Wall -pedantic testzmat.f90 -o testzmat -L../../lib -lzmat -lz +clean: + -rm -f testzmat *.o *.mod diff --git a/test/f90/testzmat.f90 b/test/f90/testzmat.f90 new file mode 100644 index 0000000..1404bd9 --- /dev/null +++ b/test/f90/testzmat.f90 @@ -0,0 +1,35 @@ +!------------------------------------------------------------------------------ +! ZMatLib test program +!------------------------------------------------------------------------------ +! +!> @author Qianqian Fang +!> @brief A demo program to call zmatlib functions to encode and decode +! +! DESCRIPTION: +!> This demo program shows how to call zmat_run/zmat_encode/zmat_decode to +!> perform buffer encoding and decoding +!------------------------------------------------------------------------------ + +program zmatdemo + +! step 1: add the below line to use zmatlib unit +use zmatlib +implicit none + +character (len=128) inputstr +integer :: ret, res +integer(kind=8) :: inputlen, outputlen +type(c_ptr) :: outputbuf +character(kind=c_char),pointer :: myout(:) + +inputstr="__o000o__(o)(o)__o000o__ =^_^= __o000o__(o)(o)__o000o__" +inputlen=len(trim(inputstr)) + +print *, trim(inputstr) + +res=zmat_run(inputlen,inputstr,outputlen, outputbuf, zmBase64, ret, 1); + +call c_f_pointer(outputbuf, myout, [outputlen]) +print *, myout + +end program