## Copyright (C) 2018 Guillaume Flandin
##
## This file is part of Octave.
##
## Octave is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING.  If not, see
## <https://www.gnu.org/licenses/>.

## Internal handle class used by memmapfile

classdef (Hidden) __memmapfile_handle__ < handle
  
  properties (Access = private, NonCopyable)
    handle = 0;
    length = 0;
    offset = 0;
  endproperties
  
  methods
    
    function this = mmap (this, filename, lngth, offset, writable)
      printf ("mmap()\n");
      # [this.handle, err, msg] = __mmap__ (filename, lngth, offset, writable);
      rw = ifelse (writable, "r+b", "rb");
      this.handle = fopen (filename, rw);
      fseek (this.handle, offset, "bof");
      this.length = lngth;
      this.offset = offset;
    endfunction
    
    function v = get_data (this, precision, offset, sz, subs)
      fseek (this.handle, this.offset + offset, "bof");
      v = fread (this.handle, prod (sz), ["*" precision]);
      v = reshape (v, sz);
      if (nargin > 4 && ! isempty (subs))
        v = subsref (v, substruct ("()", subs));
      endif
    endfunction
    
    function this = set_data (this, precision, offset, sz, subs, v)
      d = get_data (this, precision, offset, sz);
      d = subsasgn (d, substruct ("()", subs), v);
      if (! isequal (size (d), sz))
        error ("memmapfile: The size of the memory mapped data cannot change.");
      endif
      fseek (this.handle, this.offset + offset, "bof");
      fwrite (this.handle, d, precision);
      fflush (this.handle);
    endfunction
    
    function tf = is_mmapped (this)
      tf = ! isequal (this.handle, 0);
    endfunction
    
    function this = munmap (this)
      if (is_mmapped (this))
        printf ("munmap()\n");
        # [err, msg] = __munmap__ (this.handle, this.length);
        fclose (this.handle);
        this.handle = 0;
        this.length = 0;
        this.offset = 0;
      endif
    endfunction
    
    function delete (this)
      munmap (this);
    endfunction
    
  endmethods
  
endclassdef

 ## No test needed for internal handle class, see memmapfile.
 %!assert (1)
 