!
! This module contains methods for creating, deleting and accessing a "C++" VarContainer through 
! the companion "C" cVarContainer class.  The fortran CVarContainer type stores an opaque pointer
! to a cVarContainer and accesses it through the module procedures which call the corresponding "C" 
! functions.  See varcontainer.h and cvarcontainer.h for more documentation on these methods as 
! they are represented in C.
!
! If there is an exception in the C++ code, it will be caught and a message will be written
! to stderr and the ier integer argument will be returned nonzero. 
!
! a way to use this stuff,
!   use varcontainer_mod
!   type(cVarContainer) :: box
!
!   call init_cvc(box)
!   call new_cvc("mybox", box, ier)              ! or  "call CONTAINER_fetch(box)" when this was 
!                                                ! built with  "python varcontainer.py -n CONTAINER"
!   call addFloat64(box,"pi",3.14159,ier)
!   print *, getFloat64(box, "pi", ier)
!   call delete_cvc(box,ier)
!
! Maximum ranks of each variable type in fortran interface
!   Integer*4, Logical*4 -> 4
!   Real*4,    Real*8    -> 5
!   Character*(*)        -> 4 dimensions + length (rank 4 in fortran, rank 5 in c++)
!   Bytes                -> 0, scalar vector<bytes> with arbitrary length
!
! Mods
!    22Dec2009    Jim.Conboy@cffe.ac.uk
!                 cstring(trim(),  => cstr_2C(trim(), 
!                 [ Former invalid under debug compilation 
!

#include "fpreproc/byte_declare.h"

module varcontainer_mod 
  use fwrap_mod
  implicit none

  !
  ! ---------- data ---------
  !
  integer, external  :: cvc_isheld      ! simple C routine for grabbing the address of a variable

  integer, parameter :: CVC_POINTER=2                              ! size of integer pointer for cVarContainer
  integer, parameter :: CVC_POINTER_DEFAULT(CVC_POINTER) = (/0,0/) ! default value
  integer, parameter :: CVC_CHAR_POINTER_LEN = 64                  ! length of character variables returned in a pointer, stupid fortran 

  logical, parameter, private :: STORE_AXIS_COLON_ARRAY = .false.  ! .true. to store axis names in ":", .false. to use ":0",":1",...
  
  !
  ! --------- CVarContainer -------
  ! fortran cVarContainer type holds the opaque pointer to the cVarContainer instance
  !
  type :: CVarContainer
     integer :: point(CVC_POINTER) = CVC_POINTER_DEFAULT   ! pointer to cVarContainer
  end type CVarContainer


  ! ------------ construction/destruction -------------
  ! Initalizes the cVarContainer to null by allocating the pointer and setting it 
  ! to zero -- stupid fortran.
  !
  ! init_cvc(self)
  !  self = cVarContainer
  !-------
  ! Build a new instance.  The python varcontiner.py code generator provides another method
  ! for creating cVarContainers but as static singletons.
  !
  ! call new_cvc(name,self,ier,nsize)
  !  self = an intialized but empty cVarContainer
  !  name = name of the container
  !  ier  = nonzero on error
  !  nsize = optional number of quantities expected in the container
  !-------
  ! Delete an instance
  !
  ! delete_cvc(self,ier)
  !  self = cVarContainer instance
  !  ier  = nonzero on error
  !
  !-------
  ! Copy the instance pointer to a new pointer.  This copies as a cVarContainer and not a Integer(2).
  !  copy_cvc(self,you)
  !   self = cVarContainer instance
  !   you  = cVarContainer space for pointer
  !
  ! ------------------- operations -------------------
  ! Return the name of the container
  !
  !  container_name(self, name, ier)
  !   self = cVarContainer instance
  !   name = returned name of the container
  !   ier  = nonzero if there was an error
  !-------
  ! Return the number of variables by type (0 for all)
  !
  ! integer vsize(self,itype,ier)
  !   self  = cVarContainer instance
  !   itype = type code (0 for all)
  !   ier   = nonzero if there was an error
  !-------
  ! Return the number of variables by type and store their names internally.  Retrieve
  ! the names with names_fetch()
  !
  ! integer names(self,itype,ier)
  !   self  = cVarContainer instance
  !   itype = type code (0 for all)
  !   ier   = nonzero if there was an error
  !-------
  ! Iterate over the names after a call of names()
  ! names_fetch(self,idone, name, ier)
  !   self  = cVarContainer instance
  !   idone = returns true when the iteration has finished
  !   name  = next name while idone=.false.
  !   ier   = nonzero if there was an error
  !-------
  ! Return true if the container has the named variable
  !
  ! logical has_key(self,name,ier)
  !   self = cVarContainer instance
  !   name = name of the variable
  !   ier  = nonzero if there was an error
  !-------
  ! Remove the named variable
  !
  ! remove(self,name,ier)
  !   self = cVarContainer instance
  !   name = name of the variable
  !   ier  = nonzero if there was an error  
  !--------
  ! Remove all the variables
  !
  ! clear(self,ier)
  !   self = cVarContainer instance
  !   ier  = nonzero if there was an error
  !--------
  ! Retrieve the type of the contained variable
  ! 0 for none
  ! 1 for Integer*4
  ! 2 for Real*4
  ! 3 for Real*8
  ! 4 for Logical*4
  ! 5 for Character
  ! 6 for vector<Byte>
  !
  ! integer getType(self,name,ier)
  !   name = name of the variable
  !   ier  = nonzero if there was an error  
  !--------
  ! Retrieve the rank of the contained variable
  !
  ! integer getRank(self,name,ier)
  !   self = cVarContainer instance
  !   name = name of the variable
  !   ier  = nonzero if there was an error  
  !--------
  ! Get the shape of the contained variable
  !
  ! getShape(self,name, shape, ier)
  !   self  = cVarContainer instance
  !   name  = name of the variable
  !   shape = integer array which will be filled with the shape
  !   ier   = nonzero on error
  !--------
  ! Print the C++ object to stdout for debugging
  ! 
  ! show(self,ier)
  !   self = cVarContainer instance
  !   ier  = nonzero on error
  !
  ! ------------------- attributes ------------------
  ! integer,real*8 and character*(*) attributes can be associated with each variable
  ! and globally with the container.  Some attributes are special
  !  "ctype"     used for netcdf operations, do not use this as a general attribute
  ! for a variable attribute
  !  ":0" -> name of the variable for the first axis
  !  ":1" -> name of the variable for the second axis
  !  ... and so on ...
  ! The ":<n>" attributes provide an association of an axis of a variable with another
  ! rank 1 variable with length equal to the length of the axis.  These attributes are translated
  ! to dimension entries in the netcdf file.  Alternatively, a vector string attribute called ':' can contain 
  ! the names of the dimension variables.
  !--------
  ! Copy the attributes from one variable to another overwriting all of the destination attributes.
  ! Both variables must exist.
  !
  !   attCopy(self,name_src,name_dest,ier)
  !     self      = cVarContainer instance
  !     name_src  = name of variable which is the source of the attributes
  !     name_dest = name of the variable which is the destination
  !     ier       = nonzero on error
  !--------
  ! Set up for editing the attributes of a variable or the global attributes.
  ! Call this before any other attribute access subroutine.  The attributes of a variable
  ! are also setup for editing right after the variable is added to the container.  The internal
  ! attribute pointer will be cleared when the container is modified (e.g. a set method).
  ! 
  ! att(self,name,ier)  or  atts(self,name,ier)
  !   name = name of variable or empty for global attributes
  !   ier  = nonzero on error
  !--------
  ! Get number of attributes
  !
  !   integer attSize(self,ier)
  !     self  = cVarContainer instance
  !     ier   = nonzero on error
  !--------
  ! Remove all the attributes from this variable (or globals)
  !
  !   attClear(self,ier)
  !     self  = cVarContainer instance
  !     ier   = nonzero on error
  !--------
  ! Get the type of an attribute
  !   0 -> attribute does not exist
  !   1 -> integer
  !   2 -> double
  !   3 -> string
  !
  !   integer attType(self,name, ier)
  !     self  = cVarContainer instance
  !     name  = name of attribute
  !     ier   = nonzero on error
  !--------
  ! Get the number of elements in an attribute
  !
  !   integer attNumber(self,name, ier)
  !     self  = cVarContainer instance
  !     name  = name of attribute
  !     ier   = nonzero on error
  !--------
  ! Get info about an attribute.
  !
  !   attInfo(self, name, itype, inum, imaxLength, ier)
  !     self       = cVarContainer instance
  !     name       = name of attribute
  !     itype      = type of attribute or 0 if it does not exist
  !     inum       = number of elements in the attribute
  !     imaxLength = maximum length of a string attribute
  !     ier        = nonzero on error
  !--------
  ! Get an integer scalar attribute
  !
  !   integer attGetInt(self,name,ier,def)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     ier  = nonzero on error
  !     def  = optional default
  !--------
  ! Get a Real*8 scalar attribute
  !
  !   real*8 attGetReal(self,name,ier,def)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     ier  = nonzero on error
  !     def  = optional default
  !--------
  ! Get a string scalar attribute
  !
  !   attGetChar(self,name, cval, ier,def)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     cval = string attribute will be returned here
  !     ier  = nonzero on error
  !     def  = optional default
  !--------
  ! Get a vector attribute (integer,real*8,character)
  !
  !   attGet(self,name,ival,iout,ier,def)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     ival = array where result will be stored
  !     iout = number of values returned
  !     ier  = nonzero on error
  !     def  = optional default array
  !--------
  ! Get a vector attribute as a pointer.  The pointer will be resized to 
  ! the number of values before being returned.  When returning strings the
  ! pointer must be an array with each element of character length 
  ! CVC_CHAR_POINTER_LEN (currently 64).  This limitation is due to my not knowing
  ! how or if it is safe to do an arbitrary length allocation.
  !
  !   attPointer(self,name,ival,ier,def,defNull)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     ival = pointer to a one dimensional array which can be null or is deallocatable
  !     ier  = nonzero on error
  !     def  = optional default array
  !     defNull = if present and .true. and the attribute does not exist then
  !               ival will be set to null
  !--------

  private attGetVectorInt, attGetVectorReal, attGetVectorChar
  interface attGet
    module procedure attGetVectorInt, attGetVectorReal, attGetVectorChar
  end interface
  
  private attPointerInt, attPointerReal, attPointerChar
  interface attPointer
    module procedure attPointerInt, attPointerReal, attPointerChar
  end interface
  
  !--------
  ! Remove an attribute
  ! 
  !   attRemove(self,name,ier)
  !     self = cVarContainer instance
  !     name = name of attribute
  !     ier  = nonzero on error
  !--------
  ! Set an integer attribute
  !
  !   attSetInt(self,name,ival,ier)
  !     self = cVarContainer instance
  !     name = name of the attribute
  !     ival = new value for attribute
  !     ier  = nonzero on error
  !--------
  ! Set a real*8 attribute
  !
  !   attSetReal(self,name,dval,ier)
  !     self = cVarContainer of the cVarContainer
  !     name = name of the attribute
  !     dval = new real*8 value for attribute
  !     ier  = nonzero on error
  !--------
  ! Set a string attribute
  !
  !   attSetChar(self,name,ival,ier)
  !     self = cVarContainer instance
  !     name = name of the attribute
  !     ival = new character string value for attribute
  !     ier  = nonzero on error
  !--------
  ! Set a scalar or vector attribute (integer, real*8, character*(*)).
  !
  !   attSet(self,name,ival,ier)
  !     self = cVarContainer instance
  !     name = name of the attribute
  !     cval = new values for attribute
  !     ier  = nonzero on error
  !
  private attSetVectorInt, attSetVectorReal, attSetVectorChar
  interface attSet
     module procedure attSetInt,  attSetVectorInt
     module procedure attSetReal, attSetVectorReal
     module procedure attSetChar, attSetVectorChar
  end interface

  !---------
  ! Set the "units","label","type","policy" attributes in one function call.  The
  ! "type" and "policy" attributes are only needed for an axis variable.  All these
  ! attributes are optional.
  !
  !   attDesc(self,ier,units, label, type, policy)
  !     self   = cVarContainer instance
  !      ier   = nonzero on error
  !      units = optional units string
  !      label = optional label string
  !      type  = optional type string
  !      policy= optional policy string ("limit","warn","error","periodic")
  !---------
  ! Set the axis attributes ":0",":1",... or the array attribute ":" used to associate an axis with a dimension
  ! in the variable.  Theses axis attributes should be a name of a one dimensional variable
  ! with the same length as this variable's dimension.
  !
  !   attAxis(self,axis, ier)
  !      self = cVarContainer instance
  !      axis = array of strings containing the names of variables for each dimension
  !      ier  = nonzero on error
  !---------
  ! Fetch all the attribute names and store internally in a list.  The number
  ! of names is returned by this function.
  ! 
  !   integer attNames(self,ier)
  !     self = cVarContainer instance
  !     ier  = nonzero on error
  !---------
  ! After an attNames() call, this subroutine fetches one new name on each call.
  ! 
  !   attName_fetch(self,idone, name, ier)
  !     self  = cVarContainer instance
  !     idone = set true when iteration is finished
  !     name  = when not done, a new name is stored in this variable
  !     ier   = nonzero on error
  !
  ! ------------------- netcdf -----------------------
  ! See the attribute section for special handling of some attributes with the netcdf file.
  !----------
  ! Save all the container variables and attributes in a netcdf file.  The variable ":<n>" attributes (or ":" attribute)
  ! are translated to dimension entries.  Variables without a named axis will have dimensions called dim_<m>
  ! where <m> is the length of the axis.
  !
  !   ncsave(self,filename, option, ier, yes, no)
  !     self     = cVarContainer instance
  !     filename = name of netcdf file to create
  !     option   = 0 -> overwrite existing file
  !                1 -> do not overwrite an existing file
  !                2 -> save to a temporary file then copy to filename
  !     ier      = nonzero on error
  !
  !     yes = optional array of character*32 names of attributes.  A variable must contain
  !           at least one of these attributes as a nonzero scalar integer in order to be written
  !           to the netcdf file or the array must be empty.
  !
  !     no  = optional array of character*32 names of attributes.  A variable containing
  !           at least one of these attributes as a nonzero scalar integer will not be saved
  !           to the netcdf file.
  !----------
  ! Load the container from the netcdf file.  Multidimensional attributes will be ignored.  Dimensions
  ! pointing to valid variables will be translated to ":<n>" attributes.
  !
  !   ncload(self,filename, option, ier)
  !     self     = cVarContainer instance
  !     filename = name of an existing netcdf file
  !     option   = 0 -> clear the container before loading the file
  !                1 -> clear global attributes and replace variables and attributes contained in the file
  !                     but do not modify variables not referenced in the file
  !                2 -> do not change dimension or attributes, only set the container data based on the
  !                     data in the netcdf file
  !                3 -> similar to 1 except existing variables have their data copied (like 2) instead of replaced
  !                4 -> clear the container and read in the global attributes only
  !                5 -> similar to 3, do not replace global attributes and copy the data if the key already exists
  !
  ! ---------------------- update ---------------------
  ! Load the container from another cVarContainer.
  !
  !   update(self,you, option, ier)
  !     self     = cVarContainer instance
  !     you      = cVarContainer source instance
  !     option   = 0 -> clear the container before loading the file
  !                1 -> clear global attributes and replace variables and attributes contained in the file
  !                     but do not modify variables not referenced in the file
  !                2 -> do not change dimension or attributes, only set the container data based on the
  !                     data in the netcdf file
  !                3 -> similar to 1 except existing variables have their data copied (like 2) instead of replaced
  !                4 -> clear the container and read in the global attributes only
  !                5 -> similar to 3, do not replace global attributes and copy the data if the key already exists
  !     ier      = nonzero on error
  !
  ! ---------------- share ------------------
  ! Copy pointers from the argument box to this container using the same name.
  ! The variables end up sharing the same memory address so changing the value in one
  ! container changes it in the other.
  !
  !   share(self, you, names, option, ier)
  !     self     = cVarContainer instance
  !     you      = cVarContainer source instance
  !     names    = list of names of variables in source container to share
  !     option   = 0  -> replace variable if the name is already in use 
  !              = 1  -> do not replace existing variables
  !              = 2  -> return an error if there is an existing variable
  !     ier      = nonzero on error
  !
  ! -------------------- Serialization ---------------
  ! sendFile - Serialize the global attributes and container variables to a file.
  !
  !   sendFile(self, filename, ier, names, yes, no)
  !     self     = cVarContainer instance
  !     filename = name of netcdf file to create
  !     ier      = nonzero on error
  !
  !   names = optional list of variable names to send.  If not present or empty then send allocatable
  !           the variables.  A single name called GLOBAL_ATTS will only send the global attributes.
  !
  !     yes = optional array of character*32 names of attributes.  A variable must contain
  !           at least one of these attributes as a nonzero scalar integer in order to be written
  !           to the netcdf file or the array must be empty.
  !
  !     no  = optional array of character*32 names of attributes.  A variable containing
  !           at least one of these attributes as a nonzero scalar integer will not be saved
  !           to the netcdf file.
  !
  !----------------------
  ! receiveFile -> take the serialized data from a file into the container
  !
  !   receiveFile(self, filename, iop, ier, keep, protect)
  !     self     = cVarContainer instance
  !     filename = name of netcdf file to create
  !     option   = 0 -> clear the container before loading the file
  !                1 -> clear global attributes and replace variables and attributes contained in the file
  !                     but do not modify variables not referenced in the file
  !                2 -> do not change dimension or attributes, only set the container data based on the
  !                     data in the netcdf file
  !                3 -> similar to 1 except existing variables have their data copied (like 2) instead of replaced
  !                4 -> clear the container and read in the global attributes only
  !                5 -> similar to 3, do not replace global attributes and copy the data if the key already exists
  !                6 -> similar to 3 but don't change existing variable attributes
  !     ier      = nonzero on error
  ! 
  !     keep     = optional array of character*32 names of attributes.  A variable containing
  !                at least one of these attributes as a nonzero scalar integer will not be replaced
  !                but the data may be changed.  The attributes will not be changed.
  !
  !     protect  = optional array of character*32 names of attributes.  A variable containing
  !                at least one of these attributes as a nonzero scalar integer will not be
  !                changed in any way.
  ! ------------------- scalar only ------------------
  ! Scalar container operations act like values -- the address of the
  ! variable is NOT stored in the container.  The first dimension of a char container variable
  ! acts as the length of the fortran character*(*) string.  The scalar <type>=Char operations work on scalar
  ! fortran character*(*) strings.  A Bytes type is a one dimensional array of bytes.  Each Bytes can
  ! have a different length though the fortran interface only supports scalar Bytes.
  !
  !   <type> = Int32,Float32,Float64,Logical32,Char,Bytes
  !
  ! 
  ! <type> get<type>(self,name,ier,def)  
  !   self   = cVarContainer instance
  !   name   = name of scalar
  !   ier    = return nonzero on error
  !   def    = optional of same type as <type>, will be used without error
  !            if a variable called name does not exist
  !
  !     getChar and getBytes will have to wait for fortran 2008 support.  Use get() method instead.
  !
  ! set<type>(self,name,value,ier)
  !   self   = cVarContainer instance
  !   name   = name of scalar
  !   value  = of type <type>, set contained variable to this value
  !   ier    = return nonzero on error
  !
  ! add<type>(self,name,value,ier)
  !   self   = cVarContainer instance
  !   name   = name of scalar
  !   value  = of type <type>, add a new scalar contained variable and set it to this value,
  !            the argument address is not used for the storage
  !   ier    = return nonzero on error
  !
  ! The scalar Bytes type has the additional methods
  !   int sizeBytes(self, name, ier)   ! return the size of the scalar Bytes in the container
  !     self   = cVarContainer instance
  !     name   = name of scalar
  !     ier    = return nonzero on error
  !
  !   getBytesFile(self,name,file,ier)  ! replace the file with the contents of the Bytes variable
  !     self   = cVarContainer instance
  !     name   = name of scalar
  !     file   = name of file -- will be replaced if it exists
  !     ier    = return nonzero on error
  !    
  !   setBytesFile(self,name,file,ier)  ! set the Bytes variable from the contents of the file
  !     self   = cVarContainer instance
  !     name   = name of scalar
  !     file   = name of file 
  !     ier    = return nonzero on error
  !    
  !   addBytesFile(self,name,file,ier)  ! add a new Bytes variable from the contents of the file
  !     self   = cVarContainer instance
  !     name   = name of scalar
  !     file   = name of file 
  !     ier    = return nonzero on error
  !    
  !   replaceBytesFile(self,name,file,ier)  ! add a new or replace existing Bytes variable from the contents of the file
  !     self   = cVarContainer instance
  !     name   = name of scalar
  !     file   = name of file 
  !     ier    = return nonzero on error
  !    
  !
  ! ------------------- scalar or arrays -------------------
  ! Fetch the fwrap<type> pointer for a variable in the container.  The <type> must match
  ! the type of the variable.  This fwrap<type> pointer allows direct access to the elements 
  ! of the variable.  See fwrap_mod.f90 for more info.
  ! 
  ! array<type>(self, name, fwrap, ier)
  !   self  = cVarContainer instance
  !   name  = name of the variable
  !   fwrap = an integer array of size integer(FW_POINTER) where the opaque fwrap<type> pointer will be stored
  !   ier   = nonzero on error
  !
  !
  ! Retrieve data from the container by copying.
  !
  ! get(self,name,array,ier,def,igot)
  !   self  = cVarContainer instance
  !   name  = name of variable 
  !   array = storage to receive the data, must have the same rank and extents
  !           equal to or larger than the contained variable
  !   ier   = nonzero on error
  !   def   = optional array input, this will be used without error if the variable
  !           does not exist
  !   igot  = optional integer, only for the Bytes version (scalar Bytes only) which
  !           will be set to the number of bytes returned in the one dimensional byte array.  
  !           The array must be large enough to hold all of the bytes in the container Bytes.
  !
  private get_int32_0, get_int32_1,get_int32_2, get_int32_3, get_int32_4
  private get_float32_0, get_float32_1,get_float32_2, get_float32_3, get_float32_4, get_float32_5
  private get_float64_0, get_float64_1,get_float64_2, get_float64_3, get_float64_4, get_float64_5
  private get_logical32_0, get_logical32_1,get_logical32_2, get_logical32_3, get_logical32_4
  private get_char_0, get_char_1, get_char_2, get_char_3, get_char_4
  private get_bytes_0
  interface get
     module procedure get_int32_0, get_int32_1,get_int32_2, get_int32_3, get_int32_4
     module procedure get_float32_0, get_float32_1,get_float32_2, get_float32_3, get_float32_4, get_float32_5
     module procedure get_float64_0, get_float64_1,get_float64_2, get_float64_3, get_float64_4, get_float64_5
     module procedure get_logical32_0, get_logical32_1,get_logical32_2, get_logical32_3, get_logical32_4
     module procedure get_char_0, get_char_1, get_char_2, get_char_3, get_char_4
     module procedure get_bytes_0
  end interface

  !
  ! Copy the argument to the contained variable.
  !
  ! set(self,name, array, ier)
  !   self  = cVarContainer instance
  !   name  = name of variable 
  !   array = data to send to the contained variable, must have the same rank and
  !           extents equal or less than the contained variable
  !   ier   = nonzero on error
  ! 
  private set_int32_0, set_int32_1, set_int32_2, set_int32_3, set_int32_4
  private set_float32_0, set_float32_1, set_float32_2, set_float32_3, set_float32_4, set_float32_5
  private set_float64_0, set_float64_1, set_float64_2, set_float64_3, set_float64_4, set_float64_5
  private set_logical32_0, set_logical32_1, set_logical32_2, set_logical32_3, set_logical32_4
  private set_char_0, set_char_1, set_char_2, set_char_3, set_char_4
  interface set
     module procedure set_int32_0, set_int32_1, set_int32_2, set_int32_3, set_int32_4
     module procedure set_float32_0, set_float32_1, set_float32_2, set_float32_3, set_float32_4, set_float32_5
     module procedure set_float64_0, set_float64_1, set_float64_2, set_float64_3, set_float64_4, set_float64_5
     module procedure set_logical32_0, set_logical32_1, set_logical32_2, set_logical32_3, set_logical32_4
     module procedure set_char_0, set_char_1, set_char_2, set_char_3, set_char_4
     module procedure setScalarBytes
  end interface

  !
  ! Creates a new named variable.  There must not already be a variable with that
  ! name in the container. If inew=0, the argument array is used for the container
  ! storage for this variable otherwise with inew=1 new storage is allocated and the argument array
  ! is copied into it.  Attribute functions can be used for the variable right after it has
  ! been successfully added to the container.
  !
  ! NOTE: because of fortran 90 copying of arguments, the function cvc_hold(array)
  !       must be called immediately before this add() function if inew=0.  The purpose is 
  !       to temporarily store the pointer to the array in a f77/C way.  The add() method will 
  !       then store the pointer to the array in the container along with the type,rank and shape info.
  !
  ! add(self,name, array, inew, ier)
  !   self  = cVarContainer instance
  !   name  = name of variable 
  !   array = the address of this variable will be stored in the container unless
  !           inew is nonzero
  !   inew  = nonzero implies a new array of the same shape will be created for storage 
  !           zero implies this array address will be used for storage (remember to
  !           call cvc_hold(array) first when inew=zero)
  !   ier   = nonzero on error
  !
  !
  ! The following creates a new named variable set to all zero or false or blanks.
  !
  ! add0<type>(self, name, rank, shape, ier)
  !   self  = cVarContainer instance
  !   name  = name of variable 
  !   rank  = rank of variable to create
  !   shape = integer shape at least rank size
  !   ier   = nonzero on error
  !
  !
  private add_int32_0, add_int32_1, add_int32_2, add_int32_3, add_int32_4
  private add_float32_0, add_float32_1, add_float32_2, add_float32_3, add_float32_4, add_float32_5
  private add_float64_0, add_float64_1, add_float64_2, add_float64_3, add_float64_4, add_float64_5
  private add_logical32_0, add_logical32_1, add_logical32_2, add_logical32_3, add_logical32_4
  private add_char_0, add_char_1, add_char_2, add_char_3, add_char_4
  private add_bytes_0
  interface add
     module procedure add_int32_0, add_int32_1, add_int32_2, add_int32_3, add_int32_4
     module procedure add_float32_0, add_float32_1, add_float32_2, add_float32_3, add_float32_4, add_float32_5
     module procedure add_float64_0, add_float64_1, add_float64_2, add_float64_3, add_float64_4, add_float64_5
     module procedure add_logical32_0, add_logical32_1, add_logical32_2, add_logical32_3, add_logical32_4
     module procedure add_char_0, add_char_1, add_char_2, add_char_3, add_char_4
     module procedure add_bytes_0
  end interface
  
  !
  ! variable replacement
  ! An add() will fail if the variable already exists and  a set will fail if the name does not exist.  
  ! This method combines the add()/remove()/set() for the common operation of setting a variable
  ! independent of whether it exists or not.  The 'ioption' argument guides
  ! the operation.  The function returns a nonzero status if the array was added to the container and not
  ! just copied.  The attribute functions will be setup for modifying the variable right after the replace.
  ! Use cvc_hold(array) prior to this call in case the argument array is replaced.
  !      ioption =  0 -> equivalent to remove() & add(), always returns true
  !              =  1 -> if the variable exists with the correct type,rank,shape
  !                      then a copy of the data is performed otherwise the pointer
  !                      is added to the container possibly replacing an existing pointer.
  !              =  2 -> same as 1 but the type can be a copyable_type (float<->double)
  !              =  3 -> same as 2 but the contained variable need only agree in copyable_type and
  !                      rank and have a large enough shape in each dimension to hold
  !                      all of the argument's data
  ! replace(self, name, array, inew, ioption, istatus, ier) 
  !   self    = instance
  !   name    = name of variable 
  !   array   = the address of this variable might be stored in the container unless
  !             inew is nonzero
  !   inew    = nonzero -> a new array of the same shape will be created for storage if necessary
  !             0       -> the argument array address will be used for storage (remember to
  !                        call cvc_hold(array) first when inew=zero) if necessary
  !   ioption = see above
  !   istatus = nonzero when the array was added, zero on copy
  !   ier     = nonzero on error
  !
  private replace_int32_0, replace_int32_1, replace_int32_2, replace_int32_3, replace_int32_4
  private replace_float32_0, replace_float32_1, replace_float32_2, replace_float32_3, replace_float32_4, replace_float32_5
  private replace_float64_0, replace_float64_1, replace_float64_2, replace_float64_3, replace_float64_4, replace_float64_5
  private replace_logical32_0, replace_logical32_1, replace_logical32_2, replace_logical32_3, replace_logical32_4
  private replace_char_0, replace_char_1, replace_char_2, replace_char_3, replace_char_4
  private replace_bytes_0
  interface replace
     module procedure replace_int32_0, replace_int32_1, replace_int32_2, replace_int32_3, replace_int32_4
     module procedure replace_float32_0, replace_float32_1, replace_float32_2, replace_float32_3, replace_float32_4 
     module procedure replace_float32_5
     module procedure replace_float64_0, replace_float64_1, replace_float64_2, replace_float64_3, replace_float64_4
     module procedure replace_float64_5
     module procedure replace_logical32_0, replace_logical32_1, replace_logical32_2, replace_logical32_3, replace_logical32_4
     module procedure replace_char_0, replace_char_1, replace_char_2, replace_char_3, replace_char_4
     module procedure replace_bytes_0
  end interface
  

  !
  ! Will possibly (re)allocate then will fill the pointer argument with the values from the container.  The rank of
  ! the pointer must match the variable name in the container.  If the name does not exist in the container
  ! and a default has been given, the pointer is set to match the default by allocation and copy of the data.  The
  ! shape of the pointer will match the contained variable or the default on exit.
  !
  ! pointer(self,name, pointer, ier, def)
  !   self    = cVarContainer instance
  !   name    = name of the variable
  !   pointer = pointer to an array variable
  !   ier     = return nonzero on error
  !   def     = optional default array of the same type as arraypointer to be used if the variable is not in
  !             the container
  !   defNull = optional logical if present and true then a failure to find the key will cause the pointer
  !             to be deallocated if associated and nullified
  !
  ! character version will need to wait for fortran 2008 when allocate(character(len=n) :: value(k,m)) is legal
  !
  private pointer_int32_0,pointer_int32_1,pointer_int32_2,pointer_int32_3,pointer_int32_4
  private pointer_float32_0,pointer_float32_1,pointer_float32_2,pointer_float32_3,pointer_float32_4,pointer_float32_5
  private pointer_float64_0,pointer_float64_1,pointer_float64_2,pointer_float64_3,pointer_float64_4,pointer_float64_5
  private pointer_logical32_0,pointer_logical32_1,pointer_logical32_2,pointer_logical32_3,pointer_logical32_4
  private pointer_bytes_0
  interface pointer
     module procedure pointer_int32_0,pointer_int32_1,pointer_int32_2,pointer_int32_3,pointer_int32_4
     module procedure pointer_float32_0,pointer_float32_1,pointer_float32_2,pointer_float32_3,pointer_float32_4
     module procedure pointer_float32_5
     module procedure pointer_float64_0,pointer_float64_1,pointer_float64_2,pointer_float64_3,pointer_float64_4
     module procedure pointer_float64_5
     module procedure pointer_logical32_0,pointer_logical32_1,pointer_logical32_2,pointer_logical32_3,pointer_logical32_4
     module procedure pointer_bytes_0
  end interface

  interface getInt32
     module procedure getScalarInt32
  end interface

  interface setInt32
     module procedure setScalarInt32
  end interface

  interface getFloat32
     module procedure getScalarFloat32
  end interface

  interface setFloat32
     module procedure setScalarFloat32
  end interface

  interface getFloat64
     module procedure getScalarFloat64
  end interface

  interface setFloat64
     module procedure setScalarFloat64
  end interface

  interface getLogical32
     module procedure getScalarLogical32
  end interface

  interface setLogical32
     module procedure setScalarLogical32
  end interface

  interface setChar
     module procedure setScalarChar
  end interface

  interface setBytes
     module procedure setScalarBytes
  end interface

  interface atts
     module procedure att
  end interface
contains
  !
  ! initialize cVarContainer with the pointer allocated but null
  !
  subroutine init_cvc(self)
    type(cVarContainer) :: self   ! result

    !allocate(self%point(CVC_POINTER))
    self%point = 0
  end subroutine init_cvc
  

  !
  ! fetch a new cVarContainer
  !
  subroutine new_cvc(name, self, ier, nsize)
    character*(*)       :: name      ! name of variable
    type(cVarContainer) :: self      ! result
    integer             :: ier       ! nonzero on error
    integer, optional   :: nsize     ! size of hash container

    byte_declare :: cname(len(name)+1)   ! name for C

    self%point=0
    call cstring(name,cname,'2C')
    if (present(nsize)) then
       call cvc_new_size(cname,nsize,self%point,ier)
    else
       call cvc_new(cname,self%point,ier)
    end if
  end subroutine new_cvc


  !
  ! delete a cVarContainer
  !
  subroutine delete_cvc(self, ier)
    type(cVarContainer) :: self      ! cVarContainer
    integer             :: ier       ! nonzero on error

    call cvc_delete(self%point,ier)
    self%point=0
  end subroutine delete_cvc

  !
  ! copy the pointer of a cVarContainer, the data is not copied.  The target
  ! must have an allocated but empty pointer.
  !
  subroutine copy_cvc(self, you)
    type(cVarContainer) :: self  ! cVarContainer
    type(cVarContainer) :: you   ! cVarContainer

    call cvc_copy(self%point,you%point)
  end subroutine copy_cvc


  !
  ! number of variables of a given type
  !
  function vsize(self,itype, ier) result(isize)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer :: itype     ! variable type, 0 for all
    integer :: ier       ! nonzero on error
    integer :: isize     ! number of variables

    call cvc_size(self%point, itype, isize, ier)
  end function vsize

  !
  ! returns the number of variable names of a given type and stores the names
  ! internally, they can be retrieved with names_fetch
  !
  function names(self, itype, ier) result(isize)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer :: itype     ! variable type, 0 for all
    integer :: ier       ! nonzero on error
    integer :: isize     ! number of variables

    call cvc_names(self%point, itype, isize, ier)
  end function names

  !
  ! after a call to names, this subroutine iterates over the names to retrieve them
  !
  subroutine names_fetch(self, idone, name, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    logical       :: idone       ! true when iteration is finished
    character*(*) :: name        ! return name
    integer       :: ier         ! nonzero on error

    integer      :: ii, jj
    byte_declare :: cname(len(name)+1)   ! name for C
    
    idone=.false.
    jj = len(name)+1
    call cvc_names_fetch(self%point, ii, jj, cname, ier)
    if (ier==0) then
       idone = ii/=0
       if (.not. idone) call cstring(name,cname,'2F')
    end if
  end subroutine names_fetch

  !
  ! get the name of the container
  !
  subroutine container_name(self, name, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name        ! return name
    integer       :: ier         ! nonzero on error

    integer      :: jj
    byte_declare :: cname(len(name)+1)   ! name for C
    
    jj = len(name)+1
    call cvc_name(self%point, jj, cname, ier)
    if (ier==0) then
       call cstring(name,cname,'2F')
       name = adjustl(trim(name))
    end if
  end subroutine container_name

  !
  ! look for the variable name in the container
  !
  function has_key(self, name, ier) result(out)
type(cVarContainer) :: self  ! cVarContainer
    character*(*)   :: name      ! name of variable
    integer         :: ier       ! nonzero on error
    logical         :: out    ! true if name exists

    integer      :: iresult              ! nonzero for true
    byte_declare :: cname(len(name)+1)   ! name for C

    out=.false.
    call cstring(name,cname,'2C')
    call cvc_has_key(self%point, cname,iresult,ier)
    if (ier==0) out=(iresult/=0)
  end function has_key

  !
  ! remove a variable from the container
  !
  subroutine remove(self,name, ier)
type(cVarContainer) :: self  ! cVarContainer
    character*(*)   :: name   ! name of variable
    integer         :: ier    ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_remove(self%point, cname,ier)
  end subroutine remove

  !
  ! clear all the variables from the container
  !
  subroutine clear(self,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer  :: ier    ! nonzero on error

    call cvc_clear(self%point, ier)
  end subroutine clear

  !
  ! get the type of variable,
  ! 0 for none
  ! 1 for Integer*4
  ! 2 for Real*4
  ! 3 for Real*8
  ! 4 for Logical*4
  ! 5 for Character
  ! 6 for Bytes
  !
  function getType(self,name, ier) result(out)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name   ! name of variable
    integer         :: ier    ! nonzero on error
    integer                       :: out    ! type

    byte_declare :: cname(len(name)+1)   ! name for C

    out=0
    call cstring(name,cname,'2C')
    call cvc_gettype(self%point, cname,out,ier)
  end function getType

  !
  ! get the rank of variable.  For a character variable, the length is included in the rank.
  !
  function getRank(self,name, ier) result(out)
type(cVarContainer) :: self  ! cVarContainer
    character*(*)   :: name   ! name of variable
    integer         :: ier    ! nonzero on error
    integer                       :: out    ! rank

    byte_declare :: cname(len(name)+1)   ! name for C

    out=0
    call cstring(name,cname,'2C')
    call cvc_getrank(self%point, cname,out,ier)
  end function getRank

  !
  ! get the shape of the variable.  For a character variable the first dimensioin will container_name
  ! the length of the character variable.
  !
  subroutine getShape(self,name, result, ier)
type(cVarContainer) :: self  ! cVarContainer
    character*(*)   :: name      ! name of variable
    integer         :: result(:) ! shape array to be filled
    integer         :: ier       ! nonzero on error

    integer :: isize                     ! length of shape array
    byte_declare :: cname(len(name)+1)   ! name for C

    isize = size(result)
    call cstring(name,cname,'2C')
    call cvc_getshape(self%point, cname,isize,result,ier)
  end subroutine getShape  !
  
  !
  ! get the shape of the variable
  !
  subroutine getInfo(self,name, got_key, type, rank, shape, ier)
    type(cVarContainer) :: self  ! cVarContainer
    character*(*)   :: name      ! name of variable
    logical         :: got_key   ! true if this variable is in the container
    integer         :: type      ! if got_key=true, this is the type of the variable
    integer         :: rank      ! if got_key=true, this is the rank of the variable
    integer         :: shape(:)  ! shape array to be filled
    integer         :: ier       ! nonzero on error

    integer :: isize                     ! length of shape array
    integer :: iskey                     ! nonzero if the key exists
    byte_declare :: cname(len(name)+1)   ! name for C

    isize = size(shape)
    call cstring(name,cname,'2C')
    call cvc_getinfo(self%point, cname,iskey,type,rank,isize,shape,ier)
    got_key = (iskey/=0)
  end subroutine getInfo  
  
  !
  ! fetch the named variable into the cVarcontainer object in one of the variables
  ! local_i32, local_f32, local_f64, local_l32
  ! and optionally print out the values
  !
  subroutine local(self, name, iout, ier)
    type(cVarContainer) :: self      ! cVarContainer
    character*(*)       :: name      ! name of variable
    integer             :: iout      ! nonzero to write out the values
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_local(self%point, cname, iout, ier)
  end subroutine local

  !
  ! print C++ object to stdout
  !
  subroutine show(self,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer  :: ier    ! nonzero on error

    call cvc_show(self%point, ier)
  end subroutine show

  !
  ! --------- attributes ---------
  !
  ! fetch the attributes for a variable or the global attributes (empty argument string)
  ! and store them internally.  This must be called prior to the other attribute access
  ! subroutines.  If the container is modified, the internal storage will be cleared.
  !
  subroutine att(self,name, ier) 
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name    ! name of variable or empty for the global attributes
    integer         :: ier     ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att(self%point, cname,ier)    
  end subroutine att

  !
  ! copy the attributes from the source variable to the destination variable.  Both variables must exist.
  !
  subroutine attCopy(self, name_src, name_dest, ier)
    type(cVarContainer) :: self        ! cVarContainer instance
    character*(*)       :: name_src    ! name of source variable or empty for the global attributes
    character*(*)       :: name_dest   ! name of destination variable or empty for the global attributes
    integer             :: ier         ! nonzero on error

    byte_declare :: cname(len(name_src)+1)    ! name for C
    byte_declare :: dname(len(name_dest)+1)   ! name for C
    
    call cstring(name_src, cname,'2C')
    call cstring(name_dest,dname,'2C')
    call cvc_att_copy(self%point, cname, dname, ier)    
  end subroutine attCopy

  !
  ! get the number of attributes after att() call
  !
  function attSize(self,ier) result(isize)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer :: ier      ! nonzero on error
    integer :: isize    ! size result

    call cvc_att_size(self%point, isize,ier)
  end function attSize

  !
  ! remove all the attributes for this variable
  !
  subroutine attClear(self,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer :: ier       ! nonzero on error

    call cvc_att_clear(self%point, ier)
  end subroutine attClear

  !
  ! return the type of the named attribute or return 0 if the attribute does not exist
  !
  function attType(self, name, ier) result(itype)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name    ! name of variable or empty for the global attributes
    integer       :: ier     ! nonzero on error
    integer       :: itype   ! 0->none, 1->int, 2->double, 3->string

    byte_declare :: cname(len(name)+1)   ! name for C


    call cstring(name,cname,'2C')
    call cvc_att_type(self%point, cname,itype,ier) ;
  end function attType

  !
  ! return the number of elements in a named attribute.
  !
  function attNumber(self, name, ier) result(inum)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name    ! name of variable or empty for the global attributes
    integer       :: ier     ! nonzero on error
    integer       :: inum    ! number of elements

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att_vsize(self%point, cname, inum, ier) ;
  end function attNumber

  !
  ! return info about a named attribute.
  !
  subroutine attInfo(self, name, itype, inum, imaxLength, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name       ! name of variable or empty for the global attributes
    integer       :: itype      ! type of attribute, 0 if it does not exist
    integer       :: inum       ! number of elments in the attribute
    integer       :: imaxLength ! for a string attribute the maximum length of any one string
    integer       :: ier        ! nonzero on error

    integer      :: aptr(CVC_POINTER)    ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
  end subroutine attInfo

  !
  ! retrieve an integer scalar attribute
  !
  function attGetInt(self, name, ier, def) result (ival)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    integer       :: ier    ! nonzero on error
    integer       :: ival   ! integer attribute value
    integer, optional :: def
    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_att_get_intdef(self%point, cname,ival,ier,def) 
    else
       call cvc_att_get_int(self%point, cname,ival,ier) 
    end if
  end function attGetInt

  !
  ! retrieve an integer vector attribute
  !
  subroutine attGetVectorInt(self, name, ival, iout, ier, def)
    type(cVarContainer) :: self    ! cVarContainer instance
    character*(*)     :: name      ! name of variable or empty for the global attributes
    integer           :: ival(:)   ! integer attribute values returned
    integer           :: iout      ! number of elements returned
    integer           :: ier       ! nonzero on error
    integer, optional :: def(:)    ! optional default
    
    integer      :: ilen                     ! length of argument
    integer      :: idef                     ! length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C

    ilen  = size(ival)
    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=1) then
      if (present(def)) then
        idef = size(def)
        if (ilen>=idef) then
          iout = idef
          ival(1:idef) = def(1:idef)
          ier=0 ; return
        end if
      end if  
      print *, '?attGetVectorInt: unable to get info about integer attribute '//trim(name) &
               //' and bad default'
      ier=1 ; return
    end if

    if (present(def)) then
       idef = size(def)
       call cvc_att_get_vintdef(aptr, ilen, ival, ier, idef, def, iout) 
    else
       iout = inum
       call cvc_att_get_vint(aptr, ilen, ival, ier) 
    end if
  end subroutine attGetVectorInt

  !
  ! retrieve an integer vector attribute through a pointer
  !
  subroutine attPointerInt(self,name,ival,ier,def,defNull)
    type(cVarContainer) :: self      ! cVarContainer instance

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: ival(:)   ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def(:)    ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    integer      :: idef                     ! length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C

    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=1) then
      if (present(defNull)) then
         if (defNull) then
            if (associated(ival)) deallocate(ival)   ! key not found so nullify and return
            ier=0 ; return
         end if
      end if
      if (.not. present(def)) then
         print *, '?attPointerInt: no default given for nonexistent integer attribute '//name
         ier=1 ; return
      else
         idef = size(def)
         if (associated(ival)) then
           if (idef/=size(ival)) deallocate(ival)
         end if
         if (.not. associated(ival)) allocate(ival(idef))
         ival = def
         ier=0 ; return
      end if                           
    end if

    if (associated(ival)) then
      if (inum/=size(ival)) deallocate(ival)
    end if
    if (.not. associated(ival)) allocate(ival(inum))
       
    call cvc_att_get_vint(aptr, inum, ival, ier) 
  end subroutine attPointerInt

  !
  ! retrieve a floating point attribute
  !
  function attGetReal(self, name, ier, def) result (dval)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    integer       :: ier    ! nonzero on error
    real*8        :: dval   ! integer attribute value
    real*8, optional :: def

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_att_get_fp64def(self%point, cname,dval,ier,def) 
    else
       call cvc_att_get_fp64(self%point, cname,dval,ier) 
    end if
  end function attGetReal

  !
  ! retrieve a real vector attribute
  !
  subroutine attGetVectorReal(self, name, ival, iout, ier, def)
    type(cVarContainer) :: self    ! cVarContainer instance
    character*(*)     :: name      ! name of variable or empty for the global attributes
    real*8            :: ival(:)   ! real attribute values returned
    integer           :: iout      ! number of elements returned
    integer           :: ier       ! nonzero on error
    real*8,  optional :: def(:)    ! optional default
    
    integer      :: ilen                     ! length of argument
    integer      :: idef                     ! length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C

    ilen  = size(ival)
    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=2) then
      if (present(def)) then
        idef = size(def)
        if (ilen>=idef) then
          iout = idef
          ival(1:idef) = def(1:idef)
          ier=0 ; return
        end if
      end if  
      print *, '?attGetVectorReal: unable to get info about real attribute '//trim(name) &
               //' and bad default'
      ier=1 ; return
    end if

    if (present(def)) then
       idef = size(def)
       call cvc_att_get_vfp64def(aptr, ilen, ival, ier, idef, def, iout) 
    else
       iout = inum
       call cvc_att_get_vfp64(aptr, ilen, ival, ier) 
    end if
  end subroutine attGetVectorReal


  !
  ! retrieve a real vector attribute through a pointer
  !
  subroutine attPointerReal(self,name,ival,ier,def,defNull)
    type(cVarContainer) :: self      ! cVarContainer instance

    character*(*)       :: name      ! name of variable
    real*8,pointer      :: ival(:)   ! value to get
    integer             :: ier       ! nonzero on error
    real*8,    optional :: def(:)    ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    integer      :: idef                     ! length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C

    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=2) then
      if (present(defNull)) then
         if (defNull) then
            if (associated(ival)) deallocate(ival)   ! key not found so nullify and return
            ier=0 ; return
         end if
      end if
      if (.not. present(def)) then
         print *, '?attPointerReal: no default given for nonexistent real attribute '//name
         ier=1 ; return
      else
         idef = size(def)
         if (associated(ival)) then
           if (idef/=size(ival)) deallocate(ival)
         end if
         if (.not. associated(ival)) allocate(ival(idef))
         ival = def
         ier=0 ; return
      end if                           
    end if

    if (associated(ival)) then
      if (inum/=size(ival)) deallocate(ival)
    end if
    if (.not. associated(ival)) allocate(ival(inum))
       
    call cvc_att_get_vdouble(aptr, inum, ival, ier) 
  end subroutine attPointerReal

  !
  ! retrieve a string attribute
  !
  subroutine attGetChar(self, name, cval, ier, def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    character*(*) :: cval   ! attribute value
    integer       :: ier    ! nonzero on error
    character*(*), optional :: def

    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: sname(len(cval)+1)   ! result name for C
    byte_declare, allocatable :: dname(:)
    integer      :: ii                   ! size of C string for result

    ii = len(cval)+1
    cval = ' '                       ! clear
    call cstring(name,cname,'2C')
    if (present(def)) then
       allocate(dname(len(def)+1))
       call cstring(def,dname,'2C')
       call cvc_att_get_stringdef(self%point, cname,ii,sname,ier,dname)
       deallocate(dname)
    else
       call cvc_att_get_string(self%point, cname,ii,sname,ier)
    end if
    if (ier==0) call cstring(cval,sname,'2F') 
  end subroutine attGetChar

  !
  ! retrieve a character vector attribute
  !
  subroutine attGetVectorChar(self, name, ival, iout, ier, def)
    type(cVarContainer) :: self    ! cVarContainer instance
    character*(*)     :: name      ! name of variable or empty for the global attributes
    character*(*)     :: ival(:)   ! string attribute values returned
    integer           :: iout      ! number of elements returned
    integer           :: ier       ! nonzero on error
    character*(*),  optional :: def(:)    ! optional default
    
    integer      :: ilen, clen               ! array and character length of argument
    integer      :: idef, cdef               ! array and character length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C
    byte_declare :: cval(len(ival)+1)        ! temp for values
    integer      :: i, jlen                  ! temps

    ilen  = size(ival)
    clen  = len(ival)
    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=3) then
      if (present(def)) goto 100
      print *, '?attGetVectorChar: unable to get info about string attribute '//trim(name)
      ier=1 ; return
    end if

    if (ilen>=inum .and. clen>=imaxLength) then
      do i=0, inum-1
        call cvc_att_get_vxstring(aptr, i, clen, cval, jlen, ier)
        if (ier/=0) exit
        call cstring(ival(i+1),cval,'2F')
      end do
      if (ier==0) then
        iout=inum ; return
      end if
    end if

    if (present(def)) goto 100
    print *, '?attGetVectorChar: error fetching values for string attribute '//trim(name)
    ier=1
    return
    
  100 continue
    idef = size(def)
    cdef = len(def)
    if (ilen>=idef .and. clen>=cdef) then
      iout = idef
      ival(1:idef) = def(1:idef)
      ier=0 ; return
    end if
    print *, '?attGetVectorChar: bad default for string attribute '//trim(name)
    ier=1
  end subroutine attGetVectorChar


  !
  ! retrieve a string vector attribute through a pointer
  !
  subroutine attPointerChar(self,name,ival,ier,def,defNull)
    type(cVarContainer) :: self      ! cVarContainer instance

    character*(*)          :: name      ! name of variable
    character*(*),pointer  :: ival(:)   ! value to get
    integer                :: ier       ! nonzero on error
    character*(*),optional :: def(:)    ! default if present
    logical,      optional :: defNull   ! overrides def to set pointer to null if not found

    character*(CVC_CHAR_POINTER_LEN),pointer :: sptr(:) ! temp

    integer      :: clen                     ! length of cval temp
    integer      :: idef, cdef               ! array and character length of default
    integer      :: itype, inum, imaxLength  ! type and string length of attribute
    integer      :: aptr(CVC_POINTER)        ! attribute opaque pointer    
    byte_declare :: cname(len(name)+1)       ! name for C
    byte_declare,allocatable :: cval(:)      ! temp for values
    integer      :: i, jlen                  ! temps

    itype = 0           ! make sure it is defined
    call cstring(name,cname,'2C')
    call cvc_att_info(self%point, cname, itype, inum, imaxLength, aptr, ier) ;
    if (ier/=0 .or. itype/=3) then
      if (present(defNull)) then
         if (defNull) then
            if (associated(ival)) deallocate(ival)   ! key not found so nullify and return
            ier=0 ; return
         end if
      end if
      if (.not. present(def)) then
         print *, '?attPointerChar: no default given for nonexistent string attribute '//name
         ier=1 ; return
      else
         idef = size(def)
         cdef = len(def)
         if (associated(ival)) then
           if (idef/=size(ival) .or. len(ival)/=CVC_CHAR_POINTER_LEN) then
             deallocate(ival)
           end if
         end if
         if (.not. associated(ival)) then
            allocate(sptr(idef))
            ival => sptr
         else
            sptr => ival
         end if
         sptr = def
         ier=0 ; return
      end if                           
    end if

    if (associated(ival)) then
      if (inum/=size(ival) .or. len(ival)/=CVC_CHAR_POINTER_LEN) then
        deallocate(ival)
      end if
    end if
    if (.not. associated(ival)) then
       allocate(sptr(inum))
       ival => sptr
    else
       sptr => ival
    end if
       
    clen = len(sptr)+1
    allocate(cval(clen))
    do i=0, inum-1
      call cvc_att_get_vxstring(aptr, i, clen, cval, jlen, ier)
      if (ier/=0) exit
      call cstring(sptr(i+1),cval,'2F')
    end do
    deallocate(cval) 
  end subroutine attPointerChar

  !
  ! remove an attribute
  !
  subroutine attRemove(self, name, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name    ! name of variable or empty for the global attributes
    integer       :: ier     ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att_remove(self%point, cname,ier) ;
  end subroutine attRemove

  !
  ! set an attribute as an integer scalar attribute
  !
  subroutine attSetInt(self, name, ival, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    integer       :: ival   ! value of attribute
    integer       :: ier    ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att_set_int(self%point, cname,ival,ier) ;
  end subroutine attSetInt

  !
  ! set an attribute as an integer vector attribute
  !
  subroutine attSetVectorInt(self, name, ival, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name      ! name of variable or empty for the global attributes
    integer       :: ival(:)   ! value of attribute
    integer       :: ier       ! nonzero on error

    integer :: ilen                      ! len
    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    ilen = size(ival)
    call cvc_att_set_vint(self%point, cname,ilen,ival,ier) ;
  end subroutine attSetVectorInt

  !
  ! set a double attribute
  !
  subroutine attSetReal(self, name, dval, ier)
    type(cVarContainer) :: self ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    real*8        :: dval   ! value of attribute
    integer       :: ier    ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_att_set_fp64(self%point, cname,dval,ier) ;
  end subroutine attSetReal

  !
  ! set an attribute as a real vector attribute
  !
  subroutine attSetVectorReal(self, name, ival, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name      ! name of variable or empty for the global attributes
    real*8        :: ival(:)   ! value of attribute
    integer       :: ier       ! nonzero on error

    integer :: ilen                      ! len
    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    ilen = size(ival)
    call cvc_att_set_vfp64(self%point, cname,ilen,ival,ier) ;
  end subroutine attSetVectorReal

  !
  ! set a string scalar attribute
  !
  subroutine attSetChar(self, name, cval, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of variable or empty for the global attributes
    character*(*) :: cval   ! attribute value
    integer       :: ier    ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: sname(len(cval)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cstr_2C(trim(cval),sname,'2C') 
    call cvc_att_set_string(self%point, cname,sname,ier) ;
  end subroutine attSetChar

  !
  ! set a string vector attribute
  !
  subroutine attSetVectorChar(self, name, ival, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name     !  name of variable or empty for the global attributes
    character*(*) :: ival(:)  ! attribute value
    integer       :: ier      ! nonzero on error

    integer :: aptr(CVC_POINTER)         ! attribute opaque pointer    
    integer :: ilen, clen                ! array and character lengths of ival
    integer :: i                         ! temp
    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: sname(len(ival)+1)   ! name for C

    ilen = size(ival)

    call cstring(name,cname,'2C')
    call cvc_att_create_vstring(self%point, cname, ilen, aptr, ier)
    if (ier/=0) return
    do i=0, ilen-1
      clen = len_trim(ival(i+1))
      call cstring(ival(i+1)(1:clen),sname,'2C') 
      call cvc_att_set_vxstring(aptr, i, clen, sname, ier)
      if (ier/=0) exit
    end do
  end subroutine attSetVectorChar

  !
  ! returns the number of attribute names and stores the names
  ! internally, they can be retrieved with attName_fetch
  !
  function attNames(self,ier) result(isize)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer :: ier       ! nonzero on error
    integer :: isize     ! number of variables

    call cvc_att_names(self%point, isize, ier)
  end function attNames

  !
  ! after a call to attNames, this subroutine iterates over the names to retrieve them
  !
  subroutine attName_fetch(self, idone, name, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    logical       :: idone       ! true when iteration is finished
    character*(*) :: name        ! return name
    integer       :: ier         ! nonzero on error

    integer      :: ii, jj
    byte_declare :: cname(len(name)+1)   ! name for C
    

    idone=.false.
    jj = len(name)+1
    call cvc_att_name_fetch(self%point, ii, jj, cname, ier)
    if (ier==0) then
       idone = ii/=0
       if (.not. idone) call cstring(name,cname,'2F')
    end if
  end subroutine attName_fetch

  !
  ! a convenience function for setting the "units","label","type" and "policy" attributes
  !
  subroutine attDesc(self, ier, units, label, type, policy)
    type(cVarContainer)     :: self     ! cVarContainer instance
    integer                 :: ier      ! nonzero on error
    character*(*), optional :: units    ! units attribute
    character*(*), optional :: label    ! label attribute
    character*(*), optional :: type     ! string which matches a NumericAxisType
    character*(*), optional :: policy   ! string which matches a NumericAxisType.BoundaryPolicy


    ier=0
    if (present(units)) then
       call attSetChar(self,"units",trim(units),ier) ; if (ier/=0) return
    end if
    if (present(label)) then
       call attSetChar(self,"label",label,ier) ; if (ier/=0) return
    end if
    if (present(type)) then
       call attSetChar(self,"AxisType",trim(type),ier) ; if (ier/=0) return
    end if
    if (present(policy)) then
       call attSetChar(self,"AxisPolicy",trim(policy),ier) ; if (ier/=0) return
    end if
  end subroutine attDesc

  !
  ! a convenience function for setting the axis attributes ":0", ":1",...
  ! Each attribute is set in order terminating on the first empty string (if any).
  ! A maximum of 9 axis can be added in this manner though you'll run into other
  ! troubles when you hit 7 axis.
  !
  subroutine attAxis(self,axis, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer       :: ier       ! nonzero on error
    character*(*) :: axis(:)   ! list of axis
    character*2   :: att       ! attribute name
    integer       :: i,ic      ! loop variable
    character*(len(axis)) :: zxis(size(axis)) 
    
    ier=0
    
    if (STORE_AXIS_COLON_ARRAY) then
      ic = 0
      do i = 1, size(axis)
        if (len_trim(axis(i))==0) exit   ! empty axis name
        if (i>7) goto 100
        zxis(i) = trim(adjustl(axis(i)))
        ic = i
      end do    
      call attSetVectorChar(self, ":", zxis(1:ic), ier)
    else
      do i = 1, size(axis)
        if (len_trim(axis(i))==0) return   ! empty axis name
        if (i>7) goto 100
        write(att,'(a1,i1)') ':',i-1
        call attSetChar(self,att,trim(adjustl(axis(i))),ier)
        if (ier/=0) return
      end do
    end if
    return
    
  100 continue
    print *, '?attAxis: more then 7 axis names were supplied as attributes'
    ier=1  
  end subroutine attAxis

  !
  ! ---------- netcdf -----------
  !
  ! save the container to a netcdf file
  !  option = 0->overwrite, 1->do not overwrite, 2->write to temporary then overwrite 
  !
  subroutine ncsave(self,name, iop, ier, yes, no)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name   ! name of file
    integer             :: iop    ! option
    integer             :: ier    ! nonzero on error

    character*32, optional :: yes(:)     ! if present, variables saved must contain at least one nonzero scalar integer
                                         ! attribute with one of these names
    character*32, optional :: no(:)      ! if present, variables saved must not contain a nonzero scalar integer
                                         ! attribute with these names

    byte_declare :: cname(len(name)+1)   ! name for C

    integer :: i,k     ! temps

    integer                   :: nyes     ! number of yes attributes
    integer,      allocatable :: kyes(:)  ! C indices into packed yes string names
    byte_declare, allocatable :: syes(:)  ! packed yes string names

    integer                   :: nno      ! number of no attributes
    integer,      allocatable :: kno(:)   ! C indices into packed no string names
    byte_declare, allocatable :: sno(:)   ! packed no string names

    ! -- name --
    call cstr_2C(trim(adjustl(name)),cname,'2C')

    ! -- yes attributes --
    if (present(yes)) then
       nyes = size(yes)

       allocate(kyes(nyes+1),syes(33*nyes))  ! account for terminating zero
    else
       nyes = 0

       allocate(kyes(1), syes(1)) 
    end if

    kyes=0
    syes=0
    do i = 1, nyes
       k = len_trim(adjustl(yes(i)))

       call cstr_2C(trim(adjustl(yes(i))),syes(kyes(i)+1:),'2C')

       kyes(i+1) = kyes(i)+k+1  ! C index
    end do

    ! -- no attributes --
    if (present(no)) then
       nno = size(no)

       allocate(kno(nno+1),sno(33*nno))
    else
       nno = 0

       allocate(kno(1), sno(1)) 
    end if

    kno=0
    sno=0
    do i = 1, nno
       k = len_trim(adjustl(no(i)))

       call cstr_2C(trim(adjustl(no(i))),sno(kno(i)+1:),'2C')

       kno(i+1) = kno(i)+k+1  ! C index
    end do

    ! -- save --
    call cvc_ncsave(self%point, cname,iop,ier, nyes,kyes,syes, nno,kno,sno) ;

    deallocate(kyes, syes, kno, sno)
  end subroutine ncsave

  !
  ! load the container from a netcdf file
  ! option   = 0->clear container first, 1->replace duplicates, 2->change only existing data
  !
  subroutine ncload(self, name, iop, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*) :: name   ! name of file
    integer       :: iop    ! option
    integer       :: ier    ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstr_2C(trim(adjustl(name)),cname,'2C')
    call cvc_ncload(self%point, cname,iop,ier) ;
  end subroutine ncload

  !
  ! ----------------- update -----------------
  !
  ! load the container from another container
  ! option   = 0->clear container first, 1->replace duplicates, 2->change only existing data
  !
  subroutine update(self, you, iop, ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    type(cVarContainer) :: you    ! source cVarContainer instance
    integer       :: iop    ! option
    integer       :: ier    ! nonzero on error

    call cvc_update(self%point, you%point, iop, ier) ;
  end subroutine update

  !
  ! --------- share ---------
  subroutine share(self, you, names, iop, ier) ;
    type(cVarContainer) :: self      ! cVarContainer instance
    type(cVarContainer) :: you       ! source cVarContainer instance
    character*32        :: names(:)  ! share these variables
    integer             :: iop       ! option = 0  -> replace variable if the name is already in use 
                                     !        = 1  -> do not replace existing variables
                                     !        = 2  -> return an error if there is an existing variable                                                     
    integer             :: ier       ! nonzero on error
    
    integer                   :: nnames     ! number of variables
    integer,      allocatable :: knames(:)  ! C indices into packed names string names
    byte_declare, allocatable :: snames(:)  ! packed names string names

    integer :: i, k
    
    nnames = size(names)

    allocate(knames(nnames+1),snames(33*nnames))  ! account for terminating zero

    knames=0
    snames=0
    do i = 1, nnames
       k = len_trim(adjustl(names(i)))

       call cstr_2C(trim(adjustl(names(i))),snames(knames(i)+1:),'2C')

       knames(i+1) = knames(i)+k+1  ! C index
    end do

    call cvc_share(self%point, you%point, nnames,knames,snames, iop, ier) ;
    
     deallocate(knames, snames)
  end subroutine share
  
  !
  ! ---------- sendFile -----------
  !
  ! Serialize the container to a file 
  !
  subroutine sendFile(self, name, ier, names, yes, no)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name   ! name of file
    integer             :: ier    ! nonzero on error

    character*32, optional :: names(:)   ! if present, only send these variables.  If it contains only GLOBAL_ATTS
                                         ! then send the global attributes and nothing else.
    character*32, optional :: yes(:)     ! if present, variables saved must contain at least one nonzero scalar integer
                                         ! attribute with one of these names
    character*32, optional :: no(:)      ! if present, variables saved must not contain a nonzero scalar integer
                                         ! attribute with these names

    byte_declare :: cname(len(name)+1)   ! name for C

    integer :: i,k     ! temps

    integer                   :: nnames     ! number of variables
    integer,      allocatable :: knames(:)  ! C indices into packed names string names
    byte_declare, allocatable :: snames(:)  ! packed names string names

    integer                   :: nyes     ! number of yes attributes
    integer,      allocatable :: kyes(:)  ! C indices into packed yes string names
    byte_declare, allocatable :: syes(:)  ! packed yes string names

    integer                   :: nno      ! number of no attributes
    integer,      allocatable :: kno(:)   ! C indices into packed no string names
    byte_declare, allocatable :: sno(:)   ! packed no string names

    ! -- name --
    call cstr_2C(trim(adjustl(name)),cname,'2C')

    ! -- names attributes --
    if (present(names)) then
       nnames = size(names)

       allocate(knames(nnames+1),snames(33*nnames))  ! account for terminating zero
    else
       nnames = 0

       allocate(knames(1), snames(1)) 
    end if

    knames=0
    snames=0
    do i = 1, nnames
       k = len_trim(adjustl(names(i)))

       call cstr_2C(trim(adjustl(names(i))),snames(knames(i)+1:),'2C')

       knames(i+1) = knames(i)+k+1  ! C index
    end do

    ! -- yes attributes --
    if (present(yes)) then
       nyes = size(yes)

       allocate(kyes(nyes+1),syes(33*nyes))  ! account for terminating zero
    else
       nyes = 0

       allocate(kyes(1), syes(1)) 
    end if

    kyes=0
    syes=0
    do i = 1, nyes
       k = len_trim(adjustl(yes(i)))

       call cstr_2C(trim(adjustl(yes(i))),syes(kyes(i)+1:),'2C')

       kyes(i+1) = kyes(i)+k+1  ! C index
    end do

    ! -- no attributes --
    if (present(no)) then
       nno = size(no)

       allocate(kno(nno+1),sno(33*nno))
    else
       nno = 0

       allocate(kno(1), sno(1)) 
    end if

    kno=0
    sno=0
    do i = 1, nno
       k = len_trim(adjustl(no(i)))

       call cstr_2C(trim(adjustl(no(i))),sno(kno(i)+1:),'2C')

       kno(i+1) = kno(i)+k+1  ! C index
    end do

    ! -- save --
    call cvc_sendfile(self%point, cname, ier, nnames,knames,snames, nyes,kyes,syes, nno,kno,sno) ;

    deallocate(knames, snames, kyes, syes, kno, sno)
  end subroutine sendFile


  !
  ! ---------- receiveFile -----------
  !
  ! Serialize the container from a file 
  !
  subroutine receiveFile(self, name, iop, ier, keep, protect)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name   ! name of file
    integer             :: iop    ! option
    integer             :: ier    ! nonzero on error

    character*32, optional :: keep(:)    ! if present, variables which have this nonzero integer attribute are 
                                         ! not replaced but can be set
    character*32, optional :: protect(:) ! if present, variables which have this nonzero integer attribute are
                                         ! not changed in any way

    byte_declare :: cname(len(name)+1)   ! name for C

    integer :: i,k     ! temps

    integer                   :: nyes     ! number of yes attributes
    integer,      allocatable :: kyes(:)  ! C indices into packed yes string names
    byte_declare, allocatable :: syes(:)  ! packed yes string names

    integer                   :: nno      ! number of no attributes
    integer,      allocatable :: kno(:)   ! C indices into packed no string names
    byte_declare, allocatable :: sno(:)   ! packed no string names

    ! -- name --
    call cstr_2C(trim(adjustl(name)),cname,'2C')

    ! -- yes attributes --
    if (present(keep)) then
       nyes = size(keep)

       allocate(kyes(nyes+1),syes(33*nyes))  ! account for terminating zero
    else
       nyes = 0

       allocate(kyes(1), syes(1)) 
    end if

    kyes=0
    syes=0
    do i = 1, nyes
       k = len_trim(adjustl(keep(i)))

       call cstr_2C(trim(adjustl(keep(i))),syes(kyes(i)+1:),'2C')

       kyes(i+1) = kyes(i)+k+1  ! C index
    end do

    ! -- no attributes --
    if (present(protect)) then
       nno = size(protect)

       allocate(kno(nno+1),sno(33*nno))
    else
       nno = 0

       allocate(kno(1), sno(1)) 
    end if

    kno=0
    sno=0
    do i = 1, nno
       k = len_trim(adjustl(protect(i)))

       call cstr_2C(trim(adjustl(protect(i))),sno(kno(i)+1:),'2C')

       kno(i+1) = kno(i)+k+1  ! C index
    end do

    ! -- save --
    call cvc_receivefile(self%point, cname, iop, ier, nyes,kyes,syes, nno,kno,sno) ;

    deallocate(kyes, syes, kno, sno)
  end subroutine receiveFile


  !
  ! ---------- Integer*4 ---------
  !
  function getScalarInt32(self, name, ier, def) result(value)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)            :: name      ! name of variable
    integer                  :: ier       ! nonzero on error
    integer*4, optional      :: def       ! default
    integer*4                              :: value     ! result

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')

    if (present(def)) then
       call cvc_getdefscalarint32(self%point, cname,value,def,ier)
    else
       call cvc_getscalarint32(self%point, cname,value,ier)
    end if
  end function getScalarInt32
    
  subroutine setScalarInt32(self, name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)      :: name      ! name of variable
    integer*4          :: value     ! value to set
    integer            :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setscalarint32(self%point, cname,value,ier)
  end subroutine setScalarInt32

  subroutine addInt32(self, name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)      :: name      ! name of variable
    integer*4          :: value     ! value to set
    integer            :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_addscalarint32(self%point, cname,value,ier)
  end subroutine addInt32

  subroutine get_int32_0(self, name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefint32(self%point, cname,0,0,value,0,0,def,ier)
    else
       call cvc_getint32(self%point, cname,0,0,value,ier)
    end if
  end subroutine get_int32_0

  subroutine get_int32_1(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    integer*4           :: value(:)     ! value to get
    integer             :: ier          ! nonzero on error
    integer*4, optional :: def(:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefint32(self%point, cname,1,(/size(value,1)/),value,1,(/size(def,1)/),def,ier)
    else
       call cvc_getint32(self%point, cname,1,(/size(value,1)/),value,ier)
    end if
  end subroutine get_int32_1

  subroutine get_int32_2(self, name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    integer*4           :: value(:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    integer*4, optional :: def(:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefint32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            2,&
            (/size(def,1),size(def,2)/),&
            def,&
            ier)
    else
       call cvc_getint32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            ier)
    end if
  end subroutine get_int32_2

  subroutine get_int32_3(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    integer*4           :: value(:,:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    integer*4, optional :: def(:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefint32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            3,&
            (/size(def,1),size(def,2),size(def,3)/),&
            def,&
            ier)
    else
       call cvc_getint32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            ier)
    end if
  end subroutine get_int32_3

  subroutine get_int32_4(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    integer*4           :: value(:,:,:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    integer*4, optional :: def(:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefint32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            4,&
            (/size(def,1),size(def,2),size(def,3),size(def,4)/),&
            def,&
            ier)
    else
       call cvc_getint32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            ier)
    end if
  end subroutine get_int32_4

  subroutine set_int32_0(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value     ! value to get
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setint32(self%point, cname,0,0,value,ier)
  end subroutine set_int32_0

  subroutine set_int32_1(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setint32(self%point, cname,1,(/size(value,1)/),value,ier)
  end subroutine set_int32_1
  
  subroutine set_int32_2(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:)     ! value to get
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setint32(self%point, cname,2,(/size(value,1),size(value,2)/),value,ier)
  end subroutine set_int32_2
  
  subroutine set_int32_3(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setint32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,ier)
  end subroutine set_int32_3
  
  subroutine set_int32_4(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setint32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,ier)
  end subroutine set_int32_4
  
  subroutine add_int32_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addint32(self%point, cname,0,0,value,inew,ier)
  end subroutine add_int32_0

  subroutine add_int32_1(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addint32(self%point, cname,1,(/size(value,1)/),value,inew,ier)
  end subroutine add_int32_1
  
  subroutine add_int32_2(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addint32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ier)
  end subroutine add_int32_2
  
  subroutine add_int32_3(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addint32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ier)
  end subroutine add_int32_3
  
  subroutine add_int32_4(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addint32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,inew,ier)
  end subroutine add_int32_4
  

  subroutine replace_int32_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replaceint32(self%point, cname,0,0,value,inew,ioption,istatus,ier)
  end subroutine replace_int32_0

  subroutine replace_int32_1(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replaceint32(self%point, cname,1,(/size(value,1)/),value,inew,ioption,istatus,ier)
  end subroutine replace_int32_1
  
  subroutine replace_int32_2(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replaceint32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ioption,istatus,ier)
  end subroutine replace_int32_2
  
  subroutine replace_int32_3(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replaceint32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ioption,istatus,ier)
  end subroutine replace_int32_3
  
  subroutine replace_int32_4(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer*4           :: value(:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replaceint32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
    inew,ioption,istatus,ier)
  end subroutine replace_int32_4
  

  subroutine pointer_int32_0(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=0

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: value     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(1)      ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self, name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       ! shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = .true.                     ! size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value)       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_int32_0

  subroutine pointer_int32_1(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=1

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def(:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ! shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1)                     ! .and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1)))       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_int32_1

  subroutine pointer_int32_2(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=2

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: value(:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def(:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_int32_2

  subroutine pointer_int32_3(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=3

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: value(:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def(:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape


    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_int32_3

  subroutine pointer_int32_4(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=4

    character*(*)       :: name      ! name of variable
    integer*4,pointer   :: value(:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    integer*4, optional :: def(:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3).and.size(value,4)==shape(4)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_int32_4


  subroutine add0Int32(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (size(shape)<rank) then
       print *, '?add0Int32: shape is not large enough for the rank'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0int32(self%point, cname, rank, shape, ier)
    end if
  end subroutine add0Int32

  subroutine arrayInt32(self, name, fwrap, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer :: fwrap(FW_POINTER)       ! fwrap<type> instance
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_arrayint32(self%point, cname, fwrap, ier)
  end subroutine arrayInt32

  !
  ! ---------- Real*4 ---------
  !
  function getScalarFloat32(self,name, ier, def) result(value)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: ier       ! nonzero on error
    real*4, optional      :: def       ! default
    real*4                              :: value     ! result

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')

    if (present(def)) then
       call cvc_getdefscalarfloat32(self%point, cname,value,def,ier)
    else
       call cvc_getscalarfloat32(self%point, cname,value,ier)
    end if
  end function getScalarFloat32
    
  subroutine setScalarFloat32(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    real*4          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setscalarfloat32(self%point, cname,value,ier)
  end subroutine setScalarFloat32

  subroutine addFloat32(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    real*4          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_addscalarfloat32(self%point, cname,value,ier)
  end subroutine addFloat32

  subroutine get_float32_0(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value     ! value to get
    integer          :: ier       ! nonzero on error
    real*4, optional :: def       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,0,0,value,0,0,def,ier)
    else
       call cvc_getfloat32(self%point, cname,0,0,value,ier)
    end if
  end subroutine get_float32_0

  subroutine get_float32_1(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*4           :: value(:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*4, optional :: def(:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,1,(/size(value,1)/),value,1,(/size(def,1)/),def,ier)
    else
       call cvc_getfloat32(self%point, cname,1,(/size(value,1)/),value,ier)
    end if
  end subroutine get_float32_1

  subroutine get_float32_2(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*4           :: value(:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*4, optional :: def(:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            2,&
            (/size(def,1),size(def,2)/),&
            def,&
            ier)
    else
       call cvc_getfloat32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            ier)
    end if
  end subroutine get_float32_2

  subroutine get_float32_3(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*4           :: value(:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*4, optional :: def(:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            3,&
            (/size(def,1),size(def,2),size(def,3)/),&
            def,&
            ier)
    else
       call cvc_getfloat32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            ier)
    end if
  end subroutine get_float32_3

  subroutine get_float32_4(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*4           :: value(:,:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*4, optional :: def(:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            4,&
            (/size(def,1),size(def,2),size(def,3),size(def,4)/),&
            def,&
            ier)
    else
       call cvc_getfloat32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            ier)
    end if
  end subroutine get_float32_4

  subroutine get_float32_5(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*4           :: value(:,:,:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*4, optional :: def(:,:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat32(self%point, cname,&
            5,&
            (/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),&
            value,&
            5,&
            (/size(def,1),size(def,2),size(def,3),size(def,4),size(def,5)/),&
            def,&
            ier)
    else
       call cvc_getfloat32(self%point, cname,&
            5,&
            (/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),&
            value,&
            ier)
    end if
  end subroutine get_float32_5

  subroutine set_float32_0(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname,0,0,value,ier)
  end subroutine set_float32_0

  subroutine set_float32_1(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname,1,(/size(value,1)/),value,ier)
  end subroutine set_float32_1
  
  subroutine set_float32_2(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname,2,(/size(value,1),size(value,2)/),value,ier)
  end subroutine set_float32_2
  
  subroutine set_float32_3(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,ier)
  end subroutine set_float32_3
  
  subroutine set_float32_4(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,ier)
  end subroutine set_float32_4
  
  subroutine set_float32_5(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat32(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          ier)
  end subroutine set_float32_5
  
  subroutine add_float32_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname,0,0,value,inew,ier)
  end subroutine add_float32_0

  subroutine add_float32_1(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname,1,(/size(value,1)/),value,inew,ier)
  end subroutine add_float32_1
  
  subroutine add_float32_2(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ier)
  end subroutine add_float32_2
  
  subroutine add_float32_3(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ier)
  end subroutine add_float32_3
  
  subroutine add_float32_4(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,inew,ier)
  end subroutine add_float32_4
  
  subroutine add_float32_5(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*4           :: value(:,:,:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat32(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          inew,ier)
  end subroutine add_float32_5
  

  subroutine replace_float32_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4           :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname,0,0,value,inew,ioption,istatus,ier)
  end subroutine replace_float32_0

  subroutine replace_float32_1(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4           :: value(:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname,1,(/size(value,1)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float32_1
  
  subroutine replace_float32_2(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4           :: value(:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float32_2
  
  subroutine replace_float32_3(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4           :: value(:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float32_3
  
  subroutine replace_float32_4(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4           :: value(:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
    inew,ioption,istatus,ier)
  end subroutine replace_float32_4
  
  subroutine replace_float32_5(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*4              :: value(:,:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat32(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_float32_5
  
  subroutine pointer_Float32_0(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=0

    character*(*)       :: name      ! name of variable
    real*4,pointer   :: value     ! value to get
    integer             :: ier       ! nonzero on error
    real*4, optional :: def       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(1)      ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       ! shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = .true.                     ! size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value)       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_0

  subroutine pointer_Float32_1(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=1

    character*(*)       :: name      ! name of variable
    real*4,pointer   :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*4, optional :: def(:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ! shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1)                     ! .and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1)))       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_1

  subroutine pointer_Float32_2(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=2

    character*(*)       :: name      ! name of variable
    real*4,pointer   :: value(:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*4, optional :: def(:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_2

  subroutine pointer_Float32_3(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=3

    character*(*)       :: name      ! name of variable
    real*4,pointer   :: value(:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*4, optional :: def(:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_3

  subroutine pointer_Float32_4(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=4

    character*(*)       :: name      ! name of variable
    real*4,pointer   :: value(:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*4, optional :: def(:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3).and.size(value,4)==shape(4)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_4

  subroutine pointer_Float32_5(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=5

    character*(*)       :: name      ! name of variable
    real*4,pointer      :: value(:,:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*4,    optional :: def(:,:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4); shape(5)=size(def,5)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3) &
             .and.size(value,4)==shape(4).and.size(value,5)==shape(5)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4),shape(5)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float32_5

  subroutine add0Float32(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (size(shape)<rank) then
       print *, '?add0Float32: shape is not large enough for the rank'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0float32(self%point, cname, rank, shape, ier)
    end if
  end subroutine add0Float32

  subroutine arrayFloat32(self, name, fwrap, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer :: fwrap(FW_POINTER)       ! fwrap<type> instance
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_arrayfloat32(self%point, cname, fwrap, ier)
  end subroutine arrayFloat32

  !
  ! ---------- real*8 ---------
  !
  function getScalarFloat64(self,name, ier, def) result(value)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: ier       ! nonzero on error
    real*8, optional      :: def       ! default
    real*8                              :: value     ! result

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')

    if (present(def)) then
       call cvc_getdefscalarfloat64(self%point, cname,value,def,ier)
    else
       call cvc_getscalarfloat64(self%point, cname,value,ier)
    end if
  end function getScalarFloat64
    
  subroutine setScalarFloat64(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    real*8          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setscalarfloat64(self%point, cname,value,ier)
  end subroutine setScalarFloat64

  subroutine addFloat64(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    real*8          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_addscalarfloat64(self%point, cname,value,ier)
  end subroutine addFloat64

  subroutine get_float64_0(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value     ! value to get
    integer          :: ier       ! nonzero on error
    real*8, optional :: def       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,0,0,value,0,0,def,ier)
    else
       call cvc_getfloat64(self%point, cname,0,0,value,ier)
    end if
  end subroutine get_float64_0

  subroutine get_float64_1(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*8           :: value(:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*8, optional :: def(:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,1,(/size(value,1)/),value,1,(/size(def,1)/),def,ier)
    else
       call cvc_getfloat64(self%point, cname,1,(/size(value,1)/),value,ier)
    end if
  end subroutine get_float64_1

  subroutine get_float64_2(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*8           :: value(:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*8, optional :: def(:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            2,&
            (/size(def,1),size(def,2)/),&
            def,&
            ier)
    else
       call cvc_getfloat64(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            ier)
    end if
  end subroutine get_float64_2

  subroutine get_float64_3(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*8           :: value(:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*8, optional :: def(:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            3,&
            (/size(def,1),size(def,2),size(def,3)/),&
            def,&
            ier)
    else
       call cvc_getfloat64(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            ier)
    end if
  end subroutine get_float64_3

  subroutine get_float64_4(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*8           :: value(:,:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*8, optional :: def(:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            4,&
            (/size(def,1),size(def,2),size(def,3),size(def,4)/),&
            def,&
            ier)
    else
       call cvc_getfloat64(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            ier)
    end if
  end subroutine get_float64_4

  subroutine get_float64_5(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    real*8           :: value(:,:,:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    real*8, optional :: def(:,:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeffloat64(self%point, cname,&
            5,&
            (/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),&
            value,&
            5,&
            (/size(def,1),size(def,2),size(def,3),size(def,4),size(def,5)/),&
            def,&
            ier)
    else
       call cvc_getfloat64(self%point, cname,&
            5,&
            (/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),&
            value,&
            ier)
    end if
  end subroutine get_float64_5

  subroutine set_float64_0(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname,0,0,value,ier)
  end subroutine set_float64_0

  subroutine set_float64_1(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname,1,(/size(value,1)/),value,ier)
  end subroutine set_float64_1
  
  subroutine set_float64_2(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname,2,(/size(value,1),size(value,2)/),value,ier)
  end subroutine set_float64_2
  
  subroutine set_float64_3(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,ier)
  end subroutine set_float64_3
  
  subroutine set_float64_4(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,ier)
  end subroutine set_float64_4
  
  subroutine set_float64_5(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setfloat64(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          ier)
  end subroutine set_float64_5
  
  subroutine add_float64_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname,0,0,value,inew,ier)
  end subroutine add_float64_0

  subroutine add_float64_1(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname,1,(/size(value,1)/),value,inew,ier)
  end subroutine add_float64_1
  
  subroutine add_float64_2(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ier)
  end subroutine add_float64_2
  
  subroutine add_float64_3(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ier)
  end subroutine add_float64_3
  
  subroutine add_float64_4(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,inew,ier)
  end subroutine add_float64_4
  
  subroutine add_float64_5(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    real*8           :: value(:,:,:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addfloat64(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          inew,ier)
  end subroutine add_float64_5
  

  subroutine replace_float64_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8           :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname,0,0,value,inew,ioption,istatus,ier)
  end subroutine replace_float64_0

  subroutine replace_float64_1(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8           :: value(:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname,1,(/size(value,1)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float64_1
  
  subroutine replace_float64_2(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8           :: value(:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float64_2
  
  subroutine replace_float64_3(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8           :: value(:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ioption,istatus,ier)
  end subroutine replace_float64_3
  
  subroutine replace_float64_4(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8           :: value(:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
    inew,ioption,istatus,ier)
  end subroutine replace_float64_4
  
  subroutine replace_float64_5(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    real*8              :: value(:,:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacefloat64(self%point, cname, &
          5,(/size(value,1),size(value,2),size(value,3),size(value,4),size(value,5)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_float64_5
  
  subroutine pointer_Float64_0(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=0

    character*(*)       :: name      ! name of variable
    real*8,pointer   :: value     ! value to get
    integer             :: ier       ! nonzero on error
    real*8, optional :: def       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(1)      ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       ! shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = .true.                     ! size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value)       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_0

  subroutine pointer_Float64_1(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=1

    character*(*)       :: name      ! name of variable
    real*8,pointer   :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*8, optional :: def(:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ! shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1)                     ! .and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1)))       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_1

  subroutine pointer_Float64_2(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=2

    character*(*)       :: name      ! name of variable
    real*8,pointer   :: value(:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*8, optional :: def(:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_2

  subroutine pointer_Float64_3(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=3

    character*(*)       :: name      ! name of variable
    real*8,pointer   :: value(:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*8, optional :: def(:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_3

  subroutine pointer_Float64_4(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=4

    character*(*)       :: name      ! name of variable
    real*8,pointer   :: value(:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*8, optional :: def(:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3).and.size(value,4)==shape(4)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_4

  subroutine pointer_Float64_5(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=5

    character*(*)       :: name      ! name of variable
    real*8,pointer      :: value(:,:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    real*8,    optional :: def(:,:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4); shape(5)=size(def,5)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3) &
             .and.size(value,4)==shape(4).and.size(value,5)==shape(5)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4),shape(5)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_Float64_5

  subroutine add0Float64(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (size(shape)<rank) then
       print *, '?add0Float64: shape is not large enough for the rank'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0float64(self%point, cname, rank, shape, ier)
    end if
  end subroutine add0Float64

  subroutine arrayFloat64(self, name, fwrap, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer :: fwrap(FW_POINTER)       ! fwrap<type> instance
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_arrayfloat64(self%point, cname, fwrap, ier)
  end subroutine arrayFloat64

  !
  ! ---------- logical*4 ---------
  !
  function getScalarLogical32(self,name, ier, def) result(value)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)            :: name      ! name of variable
    integer                  :: ier       ! nonzero on error
    logical*4, optional      :: def       ! default
    logical*4                              :: value     ! result

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')

    if (present(def)) then
       call cvc_getdefscalarlogical32(self%point, cname,value,def,ier)
    else
       call cvc_getscalarlogical32(self%point, cname,value,ier)
    end if
  end function getScalarLogical32
    
  subroutine setScalarLogical32(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    logical*4          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setscalarlogical32(self%point, cname,value,ier)
  end subroutine setScalarLogical32

  subroutine addLogical32(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)   :: name      ! name of variable
    logical*4          :: value     ! value to set
    integer         :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    call cstring(name,cname,'2C')
    call cvc_addscalarlogical32(self%point, cname,value,ier)
  end subroutine addLogical32

  subroutine get_logical32_0(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value     ! value to get
    integer          :: ier       ! nonzero on error
    logical*4, optional :: def       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeflogical32(self%point, cname,0,0,value,0,0,def,ier)
    else
       call cvc_getlogical32(self%point, cname,0,0,value,ier)
    end if
  end subroutine get_logical32_0

  subroutine get_logical32_1(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    logical*4           :: value(:)     ! value to get
    integer          :: ier          ! nonzero on error
    logical*4, optional :: def(:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeflogical32(self%point, cname,1,(/size(value,1)/),value,1,(/size(def,1)/),def,ier)
    else
       call cvc_getlogical32(self%point, cname,1,(/size(value,1)/),value,ier)
    end if
  end subroutine get_logical32_1

  subroutine get_logical32_2(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    logical*4           :: value(:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    logical*4, optional :: def(:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeflogical32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            2,&
            (/size(def,1),size(def,2)/),&
            def,&
            ier)
    else
       call cvc_getlogical32(self%point, cname,&
            2,&
            (/size(value,1),size(value,2)/),&
            value,&
            ier)
    end if
  end subroutine get_logical32_2

  subroutine get_logical32_3(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    logical*4           :: value(:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    logical*4, optional :: def(:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeflogical32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            3,&
            (/size(def,1),size(def,2),size(def,3)/),&
            def,&
            ier)
    else
       call cvc_getlogical32(self%point, cname,&
            3,&
            (/size(value,1),size(value,2),size(value,3)/),&
            value,&
            ier)
    end if
  end subroutine get_logical32_3

  subroutine get_logical32_4(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name         ! name of variable
    logical*4           :: value(:,:,:,:)     ! value to get
    integer          :: ier          ! nonzero on error
    logical*4, optional :: def(:,:,:,:)       ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdeflogical32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            4,&
            (/size(def,1),size(def,2),size(def,3),size(def,4)/),&
            def,&
            ier)
    else
       call cvc_getlogical32(self%point, cname,&
            4,&
            (/size(value,1),size(value,2),size(value,3),size(value,4)/),&
            value,&
            ier)
    end if
  end subroutine get_logical32_4

  subroutine set_logical32_0(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setlogical32(self%point, cname,0,0,value,ier)
  end subroutine set_logical32_0

  subroutine set_logical32_1(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setlogical32(self%point, cname,1,(/size(value,1)/),value,ier)
  end subroutine set_logical32_1
  
  subroutine set_logical32_2(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setlogical32(self%point, cname,2,(/size(value,1),size(value,2)/),value,ier)
  end subroutine set_logical32_2
  
  subroutine set_logical32_3(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setlogical32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,ier)
  end subroutine set_logical32_3
  
  subroutine set_logical32_4(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:,:,:)     ! value to get
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setlogical32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,ier)
  end subroutine set_logical32_4
  
  subroutine add_logical32_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addlogical32(self%point, cname,0,0,value,inew,ier)
  end subroutine add_logical32_0

  subroutine add_logical32_1(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addlogical32(self%point, cname,1,(/size(value,1)/),value,inew,ier)
  end subroutine add_logical32_1
  
  subroutine add_logical32_2(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addlogical32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ier)
  end subroutine add_logical32_2
  
  subroutine add_logical32_3(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addlogical32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ier)
  end subroutine add_logical32_3
  
  subroutine add_logical32_4(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)    :: name      ! name of variable
    logical*4           :: value(:,:,:,:)     ! value to get
    integer          :: inew      ! nonzero for new storage
    integer          :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cvc_settruefalse(self%point, .TRUE.,.FALSE.,ier) ; if (ier/=0) return 
    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addlogical32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value,inew,ier)
  end subroutine add_logical32_4
  

  subroutine replace_logical32_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    logical*4           :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacelogical32(self%point, cname,0,0,value,inew,ioption,istatus,ier)
  end subroutine replace_logical32_0

  subroutine replace_logical32_1(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    logical*4           :: value(:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacelogical32(self%point, cname,1,(/size(value,1)/),value,inew,ioption,istatus,ier)
  end subroutine replace_logical32_1
  
  subroutine replace_logical32_2(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    logical*4           :: value(:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacelogical32(self%point, cname,2,(/size(value,1),size(value,2)/),value,inew,ioption,istatus,ier)
  end subroutine replace_logical32_2
  
  subroutine replace_logical32_3(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    logical*4           :: value(:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacelogical32(self%point, cname,3,(/size(value,1),size(value,2),size(value,3)/),value,inew,ioption,istatus,ier)
  end subroutine replace_logical32_3
  
  subroutine replace_logical32_4(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    logical*4           :: value(:,:,:,:)     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacelogical32(self%point, cname,4,(/size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
    inew,ioption,istatus,ier)
  end subroutine replace_logical32_4
  
  subroutine pointer_logical32_0(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=0

    character*(*)       :: name      ! name of variable
    logical*4,pointer   :: value     ! value to get
    integer             :: ier       ! nonzero on error
    logical*4, optional :: def       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(1)      ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       ! shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = .true.                     ! size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value)       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_logical32_0

  subroutine pointer_logical32_1(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=1

    character*(*)       :: name      ! name of variable
    logical*4,pointer   :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error
    logical*4, optional :: def(:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ! shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1)                     ! .and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1)))       ! value(shape(1),shape(2)
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_logical32_1

  subroutine pointer_logical32_2(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=2

    character*(*)       :: name      ! name of variable
    logical*4,pointer   :: value(:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    logical*4, optional :: def(:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_logical32_2

  subroutine pointer_logical32_3(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=3

    character*(*)       :: name      ! name of variable
    logical*4,pointer   :: value(:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    logical*4, optional :: def(:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_logical32_3

  subroutine pointer_logical32_4(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=4

    character*(*)       :: name      ! name of variable
    logical*4,pointer   :: value(:,:,:,:)     ! value to get
    integer             :: ier       ! nonzero on error
    logical*4, optional :: def(:,:,:,:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(irank)  ! shape
    logical :: iok           ! .true. when value is the right shape

    call getinfo(self,name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if                           
       shape(1)=size(def,1) ; shape(2)=size(def,2) ; shape(3)=size(def,3) ; shape(4)=size(def,4)
    end if
       
    if (iok) then
       iok = size(value,1)==shape(1).and.size(value,2)==shape(2).and.size(value,3)==shape(3).and.size(value,4)==shape(4)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(shape(1),shape(2),shape(3),shape(4)))    
    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_logical32_4

  subroutine add0Logical32(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (size(shape)<rank) then
       print *, '?add0Logical32: shape is not large enough for the rank'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0logical32(self%point, cname, rank, shape, ier)
    end if
  end subroutine add0Logical32

  subroutine arrayLogical32(self, name, fwrap, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer :: fwrap(FW_POINTER)       ! fwrap<type> instance
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_arraylogical32(self%point, cname, fwrap, ier)
  end subroutine arrayLogical32


  !
  ! ---------- Character---------
  !
  subroutine setScalarChar(self, name, value, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    integer :: vlen   ! value length  
      
    vlen = len(value)
    call cstring(name,cname,'2C')
    call cvc_setscalarstring(self%point, cname, vlen, value, ier)
  end subroutine setScalarChar

  subroutine addChar(self, name, value, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    integer :: vlen   ! value length  
      
    vlen = len(value)
    call cstring(name,cname,'2C')
    call cvc_addscalarstring(self%point, cname, vlen, value, ier)
  end subroutine addChar

  subroutine add0Char(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (size(shape)<rank) then
       print *, '?add0Char: shape is not large enough for the rank'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0char(self%point, cname, rank, shape, ier)
    end if
  end subroutine add0Char

  subroutine arrayChar(self, name, fwrap, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer :: fwrap(FW_POINTER)       ! fwrap<type> instance
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_arraychar(self%point, cname, fwrap, ier)
  end subroutine arrayChar
  
  subroutine get_char_0(self, name,value,ier,def)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to set
    integer             :: ier       ! nonzero on error
    character(len=*),optional :: def ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefchar(self%point, cname, &
          1,(/len(value)/),value, &
          1,(/len(def)/),  def, &
          ier)
    else
       call cvc_getchar(self%point, cname, &
          1,(/len(value)/),value, &
          ier)
    end if
  end subroutine get_char_0

  subroutine get_char_1(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    character(len=*)    :: value(:)     ! value to get
    integer             :: ier          ! nonzero on error
    character(len=*),optional :: def(:) ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefchar(self%point, cname, &
          2,(/len(value),size(value,1)/),value, &
          2,(/len(def),  size(def,1)/),  def, &
          ier)
    else
       call cvc_getchar(self%point, cname, &
          2,(/len(value),size(value,1)/),value, &
          ier)
    end if
  end subroutine get_char_1

  subroutine get_char_2(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    character(len=*)    :: value(:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    character(len=*),optional :: def(:,:) ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefchar(self%point, cname, &
          3,(/len(value),size(value,1),size(value,2)/),value, &
          3,(/len(def),  size(def,1),  size(def,2)/),  def, &
          ier)
    else
       call cvc_getchar(self%point, cname, &
          3,(/len(value),size(value,1),size(value,2)/),value, &
          ier)
    end if
  end subroutine get_char_2

  subroutine get_char_3(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    character(len=*)    :: value(:,:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    character(len=*),optional :: def(:,:,:) ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefchar(self%point, cname, &
          4,(/len(value),size(value,1),size(value,2),size(value,3)/),value, &
          4,(/len(def),  size(def,1),  size(def,2),  size(def,3)/),  def, &
          ier)
    else
       call cvc_getchar(self%point, cname, &
          4,(/len(value),size(value,1),size(value,2),size(value,3)/),value, &
          ier)
    end if
  end subroutine get_char_3

  subroutine get_char_4(self,name,value,ier,def)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name         ! name of variable
    character(len=*)    :: value(:,:,:,:)     ! value to get
    integer             :: ier          ! nonzero on error
    character(len=*),optional :: def(:,:,:,:) ! default if present

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefchar(self%point, cname, &
          5,(/len(value),size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
          5,(/len(def),  size(def,1),  size(def,2),  size(def,3),  size(def,4)/),  def, &
          ier)
    else
       call cvc_getchar(self%point, cname, &
          5,(/len(value),size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
          ier)
    end if
  end subroutine get_char_4
  
  subroutine set_char_0(self,name,value,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setchar(self%point, cname, &
          1,(/len(value)/),value, &
          ier)
  end subroutine set_char_0

  subroutine set_char_1(self,name,value,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:)  ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setchar(self%point, cname, &
          2,(/len(value),size(value,1)/),value, &
          ier)
  end subroutine set_char_1

  subroutine set_char_2(self,name,value,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:)  ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setchar(self%point, cname, &
          3,(/len(value),size(value,1),size(value,2)/),value, &
          ier)
  end subroutine set_char_2

  subroutine set_char_3(self,name,value,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:)  ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setchar(self%point, cname, &
          4,(/len(value),size(value,1),size(value,2),size(value,3)/),value, &
          ier)
  end subroutine set_char_3

  subroutine set_char_4(self,name,value,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:,:)  ! value to set
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setchar(self%point, cname, &
          5,(/len(value),size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
          ier)
  end subroutine set_char_4

  subroutine add_char_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to add
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addchar(self%point, cname, &
          1,(/len(value)/),value, &
          inew,ier)
  end subroutine add_char_0

  subroutine add_char_1(self,name,value,inew,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:)  ! value to add
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addchar(self%point, cname, &
          2,(/len(value),size(value,1)/),value, &
          inew,ier)
  end subroutine add_char_1

  subroutine add_char_2(self,name,value,inew,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:)  ! value to add
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addchar(self%point, cname, &
          3,(/len(value),size(value,1),size(value,2)/),value, &
          inew,ier)
  end subroutine add_char_2

  subroutine add_char_3(self,name,value,inew,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:)  ! value to add
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addchar(self%point, cname, &
          4,(/len(value),size(value,1),size(value,2),size(value,3)/),value, &
          inew,ier)
  end subroutine add_char_3

  subroutine add_char_4(self,name,value,inew,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:,:)  ! value to add
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::add(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_addchar(self%point, cname, &
          5,(/len(value),size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
          inew,ier)
  end subroutine add_char_4
  
  subroutine replace_char_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value     ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacechar(self%point, cname, &
          1,(/len(value)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_char_0

  subroutine replace_char_1(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacechar(self%point, cname, &
          2,(/len(value),size(value,1)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_char_1

  subroutine replace_char_2(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacechar(self%point, cname, &
          3,(/len(value),size(value,1),size(value,2)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_char_2

  subroutine replace_char_3(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacechar(self%point, cname, &
          4,(/len(value),size(value,1),size(value,2),size(value,3)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_char_3

  subroutine replace_char_4(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character(len=*)    :: value(:,:,:,:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0 .and. cvc_isheld()==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " the function cvc_hold(variable) must be called immediately before,"
       print *, " the varcontainer_mod::replace(name,variable,inew,ier) function" 
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacechar(self%point, cname, &
          5,(/len(value),size(value,1),size(value,2),size(value,3),size(value,4)/),value, &
          inew,ioption,istatus,ier)
  end subroutine replace_char_4
  
  !
  ! ---------- Bytes---------
  !
  subroutine setScalarBytes(self, name, value, ier)
    type(cVarContainer) :: self     ! cVarContainer instance
    character*(*)      :: name      ! name of variable
    byte_declare       :: value(:)  ! value to set
    integer            :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_setscalarbytes(self%point, cname, size(value), value, ier)
  end subroutine setScalarBytes

  subroutine addBytes(self, name, value, ier)
    type(cVarContainer) :: self     ! cVarContainer instance
    character*(*)      :: name      ! name of variable
    byte_declare       :: value(:)  ! value to set
    integer            :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_addscalarbytes(self%point, cname, size(value), value, ier)
  end subroutine addBytes
  
  subroutine get_bytes_0(self, name,value,ier,def,igot)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    byte_declare        :: value(:)  ! value to get
    integer             :: ier       ! nonzero on error
    byte_declare, optional :: def(:) ! default if present
    integer,      optional :: igot   ! return the number of values fetched

    byte_declare :: cname(len(name)+1)   ! name for C
    integer      :: pgot                 ! will be igot
    
    pgot=0
    call cstring(name,cname,'2C')
    if (present(def)) then
       call cvc_getdefscalarbytes(self%point, cname,size(value),value,size(def),def,pgot,ier)
    else
       call cvc_getscalarbytes(self%point, cname,size(value),value,pgot,ier)
    end if
    if (present(igot)) igot=pgot
  end subroutine get_bytes_0

  subroutine add_bytes_0(self,name,value,inew,ier)
    type(cVarContainer) :: self   ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    byte_declare        :: value(:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0) then
       print *, '?varcontainer_mod::add(): failed to add the variable '//trim(name)//', '
       print *, " Bytes can only be copied into the container, the pointer can not be added"
       ier=1
       return
    end if
    call addBytes(self, name, value, ier)
  end subroutine add_bytes_0

  subroutine replace_bytes_0(self,name,value,inew,ioption,istatus,ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    byte_declare        :: value(:)  ! value to get
    integer             :: inew      ! nonzero for new storage
    integer             :: ioption   ! option
    integer             :: istatus   ! returned status
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (inew==0) then
       print *, '?varcontainer_mod::replace(): failed to add the variable '//trim(name)//', '
       print *, " Bytes can only be copied into the container, the pointer can not be added"
       ier=1
       return
    end if
    call cstring(name,cname,'2C')
    call cvc_replacescalarbytes(self%point, cname,size(value),value,ioption,istatus,ier)
  end subroutine replace_bytes_0


  subroutine pointer_bytes_0(self,name,value,ier,def,defNull)
    type(cVarContainer) :: self   ! cVarContainer instance
    integer, parameter  :: irank=0

    character*(*)       :: name      ! name of variable
    byte_declare,pointer   :: value(:)     ! value to get
    integer             :: ier       ! nonzero on error
    byte_declare, optional :: def(:)       ! default if present
    logical,   optional :: defNull   ! overrides def to set pointer to null if not found

    logical :: got_key       ! .true. when the key is in the container
    integer :: type          ! type 
    integer :: rank          ! rank
    integer :: shape(1)      ! shape
    logical :: iok           ! .true. when value is the right shape
    integer :: isize         ! size of returned value
    
    call getinfo(self, name, got_key, type, rank, shape, ier)
    if (ier/=0) return

    iok = associated(value)      ! iok=.true. when have an associated array

    if (got_key) then
       if (rank/=irank) then
          print *, '?pointer: expected a rank of ',irank,', got rank ',rank,'for variable ',name
          ier=1 ; return 
       end if
       isize = sizeBytes(self,name,ier) ; if (ier/=0) return   ! this will check if variable is a Bytes
    else
       if (present(defNull)) then
          if (defNull) then
             if (iok) deallocate(value)   ! key not found so nullify and return
             nullify(value)
             return
          end if
       end if
       if (.not. present(def)) then
          print *, '?pointer: no default given for undefined variable ',name
          ier=1 ; return
       end if    
       isize = size(def)                       
       ! shape(1)=size(def,1) ; shape(2)=size(def,2)
    end if
       
    if (iok) then
       iok = size(value)==isize                 ! size(value,1)==shape(1).and.size(value,2)==shape(2)
       if (.not. iok) deallocate(value)
    end if
    if (.not. iok) allocate(value(isize))       ! value(shape(1),shape(2)

    if (got_key) then
       call get(self,name,value,ier)
    else
       value=def
    end if
  end subroutine pointer_bytes_0

  subroutine add0Bytes(self, name, rank, shape, ier)
    type(cVarContainer) :: self       ! cVarContainer instance
    character*(*)         :: name      ! name of variable
    integer               :: rank      ! rank
    integer               :: shape(:)  ! shape for new variable
    integer               :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    if (rank/=0) then
       print *, '?add0Bytes: only a rank=0 (scalar) Bytes can be added'
       ier=1
    else
       call cstring(name,cname,'2C')
       call cvc_add0bytes(self%point, cname, ier)
    end if
  end subroutine add0Bytes

  integer function sizeBytes(self, name, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cvc_sizescalarbytes(self%point, cname, sizeBytes, ier)
  end function sizeBytes

  subroutine getBytesFile(self, name, file, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character*(*)       :: file      ! name of file
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: fname(len(file)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cstring(file,fname,'2C')
    call cvc_getscalarbytestofile(self%point, cname, fname, ier)
  end subroutine getBytesFile

  subroutine setBytesFile(self, name, file, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character*(*)       :: file      ! name of file
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: fname(len(file)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cstring(file,fname,'2C')
    call cvc_setscalarbytesfromfile(self%point, cname, fname, ier)
  end subroutine setBytesFile

  subroutine addBytesFile(self, name, file, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character*(*)       :: file      ! name of file
    integer             :: ier       ! nonzero on error

    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: fname(len(file)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cstring(file,fname,'2C')
    call cvc_addscalarbytesfromfile(self%point, cname, fname, ier)
  end subroutine addBytesFile

  subroutine replaceBytesFile(self, name, file, ier)
    type(cVarContainer) :: self      ! cVarContainer instance
    character*(*)       :: name      ! name of variable
    character*(*)       :: file      ! name of file
    integer             :: ier       ! nonzero on error

    integer :: ioption, istatus
    
    byte_declare :: cname(len(name)+1)   ! name for C
    byte_declare :: fname(len(file)+1)   ! name for C

    call cstring(name,cname,'2C')
    call cstring(file,fname,'2C')
    ioption=0 ; istatus=0          ! you can use any option as long as it is zero
    call cvc_replacescalarbytesfromfile(self%point, cname, fname, ioption, istatus, ier)
  end subroutine replaceBytesFile

end module varcontainer_mod


