awips2/pythonPackages/h5py/h5py/_proxy.pyx
root e2ecdcfe33 Initial revision of AWIPS2 11.9.0-7p5
Former-commit-id: a02aeb236c [formerly 9f19e3f712] [formerly a02aeb236c [formerly 9f19e3f712] [formerly 06a8b51d6d [formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]]]
Former-commit-id: 06a8b51d6d
Former-commit-id: 8e80217e59 [formerly 3360eb6c5f]
Former-commit-id: 377dcd10b9
2012-01-06 08:55:05 -06:00

291 lines
8.3 KiB
Cython
Executable file

# cython: profile=False
#+
#
# This file is part of h5py, a low-level Python interface to the HDF5 library.
#
# Copyright (C) 2008 Andrew Collette
# http://h5py.alfven.org
# License: BSD (See LICENSE.txt for full license)
#
# $Date$
#
#-
"""
Proxy functions for read/write, to work around the HDF5 bogus type issue.
"""
cdef enum copy_dir:
H5PY_SCATTER = 0,
H5PY_GATHER
cdef herr_t attr_rw(hid_t attr, hid_t mtype, void *progbuf, int read) except -1:
cdef htri_t need_bkg
cdef hid_t atype = -1
cdef hid_t aspace = -1
cdef hsize_t npoints
cdef size_t msize, asize
cdef void* conv_buf = NULL
cdef void* back_buf = NULL
try:
atype = H5Aget_type(attr)
if not (needs_proxy(atype) or needs_proxy(mtype)):
if read:
H5Aread(attr, mtype, progbuf)
else:
H5Awrite(attr, mtype, progbuf)
else:
asize = H5Tget_size(atype)
msize = H5Tget_size(mtype)
aspace = H5Aget_space(attr)
npoints = H5Sget_select_npoints(aspace)
conv_buf = create_buffer(asize, msize, npoints)
if read:
need_bkg = needs_bkg_buffer(atype, mtype)
else:
need_bkg = needs_bkg_buffer(mtype, atype)
if need_bkg:
back_buf = malloc(msize*npoints)
memcpy(back_buf, progbuf, msize*npoints)
if read:
H5Aread(attr, atype, conv_buf)
H5Tconvert(atype, mtype, npoints, conv_buf, back_buf, H5P_DEFAULT)
memcpy(progbuf, conv_buf, msize*npoints)
else:
memcpy(conv_buf, progbuf, msize*npoints)
H5Tconvert(mtype, atype, npoints, conv_buf, back_buf, H5P_DEFAULT)
H5Awrite(attr, atype, conv_buf)
finally:
free(conv_buf)
free(back_buf)
if atype > 0:
H5Tclose(atype)
if aspace > 0:
H5Sclose(aspace)
return 0
# =============================================================================
# Proxy functions to safely release the GIL around read/write operations
cdef herr_t H5PY_H5Dread(hid_t dset, hid_t mtype, hid_t mspace,
hid_t fspace, hid_t dxpl, void* buf) except -1:
cdef herr_t retval
with nogil:
retval = H5Dread(dset, mtype, mspace, fspace, dxpl, buf)
if retval < 0:
return -1
return retval
cdef herr_t H5PY_H5Dwrite(hid_t dset, hid_t mtype, hid_t mspace,
hid_t fspace, hid_t dxpl, void* buf) except -1:
cdef herr_t retval
with nogil:
retval = H5Dwrite(dset, mtype, mspace, fspace, dxpl, buf)
if retval < 0:
return -1
return retval
# =============================================================================
# Proxy for vlen buf workaround
cdef herr_t dset_rw(hid_t dset, hid_t mtype, hid_t mspace, hid_t fspace,
hid_t dxpl, void* progbuf, int read) except -1:
cdef htri_t need_bkg
cdef hid_t dstype = -1 # Dataset datatype
cdef hid_t dspace = -1 # Dataset dataspace
cdef hid_t cspace = -1 # Temporary contiguous dataspaces
cdef void* back_buf = NULL
cdef void* conv_buf = NULL
cdef hsize_t npoints
try:
dstype = H5Dget_type(dset)
if not (needs_proxy(dstype) or needs_proxy(mtype)):
if read:
H5PY_H5Dread(dset, mtype, mspace, fspace, dxpl, progbuf)
else:
H5PY_H5Dwrite(dset, mtype, mspace, fspace, dxpl, progbuf)
else:
if mspace == H5S_ALL and fspace != H5S_ALL:
mspace = fspace
elif mspace != H5S_ALL and fspace == H5S_ALL:
fspace = mspace
elif mspace == H5S_ALL and fspace == H5S_ALL:
fspace = mspace = dspace = H5Dget_space(dset)
npoints = H5Sget_select_npoints(mspace)
cspace = H5Screate_simple(1, &npoints, NULL)
conv_buf = create_buffer(H5Tget_size(dstype), H5Tget_size(mtype), npoints)
# Only create a (contiguous) backing buffer if absolutely
# necessary. Note this buffer always has memory type.
if read:
need_bkg = needs_bkg_buffer(dstype, mtype)
else:
need_bkg = needs_bkg_buffer(mtype, dstype)
if need_bkg:
back_buf = malloc(H5Tget_size(mtype)*npoints)
h5py_copy(mtype, mspace, back_buf, progbuf, H5PY_GATHER)
if read:
H5PY_H5Dread(dset, dstype, cspace, fspace, dxpl, conv_buf)
H5Tconvert(dstype, mtype, npoints, conv_buf, back_buf, dxpl)
h5py_copy(mtype, mspace, conv_buf, progbuf, H5PY_SCATTER)
else:
h5py_copy(mtype, mspace, conv_buf, progbuf, H5PY_GATHER)
H5Tconvert(mtype, dstype, npoints, conv_buf, back_buf, dxpl)
H5PY_H5Dwrite(dset, dstype, cspace, fspace, dxpl, conv_buf)
finally:
free(back_buf)
free(conv_buf)
if dstype > 0:
H5Tclose(dstype)
if dspace > 0:
H5Sclose(dspace)
if cspace > 0:
H5Sclose(cspace)
return 0
cdef void* create_buffer(size_t ipt_size, size_t opt_size, size_t nl) except NULL:
cdef size_t final_size
cdef void* buf
if ipt_size >= opt_size:
final_size = ipt_size*nl
else:
final_size = opt_size*nl
buf = malloc(final_size)
if buf == NULL:
raise MemoryError("Failed to allocate conversion buffer")
return buf
# =============================================================================
# Scatter/gather routines
ctypedef struct h5py_scatter_t:
size_t i
size_t elsize
void* buf
cdef herr_t h5py_scatter_cb(void* elem, hid_t type_id, unsigned ndim,
hsize_t *point, void *operator_data) except -1:
cdef h5py_scatter_t* info = <h5py_scatter_t*>operator_data
memcpy(elem, (<char*>info[0].buf)+((info[0].i)*(info[0].elsize)),
info[0].elsize)
info[0].i += 1
return 0
cdef herr_t h5py_gather_cb(void* elem, hid_t type_id, unsigned ndim,
hsize_t *point, void *operator_data) except -1:
cdef h5py_scatter_t* info = <h5py_scatter_t*>operator_data
memcpy((<char*>info[0].buf)+((info[0].i)*(info[0].elsize)), elem,
info[0].elsize)
info[0].i += 1
return 0
# Copy between a contiguous and non-contiguous buffer, with the layout
# of the latter specified by a dataspace selection.
cdef herr_t h5py_copy(hid_t tid, hid_t space, void* contig, void* noncontig,
copy_dir op) except -1:
cdef h5py_scatter_t info
cdef hsize_t elsize
elsize = H5Tget_size(tid)
info.i = 0
info.elsize = elsize
info.buf = contig
if op == H5PY_SCATTER:
H5Diterate(noncontig, tid, space, h5py_scatter_cb, &info)
elif op == H5PY_GATHER:
H5Diterate(noncontig, tid, space, h5py_gather_cb, &info)
else:
raise RuntimeError("Illegal direction")
return 0
# =============================================================================
# VLEN support routines
cdef htri_t needs_bkg_buffer(hid_t src, hid_t dst) except -1:
cdef H5T_cdata_t *info = NULL
if H5Tdetect_class(src, H5T_COMPOUND) or H5Tdetect_class(dst, H5T_COMPOUND):
return 1
H5Tfind(src, dst, &info)
if info[0].need_bkg == H5T_BKG_YES:
return 1
return 0
# Determine if the given type requires proxy buffering
cdef htri_t needs_proxy(hid_t tid) except -1:
cdef H5T_class_t cls
cdef hid_t supertype
cdef int i, n
cdef htri_t result
cls = H5Tget_class(tid)
if cls == H5T_VLEN or cls == H5T_REFERENCE:
return 1
elif cls == H5T_STRING:
return H5Tis_variable_str(tid)
elif cls == H5T_ARRAY:
supertype = H5Tget_super(tid)
try:
return needs_proxy(supertype)
finally:
H5Tclose(supertype)
elif cls == H5T_COMPOUND:
n = H5Tget_nmembers(tid)
for i from 0<=i<n:
supertype = H5Tget_member_type(tid, i)
try:
result = needs_proxy(supertype)
if result > 0:
return 1
finally:
H5Tclose(supertype)
return 0
return 0