Move Java wrappers to FFM using jextract and java 25 (#5957)

FFM build requires Java 25, Jextract 25.
Generates FFM bindings during configure.
JNI is default when the requirements are not met or can be forced.
Presets added for maven and FFM - JNI is default selection.
Enhanced Maven options will work with either JNI or FFM
New Workflows for testing and maven uploads.
Extensive documentation changes for java.
This commit is contained in:
Allen Byrne
2025-11-04 14:03:06 -06:00
committed by GitHub
parent 18297c1923
commit b754dcb8f2
621 changed files with 104632 additions and 4346 deletions
+144 -18
View File
@@ -1,20 +1,11 @@
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA C Java)
set (CMAKE_MODULE_PATH "${HDF_CONFIG_DIR} ${HDF_RESOURCES_DIR}")
find_package (Java)
#-----------------------------------------------------------------------------
# Include some macros for reusable code
#-----------------------------------------------------------------------------
include (UseJava)
message (VERBOSE "JAVA: JAVA_HOME=$ENV{JAVA_HOME} JAVA_ROOT=$ENV{JAVA_ROOT}")
find_package (JNI)
message (VERBOSE "JNI_LIBRARIES=${JNI_LIBRARIES}")
message (VERBOSE "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
if (WIN32)
set (HDF_JRE_DIRECTORY "C:/Program Files/Java/jre")
else ()
@@ -25,8 +16,6 @@ endif ()
# Include the main src and config directories
#-----------------------------------------------------------------------------
set (HDF5_JAVA_INCLUDE_DIRECTORIES
${JNI_INCLUDE_DIRS}
${HDF5_JAVA_JNI_SRC_DIR}
${JAVA_INCLUDE_PATH}
${JAVA_INCLUDE_PATH2}
)
@@ -34,16 +23,153 @@ set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${HDF5_JAVA_INCLUDE_DIR
set (CMAKE_JAVA_INCLUDE_PATH "")
if (Java_VERSION_STRING VERSION_GREATER_EQUAL "25.0.0")
if (HDF5_ENABLE_JNI)
set (HDF5_JAVA_USE_FFM FALSE)
message (STATUS "Building HDF5 Java with JNI implementation (explicitly requested via HDF5_ENABLE_JNI)")
else ()
set (HDF5_JAVA_USE_FFM TRUE)
set (HDF5_ENABLE_JAVA_COMPAT TRUE)
message (STATUS "Building HDF5 Java with FFM implementation (Java ${Java_VERSION_STRING})")
# Find the jextract tool using the JEXTRACT_HOME or JAVA_HOME environment variable
# On Windows, jextract uses .bat extension
if (WIN32)
find_program (JEXTRACT_EXECUTABLE
NAMES jextract.bat jextract
PATHS "$ENV{JEXTRACT_HOME}/bin" "$ENV{JAVA_HOME}/bin"
REQUIRED
NO_DEFAULT_PATH
)
else ()
find_program (JEXTRACT_EXECUTABLE
NAMES jextract
PATHS "$ENV{JEXTRACT_HOME}/bin" "$ENV{JAVA_HOME}/bin"
REQUIRED
NO_DEFAULT_PATH
)
endif ()
if (NOT JEXTRACT_EXECUTABLE)
message (FATAL_ERROR "Could not find jextract executable. "
"Please set JEXTRACT_HOME or ensure jextract is in JAVA_HOME/bin\n"
"JEXTRACT_HOME=$ENV{JEXTRACT_HOME}\n"
"JAVA_HOME=$ENV{JAVA_HOME}")
endif ()
# jextract will output to the jsrc binary directory
# When jsrc/CMakeLists.txt runs, HDF5_JAVA_JSRC_BINARY_DIR will be set to this location by CMake
set (JEXTRACT_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/jsrc)
# Display jextract configuration
message (STATUS "jextract executable: ${JEXTRACT_EXECUTABLE}")
message (STATUS "jextract output directory: ${JEXTRACT_OUTPUT_DIR}")
message (STATUS "HDF5 source directory: ${HDF5_SRC_DIR}")
# Test if jextract executable exists and is runnable
if (NOT EXISTS "${JEXTRACT_EXECUTABLE}")
message (FATAL_ERROR "jextract executable does not exist at: ${JEXTRACT_EXECUTABLE}")
endif ()
# Try to run jextract --version as a test
message (STATUS "Testing jextract executable...")
execute_process (
COMMAND ${JEXTRACT_EXECUTABLE} --version
RESULT_VARIABLE JEXTRACT_VERSION_RESULT
OUTPUT_VARIABLE JEXTRACT_VERSION_OUTPUT
ERROR_VARIABLE JEXTRACT_VERSION_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
message (STATUS "jextract version test result: ${JEXTRACT_VERSION_RESULT}")
message (STATUS "jextract version output: ${JEXTRACT_VERSION_OUTPUT}")
if (NOT "${JEXTRACT_VERSION_ERROR}" STREQUAL "")
message (STATUS "jextract version error: ${JEXTRACT_VERSION_ERROR}")
endif ()
# Generate Java bindings with error handling
message (STATUS "Running jextract to generate FFM bindings...")
execute_process (
COMMAND
${JEXTRACT_EXECUTABLE}
--include-dir ${HDF5_SRC_DIR}
--include-dir ${HDF5_SRC_BINARY_DIR}
--include-dir ${H5FD_SUBFILING_DIR}
--output ${JEXTRACT_OUTPUT_DIR}
--target-package org.hdfgroup.javahdf5
--library hdf5
${HDF5_SRC_DIR}/hdf5.h
RESULT_VARIABLE JEXTRACT_RESULT
OUTPUT_VARIABLE JEXTRACT_OUTPUT
ERROR_VARIABLE JEXTRACT_ERROR
ECHO_OUTPUT_VARIABLE
ECHO_ERROR_VARIABLE
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# Check if jextract succeeded
message (STATUS "jextract exit code: ${JEXTRACT_RESULT}")
if (NOT JEXTRACT_RESULT EQUAL 0)
message (STATUS "jextract output length: ${JEXTRACT_OUTPUT}")
message (STATUS "jextract error length: ${JEXTRACT_ERROR}")
message (FATAL_ERROR "jextract failed with exit code ${JEXTRACT_RESULT}\n"
"Executable: ${JEXTRACT_EXECUTABLE}\n"
"Working dir: ${CMAKE_CURRENT_BINARY_DIR}\n"
"Output: ${JEXTRACT_OUTPUT}\n"
"Error: ${JEXTRACT_ERROR}")
endif ()
# Verify that key FFM binding files were generated
set (EXPECTED_FFM_FILE "${JEXTRACT_OUTPUT_DIR}/org/hdfgroup/javahdf5/hdf5_h.java")
if (NOT EXISTS "${EXPECTED_FFM_FILE}")
message (FATAL_ERROR "jextract did not generate expected file: ${EXPECTED_FFM_FILE}")
endif ()
message (STATUS "FFM bindings generated successfully at ${JEXTRACT_OUTPUT_DIR}")
endif ()
else ()
set (HDF5_JAVA_USE_FFM FALSE)
set (HDF5_ENABLE_JNI TRUE)
message (STATUS "Building HDF5 Java with JNI implementation (Java ${Java_VERSION_STRING})")
if (Java_VERSION_STRING VERSION_LESS "11.0.0")
message (FATAL_ERROR "Java version ${Java_VERSION_STRING} is not supported. Minimum required: Java 11")
endif ()
endif ()
# Update global cache variables based on detected implementation
if (HDF5_JAVA_USE_FFM)
set (HDF5_JAVA_IMPLEMENTATION "FFM" CACHE STRING "Java implementation being built" FORCE)
set (HDF5_JAVA_ARTIFACT_ID "hdf5-java-ffm" CACHE STRING "Maven artifact ID for Java bindings" FORCE)
set (DOXYGEN_JAVA_DIR ${HDF5_JAVA_SRC_PATH})
else ()
set (HDF5_JAVA_IMPLEMENTATION "JNI" CACHE STRING "Java implementation being built" FORCE)
set (HDF5_JAVA_ARTIFACT_ID "hdf5-java-jni" CACHE STRING "Maven artifact ID for Java bindings" FORCE)
set (DOXYGEN_JAVA_DIR ${HDF5_JAVA_SRCJNI_PATH})
endif ()
set_property(CACHE HDF5_JAVA_IMPLEMENTATION PROPERTY STRINGS FFM JNI)
mark_as_advanced (HDF5_JAVA_IMPLEMENTATION HDF5_JAVA_ARTIFACT_ID)
# Display final configuration
message (STATUS "Java implementation: ${HDF5_JAVA_IMPLEMENTATION}")
message (STATUS "Java Maven artifact: org.hdfgroup:${HDF5_JAVA_ARTIFACT_ID}")
#-----------------------------------------------------------------------------
# Traverse source subdirectory
#-----------------------------------------------------------------------------
add_subdirectory (src)
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if (NOT HDF5_EXTERNALLY_CONFIGURED AND BUILD_TESTING)
add_subdirectory (test)
# Build appropriate subdirectories based on implementation
if (HDF5_JAVA_USE_FFM)
add_subdirectory (jsrc)
if (HDF5_ENABLE_JAVA_COMPAT)
add_subdirectory (hdf)
endif ()
if (NOT HDF5_EXTERNALLY_CONFIGURED AND BUILD_TESTING)
add_subdirectory (jtest)
if (HDF5_ENABLE_JAVA_COMPAT)
add_subdirectory (test)
endif ()
endif ()
else ()
add_subdirectory (src-jni)
endif ()
#-----------------------------------------------------------------------------
+253
View File
@@ -0,0 +1,253 @@
#-----------------------------------------------------------------------------
# CMake configuration for HDF5 Java hdf.hdf5lib package
# This file sets up the build, packaging, and installation rules for the HDF5 Java hdf.hdf5lib package.
# It handles Java source grouping, JAR creation, JFFM dependencies, and formatting for the HDF5 Java bindings.
#-----------------------------------------------------------------------------
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA_HDF_HDF5 Java)
set (CMAKE_VERBOSE_MAKEFILE 1)
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${HDF5_JAVA_JSRC_SOURCE_DIR};${HDF5_JAVA_JSRC_BINARY_DIR};${HDF5_JAVA_HDF_HDF5_SOURCE_DIR};${HDF5_JAVA_HDF_HDF5_BINARY_DIR};${HDF5_JAVA_LIB_DIR};${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${HDF5_JAVA_HDF5_LIB_CORENAME}.dir/hdf/hdf5lib")
SET_GLOBAL_VARIABLE (HDF5_JAVA_SOURCE_PACKAGES
"${HDF5_JAVA_SOURCE_PACKAGES};hdf.hdf5lib.callbacks;hdf.hdf5lib.exceptions;hdf.hdf5lib.structs;hdf.hdf5lib"
)
set (HDF5_JAVA_HDF_HDF5_CALLBACKS_SOURCES
callbacks/H5A_iterate_cb.java
callbacks/H5A_iterate_t.java
callbacks/H5D_append_cb.java
callbacks/H5D_append_t.java
callbacks/H5D_iterate_cb.java
callbacks/H5D_iterate_t.java
callbacks/H5E_walk_cb.java
callbacks/H5E_walk_t.java
callbacks/H5L_iterate_t.java
callbacks/H5L_iterate_opdata_t.java
callbacks/H5O_iterate_t.java
callbacks/H5O_iterate_opdata_t.java
# callbacks/H5P_cls_close_func_cb.java
# callbacks/H5P_cls_close_func_t.java
# callbacks/H5P_cls_copy_func_cb.java
# callbacks/H5P_cls_copy_func_t.java
# callbacks/H5P_cls_create_func_cb.java
# callbacks/H5P_cls_create_func_t.java
# callbacks/H5P_prp_close_func_cb.java
# callbacks/H5P_prp_compare_func_cb.java
# callbacks/H5P_prp_copy_func_cb.java
# callbacks/H5P_prp_create_func_cb.java
# callbacks/H5P_prp_delete_func_cb.java
# callbacks/H5P_prp_get_func_cb.java
# callbacks/H5P_prp_set_func_cb.java
callbacks/H5P_iterate_cb.java
callbacks/H5P_iterate_t.java
)
set (HDF5_JAVADOC_HDFH5I_INVALID_HID_HDF5_CALLBACKS_SOURCES
${HDF5_JAVA_HDF_HDF5_CALLBACKS_SOURCES}
callbacks/package-info.java
)
set (HDF5_JAVA_HDF_HDF5_EXCEPTIONS_SOURCES
exceptions/HDF5Exception.java
exceptions/HDF5IdException.java
exceptions/HDF5AttributeException.java
exceptions/HDF5BtreeException.java
exceptions/HDF5DataFiltersException.java
exceptions/HDF5DatasetInterfaceException.java
exceptions/HDF5DataspaceInterfaceException.java
exceptions/HDF5DataStorageException.java
exceptions/HDF5DatatypeInterfaceException.java
exceptions/HDF5ExternalFileListException.java
exceptions/HDF5FileInterfaceException.java
exceptions/HDF5FunctionArgumentException.java
exceptions/HDF5FunctionEntryExitException.java
exceptions/HDF5HeapException.java
exceptions/HDF5InternalErrorException.java
exceptions/HDF5JavaException.java
exceptions/HDF5LibraryException.java
exceptions/HDF5LowLevelIOException.java
exceptions/HDF5MetaDataCacheException.java
exceptions/HDF5ObjectHeaderException.java
exceptions/HDF5PropertyListInterfaceException.java
exceptions/HDF5ReferenceException.java
exceptions/HDF5ResourceUnavailableException.java
exceptions/HDF5SymbolTableException.java
)
set (HDF5_JAVADOC_HDF_HDF5_EXCEPTIONS_SOURCES
${HDF5_JAVA_HDF_HDF5_EXCEPTIONS_SOURCES}
exceptions/package-info.java
)
set (HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES
structs/H5_ih_info_t.java
structs/H5A_info_t.java
structs/H5AC_cache_config_t.java
structs/H5E_error2_t.java
structs/H5F_info2_t.java
structs/H5G_info_t.java
structs/H5L_info_t.java
structs/H5O_hdr_info_t.java
structs/H5O_info_t.java
structs/H5O_native_info_t.java
structs/H5O_token_t.java
)
list(APPEND HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES structs/H5FD_ros3_fapl_t.java)
# list(APPEND HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES structs/H5FD_hdfs_fapl_t.java)
set (HDF5_JAVADOC_HDF_HDF5_STRUCTS_SOURCES
${HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES}
structs/package-info.java
)
set (HDF5_JAVA_HDF_HDF5_SOURCES
HDFArray.java
HDF5Constants.java
HDFNativeData.java
H5.java
VLDataConverter.java
)
set (HDF5_JAVADOC_HDF_HDF5_SOURCES
${HDF5_JAVA_HDF_HDF5_SOURCES}
package-info.java
)
file (WRITE ${PROJECT_BINARY_DIR}/Manifest.txt
"Enable-Native-Access: ALL-UNNAMED
"
)
set (CMAKE_JAVA_INCLUDE_PATH "${HDF5_JAVAHDF5_JARS};${HDF5_JAVA_LOGGING_JAR}")
# Create main JAR with platform classifier if Maven deployment is enabled
if (HDF5_ENABLE_MAVEN_DEPLOY)
# Determine platform and architecture for Maven classifiers
if (WIN32)
set (HDF5_MAVEN_PLATFORM "windows")
elseif (APPLE)
set (HDF5_MAVEN_PLATFORM "macos")
else ()
set (HDF5_MAVEN_PLATFORM "linux")
endif ()
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
set (HDF5_MAVEN_ARCHITECTURE "aarch64")
else ()
set (HDF5_MAVEN_ARCHITECTURE "x86_64")
endif ()
else ()
set (HDF5_MAVEN_ARCHITECTURE "x86")
endif ()
# Set version suffix for snapshots vs releases
if (HDF5_MAVEN_SNAPSHOT)
set (HDF5_MAVEN_VERSION_SUFFIX "-SNAPSHOT")
else ()
set (HDF5_MAVEN_VERSION_SUFFIX "")
endif ()
# Build JAR once with platform classifier - this is the primary JAR
set (HDF5_JAR_CLASSIFIER "${HDF5_MAVEN_PLATFORM}-${HDF5_MAVEN_ARCHITECTURE}")
add_jar (${HDF5_JAVA_HDF5_LIB_TARGET}
OUTPUT_NAME "${HDF5_JAVA_HDF5_LIB_TARGET}-${HDF5_PACKAGE_VERSION}${HDF5_MAVEN_VERSION_SUFFIX}-${HDF5_JAR_CLASSIFIER}"
MANIFEST ${PROJECT_BINARY_DIR}/Manifest.txt
${HDF5_JAVA_HDF_HDF5_CALLBACKS_SOURCES}
${HDF5_JAVA_HDF_HDF5_EXCEPTIONS_SOURCES}
${HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES}
${HDF5_JAVA_HDF_HDF5_SOURCES}
)
# Get the JAR file path for the platform-specific JAR
get_target_property (HDF5_JAVA_PLATFORM_JAR_FILE ${HDF5_JAVA_HDF5_LIB_TARGET} JAR_FILE)
# Define the universal JAR name and path (without classifier)
set (HDF5_JAVA_UNIVERSAL_JAR_NAME "${HDF5_JAVA_HDF5_LIB_TARGET}-${HDF5_PACKAGE_VERSION}${HDF5_MAVEN_VERSION_SUFFIX}.jar")
set (HDF5_JAVA_UNIVERSAL_JAR_FILE "${CMAKE_CURRENT_BINARY_DIR}/${HDF5_JAVA_UNIVERSAL_JAR_NAME}")
# Create universal JAR by copying the platform-specific JAR
set (HDF5_JAVA_UNIVERSAL_TARGET "${HDF5_JAVA_HDF5_LIB_TARGET}-universal")
add_custom_command (
OUTPUT ${HDF5_JAVA_UNIVERSAL_JAR_FILE}
COMMAND ${CMAKE_COMMAND} -E copy ${HDF5_JAVA_PLATFORM_JAR_FILE} ${HDF5_JAVA_UNIVERSAL_JAR_FILE}
DEPENDS ${HDF5_JAVA_HDF5_LIB_TARGET}
COMMENT "Creating universal JAR ${HDF5_JAVA_UNIVERSAL_JAR_NAME} from platform-specific JAR"
)
# Create a target for the universal JAR
add_custom_target (${HDF5_JAVA_UNIVERSAL_TARGET} ALL
DEPENDS ${HDF5_JAVA_UNIVERSAL_JAR_FILE}
)
set_target_properties (${HDF5_JAVA_UNIVERSAL_TARGET} PROPERTIES FOLDER libraries/java)
# Export universal target name for test dependencies
SET_GLOBAL_VARIABLE (HDF5_JAVA_HDF5_UNIVERSAL_TARGET ${HDF5_JAVA_UNIVERSAL_TARGET})
# Install both JARs
install_jar (${HDF5_JAVA_HDF5_LIB_TARGET} LIBRARY DESTINATION ${HDF5_INSTALL_JAR_DIR} COMPONENT maven)
install (FILES ${HDF5_JAVA_UNIVERSAL_JAR_FILE} DESTINATION ${HDF5_INSTALL_JAR_DIR} COMPONENT libraries)
# Update global variables for both JARs
# Use universal JAR for examples/tests (for compatibility)
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS "${HDF5_JAVA_JARS};${HDF5_JAVA_UNIVERSAL_JAR_FILE}")
# Export both JARs for installation
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS_TO_EXPORT "${HDF5_JAVA_JARS_TO_EXPORT};${HDF5_JAVA_UNIVERSAL_JAR_FILE}")
SET_GLOBAL_VARIABLE (HDF5_MAVEN_PLATFORM_JAR_FILE "${HDF5_JAVA_PLATFORM_JAR_FILE}")
else ()
# Standard JAR creation without Maven classifiers
add_jar (${HDF5_JAVA_HDF5_LIB_TARGET} OUTPUT_NAME "${HDF5_JAVA_HDF5_LIB_TARGET}-${HDF5_PACKAGE_VERSION}" MANIFEST ${PROJECT_BINARY_DIR}/Manifest.txt ${HDF5_JAVA_HDF_HDF5_CALLBACKS_SOURCES} ${HDF5_JAVA_HDF_HDF5_EXCEPTIONS_SOURCES} ${HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES} ${HDF5_JAVA_HDF_HDF5_SOURCES})
install_jar (${HDF5_JAVA_HDF5_LIB_TARGET} LIBRARY DESTINATION ${HDF5_INSTALL_JAR_DIR} COMPONENT libraries)
# For non-Maven builds, use the standard JAR
get_target_property (${HDF5_JAVA_HDF5_LIB_TARGET}_JAR_FILE ${HDF5_JAVA_HDF5_LIB_TARGET} JAR_FILE)
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS "${HDF5_JAVA_JARS};${${HDF5_JAVA_HDF5_LIB_TARGET}_JAR_FILE}")
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS_TO_EXPORT "${HDF5_JAVA_JARS_TO_EXPORT};${${HDF5_JAVA_HDF5_LIB_TARGET}_JAR_FILE}")
endif ()
message (STATUS "HDF5 java jar: ${HDF5_JAVA_JARS}")
# Always export the platform-specific JAR for reference (used by Maven deployment)
get_target_property (${HDF5_JAVA_HDF5_LIB_TARGET}_JAR_FILE ${HDF5_JAVA_HDF5_LIB_TARGET} JAR_FILE)
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS_TO_EXPORT "${HDF5_JAVA_JARS_TO_EXPORT};${${HDF5_JAVA_HDF5_LIB_TARGET}_JAR_FILE}")
message (STATUS "HDF5 java export jar: ${HDF5_JAVA_JARS}")
add_dependencies (${HDF5_JAVA_HDF5_LIB_TARGET} ${HDF5_JAVA_JSRC_LIB_TARGET})
set_target_properties (${HDF5_JAVA_HDF5_LIB_TARGET} PROPERTIES FOLDER libraries/java)
# Set HDF5_JAVA_LIBRARY for examples to depend on
SET_GLOBAL_VARIABLE (HDF5_JAVA_LIBRARY ${HDF5_JAVA_HDF5_LIB_TARGET})
#-----------------------------------------------------------------------------
# Maven POM Generation
#-----------------------------------------------------------------------------
if (HDF5_ENABLE_MAVEN_DEPLOY)
# Configure timestamp for build metadata
string (TIMESTAMP CMAKE_CONFIGURE_DATE "%Y-%m-%d %H:%M:%S UTC" UTC)
# Generate POM file from template
configure_file (
${CMAKE_CURRENT_SOURCE_DIR}/pom.xml.in
${CMAKE_CURRENT_BINARY_DIR}/pom.xml
@ONLY
)
# Install POM file for deployment
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/pom.xml
DESTINATION ${HDF5_INSTALL_JAR_DIR}
COMPONENT maven
)
# Add Maven deployment information to global variables
SET_GLOBAL_VARIABLE (HDF5_MAVEN_POM_FILE "${CMAKE_CURRENT_BINARY_DIR}/pom.xml")
SET_GLOBAL_VARIABLE (HDF5_MAVEN_PLATFORM_CLASSIFIER "${HDF5_MAVEN_PLATFORM}-${HDF5_MAVEN_ARCHITECTURE}")
message (STATUS "Maven POM configured: ${HDF5_MAVEN_PLATFORM}-${HDF5_MAVEN_ARCHITECTURE}")
endif ()
if (HDF5_ENABLE_FORMATTERS)
clang_format (HDF5_JAVA_SRC_FORMAT ${HDF5_JAVA_HDF_HDF5_CALLBACKS_SOURCES} ${HDF5_JAVA_HDF_HDF5_EXCEPTIONS_SOURCES} ${HDF5_JAVA_HDF_HDF5_STRUCTS_SOURCES} ${HDF5_JAVA_HDF_HDF5_SOURCES})
endif ()
set (CMAKE_JAVA_INCLUDE_PATH "")
File diff suppressed because it is too large Load Diff
+1736
View File
@@ -0,0 +1,1736 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import hdf.hdf5lib.H5;
import hdf.hdf5lib.structs.H5O_token_t;
import org.hdfgroup.javahdf5.*;
/**
* \page HDF5CONST Constants and Enumerated Types
* This class contains C constants and enumerated types of HDF5 library. The
* values of these constants are obtained from the library by calling
* the JNI function jconstant, where jconstant is used for any of the private constants
* which start their name with "H5" need to be converted.
* <P>
* <B>Do not edit this file!</b>
*
* @see @ref HDF5LIB
*/
public class HDF5Constants {
static { System.err.println("OpenIDs = " + H5.getOpenIDCount()); }
/** Special parameters for szip compression */
public static final int H5_SZIP_MAX_PIXELS_PER_BLOCK = H5_SZIP_MAX_PIXELS_PER_BLOCK();
/** Special parameters for szip compression */
public static final int H5_SZIP_NN_OPTION_MASK = H5_SZIP_NN_OPTION_MASK();
/** Special parameters for szip compression */
public static final int H5_SZIP_EC_OPTION_MASK = H5_SZIP_EC_OPTION_MASK();
/** Special parameters for szip compression */
public static final int H5_SZIP_ALLOW_K13_OPTION_MASK = H5_SZIP_ALLOW_K13_OPTION_MASK();
/** Special parameters for szip compression */
public static final int H5_SZIP_CHIP_OPTION_MASK = H5_SZIP_CHIP_OPTION_MASK();
/** indices on links, unknown index type */
public static final int H5_INDEX_UNKNOWN = H5_INDEX_UNKNOWN();
/** indices on links, index on names */
public static final int H5_INDEX_NAME = H5_INDEX_NAME();
/** indices on links, index on creation order */
public static final int H5_INDEX_CRT_ORDER = H5_INDEX_CRT_ORDER();
/** indices on links, number of indices defined */
public static final int H5_INDEX_N = H5_INDEX_N();
/** Common iteration orders, Unknown order */
public static final int H5_ITER_UNKNOWN = H5_ITER_UNKNOWN();
/** Common iteration orders, Increasing order */
public static final int H5_ITER_INC = H5_ITER_INC();
/** Common iteration orders, Decreasing order */
public static final int H5_ITER_DEC = H5_ITER_DEC();
/** Common iteration orders, No particular order, whatever is fastest */
public static final int H5_ITER_NATIVE = H5_ITER_NATIVE();
/** Common iteration orders, Number of iteration orders */
public static final int H5_ITER_N = H5_ITER_N();
/** The version of the H5AC_cache_config_t in use */
public static final int H5AC_CURR_CACHE_CONFIG_VERSION = H5AC__CURR_CACHE_CONFIG_VERSION();
/** The maximum length of the trace file path */
public static final int H5AC_MAX_TRACE_FILE_NAME_LEN = H5AC__MAX_TRACE_FILE_NAME_LEN();
/**
* When metadata_write_strategy is set to this value, only process
* zero is allowed to write dirty metadata to disk. All other
* processes must retain dirty metadata until they are informed at
* a sync point that the dirty metadata in question has been written
* to disk.
*/
public static final int H5AC_METADATA_WRITE_STRATEGY_PROCESS_0_ONLY =
H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY();
/**
* In the distributed metadata write strategy, process zero still makes
* the decisions as to what entries should be flushed, but the actual
* flushes are distributed across the processes in the computation to
* the extent possible.
*/
public static final int H5AC_METADATA_WRITE_STRATEGY_DISTRIBUTED =
H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED();
/** Don't attempt to increase the size of the cache automatically */
public static final int H5C_incr_off = H5C_incr__off();
/**
* Attempt to increase the size of the cache
* whenever the average hit rate over the last epoch drops
* below the value supplied in the lower_hr_threshold
* field
*/
public static final int H5C_incr_threshold = H5C_incr__threshold();
/** Don't perform flash increases in the size of the cache */
public static final int H5C_flash_incr_off = H5C_flash_incr__off();
/** increase the current maximum cache size by x * flash_multiple less any free space in the cache */
public static final int H5C_flash_incr_add_space = H5C_flash_incr__add_space();
/** Don't attempt to decrease the size of the cache automatically */
public static final int H5C_decr_off = H5C_decr__off();
/**
* Attempt to decrease the size of the cache
* whenever the average hit rate over the last epoch rises
* above the value supplied in the upper_hr_threshold
* field
*/
public static final int H5C_decr_threshold = H5C_decr__threshold();
/**
* At the end of each epoch, search the cache for
* entries that have not been accessed for at least the number
* of epochs specified in the epochs_before_eviction field, and
* evict these entries
*/
public static final int H5C_decr_age_out = H5C_decr__age_out();
/**
* Same as age_out, but we only
* attempt to reduce the cache size when the hit rate observed
* over the last epoch exceeds the value provided in the
* upper_hr_threshold field
*/
public static final int H5C_decr_age_out_with_threshold = H5C_decr__age_out_with_threshold();
/** */
public static final int H5D_CHUNK_IDX_BTREE = H5D_CHUNK_IDX_BTREE();
/** */
public static final int H5D_ALLOC_TIME_DEFAULT = H5D_ALLOC_TIME_DEFAULT();
/** */
public static final int H5D_ALLOC_TIME_EARLY = H5D_ALLOC_TIME_EARLY();
/** */
public static final int H5D_ALLOC_TIME_ERROR = H5D_ALLOC_TIME_ERROR();
/** */
public static final int H5D_ALLOC_TIME_INCR = H5D_ALLOC_TIME_INCR();
/** */
public static final int H5D_ALLOC_TIME_LATE = H5D_ALLOC_TIME_LATE();
/** */
public static final int H5D_FILL_TIME_ERROR = H5D_FILL_TIME_ERROR();
/** */
public static final int H5D_FILL_TIME_ALLOC = H5D_FILL_TIME_ALLOC();
/** */
public static final int H5D_FILL_TIME_NEVER = H5D_FILL_TIME_NEVER();
/** */
public static final int H5D_FILL_TIME_IFSET = H5D_FILL_TIME_IFSET();
/** */
public static final int H5D_FILL_VALUE_DEFAULT = H5D_FILL_VALUE_DEFAULT();
/** */
public static final int H5D_FILL_VALUE_ERROR = H5D_FILL_VALUE_ERROR();
/** */
public static final int H5D_FILL_VALUE_UNDEFINED = H5D_FILL_VALUE_UNDEFINED();
/** */
public static final int H5D_FILL_VALUE_USER_DEFINED = H5D_FILL_VALUE_USER_DEFINED();
/** */
public static final int H5D_LAYOUT_ERROR = H5D_LAYOUT_ERROR();
/** */
public static final int H5D_CHUNKED = H5D_CHUNKED();
/** */
public static final int H5D_COMPACT = H5D_COMPACT();
/** */
public static final int H5D_CONTIGUOUS = H5D_CONTIGUOUS();
/** */
public static final int H5D_VIRTUAL = H5D_VIRTUAL();
/** */
public static final int H5D_NLAYOUTS = H5D_NLAYOUTS();
/** */
public static final int H5D_SPACE_STATUS_ALLOCATED = H5D_SPACE_STATUS_ALLOCATED();
/** */
public static final int H5D_SPACE_STATUS_ERROR = H5D_SPACE_STATUS_ERROR();
/** */
public static final int H5D_SPACE_STATUS_NOT_ALLOCATED = H5D_SPACE_STATUS_NOT_ALLOCATED();
/** */
public static final int H5D_SPACE_STATUS_PART_ALLOCATED = H5D_SPACE_STATUS_PART_ALLOCATED();
/** */
public static final int H5D_VDS_ERROR = H5D_VDS_ERROR();
/** */
public static final int H5D_VDS_FIRST_MISSING = H5D_VDS_FIRST_MISSING();
/** */
public static final int H5D_VDS_LAST_AVAILABLE = H5D_VDS_LAST_AVAILABLE();
/** */
public static final int H5D_CHUNK_DONT_FILTER_PARTIAL_CHUNKS = H5D_CHUNK_DONT_FILTER_PARTIAL_CHUNKS();
/** Different kinds of error information - H5E_type_t */
public static final int H5E_MAJOR = H5E_MAJOR();
/** Different kinds of error information - H5E_type_t */
public static final int H5E_MINOR = H5E_MINOR();
/** Minor error codes - Object header related errors - Alignment error */
public static final long H5E_ALIGNMENT = H5E_ALIGNMENT_g();
/** Minor error codes - Resource errors - Object already exists */
public static final long H5E_ALREADYEXISTS = H5E_ALREADYEXISTS_g();
/** Minor error codes - Function entry/exit interface - Object already initialized */
public static final long H5E_ALREADYINIT = H5E_ALREADYINIT_g();
/** Major error codes - Invalid arguments to routine */
public static final long H5E_ARGS = H5E_ARGS_g();
/** Major error codes - Object ID */
public static final long H5E_ID = H5E_ID_g();
/** Major error codes - Attribute */
public static final long H5E_ATTR = H5E_ATTR_g();
/** Minor error codes - Object ID related errors - Unable to find ID information (already closed?) */
public static final long H5E_BADID = H5E_BADID_g();
/** Minor error codes - File accessibility errors - Bad file ID accessed */
public static final long H5E_BADFILE = H5E_BADFILE_g();
/** Minor error codes - Object ID related errors - Unable to find ID group information */
public static final long H5E_BADGROUP = H5E_BADGROUP_g();
/** Minor error codes - Object header related errors - Iteration failed */
public static final long H5E_BADITER = H5E_BADITER_g();
/** Minor error codes - Object header related errors - Unrecognized message */
public static final long H5E_BADMESG = H5E_BADMESG_g();
/** Minor error codes - Argument errors - Out of range */
public static final long H5E_BADRANGE = H5E_BADRANGE_g();
/** Minor error codes - Dataspace errors - Invalid selection */
public static final long H5E_BADSELECT = H5E_BADSELECT_g();
/** Datatype conversion errors - Bad size for object */
public static final long H5E_BADSIZE = H5E_BADSIZE_g();
/** Minor error codes - Argument errors - Inappropriate type */
public static final long H5E_BADTYPE = H5E_BADTYPE_g();
/** Minor error codes - Argument errors - Bad value */
public static final long H5E_BADVALUE = H5E_BADVALUE_g();
/** Major error codes - B-Tree node */
public static final long H5E_BTREE = H5E_BTREE_g();
/** Major error codes - Object cache */
public static final long H5E_CACHE = H5E_CACHE_g();
/** I/O pipeline errors - Callback failed */
public static final long H5E_CALLBACK = H5E_CALLBACK_g();
/** I/O pipeline errors - Error from filter 'can apply' callback */
public static final long H5E_CANAPPLY = H5E_CANAPPLY_g();
/** Minor error codes - Resource errors - Can't allocate space */
public static final long H5E_CANTALLOC = H5E_CANTALLOC_g();
/** Minor error codes - Dataspace errors - Can't append object */
public static final long H5E_CANTAPPEND = H5E_CANTAPPEND_g();
/** Minor error codes - Heap errors - Can't attach object */
public static final long H5E_CANTATTACH = H5E_CANTATTACH_g();
/** Minor error codes - Cache related errors - Unable to mark metadata as clean */
public static final long H5E_CANTCLEAN = H5E_CANTCLEAN_g();
/** Minor error codes - Dataspace errors - Can't clip hyperslab region */
public static final long H5E_CANTCLIP = H5E_CANTCLIP_g();
/** Minor error codes - File accessibility errors - Unable to close file */
public static final long H5E_CANTCLOSEFILE = H5E_CANTCLOSEFILE_g();
/** Minor error codes - Group related errors - Can't close object */
public static final long H5E_CANTCLOSEOBJ = H5E_CANTCLOSEOBJ_g();
/** Minor error codes - Dataspace errors - Can't compare objects */
public static final long H5E_CANTCOMPARE = H5E_CANTCOMPARE_g();
/** Minor error codes - Heap errors - Can't compute value */
public static final long H5E_CANTCOMPUTE = H5E_CANTCOMPUTE_g();
/** Datatype conversion errors - Can't convert datatypes */
public static final long H5E_CANTCONVERT = H5E_CANTCONVERT_g();
/** Minor error codes - Resource errors - Unable to copy object */
public static final long H5E_CANTCOPY = H5E_CANTCOPY_g();
/** Minor error codes - Cache related errors - Unable to cork an object */
public static final long H5E_CANTCORK = H5E_CANTCORK_g();
/** Minor error codes - Dataspace errors - Can't count elements */
public static final long H5E_CANTCOUNT = H5E_CANTCOUNT_g();
/** Minor error codes - File accessibility errors - Unable to create file */
public static final long H5E_CANTCREATE = H5E_CANTCREATE_g();
/** Minor error codes - Object ID related errors - Unable to decrement reference count */
public static final long H5E_CANTDEC = H5E_CANTDEC_g();
/** Minor error codes - B-tree related errors - Unable to decode value */
public static final long H5E_CANTDECODE = H5E_CANTDECODE_g();
/** Minor error codes - Object header related errors - Can't delete message */
public static final long H5E_CANTDELETE = H5E_CANTDELETE_g();
/** Minor error codes - File accessibility errors - Unable to delete file */
public static final long H5E_CANTDELETEFILE = H5E_CANTDELETEFILE_g();
/** Minor error codes - Cache related errors - Unable to create a flush dependency */
public static final long H5E_CANTDEPEND = H5E_CANTDEPEND_g();
/** Minor error codes - Cache related errors - Unable to mark metadata as dirty */
public static final long H5E_CANTDIRTY = H5E_CANTDIRTY_g();
/** Minor error codes - B-tree related errors - Unable to encode value */
public static final long H5E_CANTENCODE = H5E_CANTENCODE_g();
/** Minor error codes - Cache related errors - Unable to expunge a metadata cache entry */
public static final long H5E_CANTEXPUNGE = H5E_CANTEXPUNGE_g();
/** Minor error codes - Heap errors - Can't extend heap's space */
public static final long H5E_CANTEXTEND = H5E_CANTEXTEND_g();
/** I/O pipeline errors - Filter operation failed */
public static final long H5E_CANTFILTER = H5E_CANTFILTER_g();
/** Minor error codes - Cache related errors - Unable to flush data from cache */
public static final long H5E_CANTFLUSH = H5E_CANTFLUSH_g();
/** Minor error codes - Resource errors - Unable to free object */
public static final long H5E_CANTFREE = H5E_CANTFREE_g();
/** Minor error codes - Parallel MPI - Can't gather data */
public static final long H5E_CANTGATHER = H5E_CANTGATHER_g();
/** Minor error codes - Resource errors - Unable to garbage collect */
public static final long H5E_CANTGC = H5E_CANTGC_g();
/** Minor error codes - Property list errors - Can't get value */
public static final long H5E_CANTGET = H5E_CANTGET_g();
/** Minor error codes - Resource errors - Unable to compute size */
public static final long H5E_CANTGETSIZE = H5E_CANTGETSIZE_g();
/** Minor error codes - Object ID related errors - Unable to increment reference count */
public static final long H5E_CANTINC = H5E_CANTINC_g();
/** Minor error codes - Function entry/exit interface - Unable to initialize object */
public static final long H5E_CANTINIT = H5E_CANTINIT_g();
/** Minor error codes - Cache related errors - Unable to insert metadata into cache */
public static final long H5E_CANTINS = H5E_CANTINS_g();
/** Minor error codes - B-tree related errors - Unable to insert object */
public static final long H5E_CANTINSERT = H5E_CANTINSERT_g();
/** Minor error codes - B-tree related errors - Unable to list node */
public static final long H5E_CANTLIST = H5E_CANTLIST_g();
/** Minor error codes - Cache related errors - Unable to load metadata into cache */
public static final long H5E_CANTLOAD = H5E_CANTLOAD_g();
/** Minor error codes - Resource errors - Unable to lock object */
public static final long H5E_CANTLOCK = H5E_CANTLOCK_g();
/** Minor error codes - File accessibility errors Unable to lock file */
public static final long H5E_CANTLOCKFILE = H5E_CANTLOCKFILE_g();
/** Minor error codes - Cache related errors - Unable to mark a pinned entry as clean */
public static final long H5E_CANTMARKCLEAN = H5E_CANTMARKCLEAN_g();
/** Minor error codes - Cache related errors - Unable to mark a pinned entry as dirty */
public static final long H5E_CANTMARKDIRTY = H5E_CANTMARKDIRTY_g();
/** Minor error codes - Cache related errors - Unable to mark an entry as unserialized */
public static final long H5E_CANTMARKSERIALIZED = H5E_CANTMARKSERIALIZED_g();
/** Minor error codes - Cache related errors - Unable to mark an entry as serialized */
public static final long H5E_CANTMARKUNSERIALIZED = H5E_CANTMARKUNSERIALIZED_g();
/** Minor error codes - Free space errors - Can't merge objects */
public static final long H5E_CANTMERGE = H5E_CANTMERGE_g();
/** Minor error codes - B-tree related errors - Unable to modify record */
public static final long H5E_CANTMODIFY = H5E_CANTMODIFY_g();
/** Minor error codes - Link related errors - Can't move object */
public static final long H5E_CANTMOVE = H5E_CANTMOVE_g();
/** Minor error codes - Dataspace errors - Can't move to next iterator location */
public static final long H5E_CANTNEXT = H5E_CANTNEXT_g();
/** Minor error codes - Cache related errors - Unable to notify object about action */
public static final long H5E_CANTNOTIFY = H5E_CANTNOTIFY_g();
/** Minor error codes - File accessibility errors - Unable to open file */
public static final long H5E_CANTOPENFILE = H5E_CANTOPENFILE_g();
/** Minor error codes - Group related errors - Can't open object */
public static final long H5E_CANTOPENOBJ = H5E_CANTOPENOBJ_g();
/** Minor error codes - Heap errors - Can't operate on object */
public static final long H5E_CANTOPERATE = H5E_CANTOPERATE_g();
/** Minor error codes - Object header related errors - Can't pack messages */
public static final long H5E_CANTPACK = H5E_CANTPACK_g();
/** Minor error codes - Cache related errors - Unable to pin cache entry */
public static final long H5E_CANTPIN = H5E_CANTPIN_g();
/** Minor error codes - Cache related errors - Unable to protect metadata */
public static final long H5E_CANTPROTECT = H5E_CANTPROTECT_g();
/** Minor error codes - Parallel MPI - Can't receive data */
public static final long H5E_CANTRECV = H5E_CANTRECV_g();
/** Minor error codes - B-tree related errors - Unable to redistribute records */
public static final long H5E_CANTREDISTRIBUTE = H5E_CANTREDISTRIBUTE_g();
/** Minor error codes - Object ID related errors - Unable to register new ID */
public static final long H5E_CANTREGISTER = H5E_CANTREGISTER_g();
/** Minor error codes - Function entry/exit interface - Unable to release object */
public static final long H5E_CANTRELEASE = H5E_CANTRELEASE_g();
/** Minor error codes - B-tree related errors - Unable to remove object */
public static final long H5E_CANTREMOVE = H5E_CANTREMOVE_g();
/** Minor error codes - Object header related errors - Unable to rename object */
public static final long H5E_CANTRENAME = H5E_CANTRENAME_g();
/** Minor error codes - Object header related errors - Can't reset object */
public static final long H5E_CANTRESET = H5E_CANTRESET_g();
/** Minor error codes - Cache related errors - Unable to resize a metadata cache entry */
public static final long H5E_CANTRESIZE = H5E_CANTRESIZE_g();
/** Minor error codes - Heap errors - Can't restore condition */
public static final long H5E_CANTRESTORE = H5E_CANTRESTORE_g();
/** Minor error codes - Free space errors - Can't revive object */
public static final long H5E_CANTREVIVE = H5E_CANTREVIVE_g();
/** Minor error codes - Free space errors - Can't shrink container */
public static final long H5E_CANTSHRINK = H5E_CANTSHRINK_g();
/** Minor error codes - Dataspace errors - Can't select hyperslab */
public static final long H5E_CANTSELECT = H5E_CANTSELECT_g();
/** Minor error codes - Cache related errors - Unable to serialize data from cache */
public static final long H5E_CANTSERIALIZE = H5E_CANTSERIALIZE_g();
/** Minor error codes - Property list errors - Can't set value */
public static final long H5E_CANTSET = H5E_CANTSET_g();
/** Minor error codes - Link related errors - Can't sort objects */
public static final long H5E_CANTSORT = H5E_CANTSORT_g();
/** Minor error codes - B-tree related errors - Unable to split node */
public static final long H5E_CANTSPLIT = H5E_CANTSPLIT_g();
/** Minor error codes - B-tree related errors - Unable to swap records */
public static final long H5E_CANTSWAP = H5E_CANTSWAP_g();
/** Minor error codes - Cache related errors - Unable to tag metadata in the cache */
public static final long H5E_CANTTAG = H5E_CANTTAG_g();
/** Minor error codes - Cache related errors - Unable to uncork an object */
public static final long H5E_CANTUNCORK = H5E_CANTUNCORK_g();
/** Minor error codes - Cache related errors - Unable to destroy a flush dependency */
public static final long H5E_CANTUNDEPEND = H5E_CANTUNDEPEND_g();
/** Minor error codes - Resource errors - Unable to unlock object */
public static final long H5E_CANTUNLOCK = H5E_CANTUNLOCK_g();
/** Minor error codes - File accessibility errors Unable to unlock file */
public static final long H5E_CANTUNLOCKFILE = H5E_CANTUNLOCKFILE_g();
/** Minor error codes - Cache related errors - Unable to un-pin cache entry */
public static final long H5E_CANTUNPIN = H5E_CANTUNPIN_g();
/** Minor error codes - Cache related errors - Unable to unprotect metadata */
public static final long H5E_CANTUNPROTECT = H5E_CANTUNPROTECT_g();
/** Minor error codes - Cache related errors - Unable to mark metadata as unserialized */
public static final long H5E_CANTUNSERIALIZE = H5E_CANTUNSERIALIZE_g();
/** Minor error codes - Heap errors - Can't update object */
public static final long H5E_CANTUPDATE = H5E_CANTUPDATE_g();
/** Generic low-level file I/O errors - Close failed */
public static final long H5E_CLOSEERROR = H5E_CLOSEERROR_g();
/** Minor error codes - Group related errors - Name component is too long */
public static final long H5E_COMPLEN = H5E_COMPLEN_g();
/** Major error codes - API Context */
public static final long H5E_CONTEXT = H5E_CONTEXT_g();
/** Major error codes - Dataset */
public static final long H5E_DATASET = H5E_DATASET_g();
/** Major error codes - Dataspace */
public static final long H5E_DATASPACE = H5E_DATASPACE_g();
/** Major error codes - Datatype */
public static final long H5E_DATATYPE = H5E_DATATYPE_g();
/** Value for the default error stack */
public static final long H5E_DEFAULT = H5E_DEFAULT();
/** Minor error codes - Property list errors - Duplicate class name in parent class */
public static final long H5E_DUPCLASS = H5E_DUPCLASS_g();
/** Major error codes - Extensible Array */
public static final long H5E_EARRAY = H5E_EARRAY_g();
/** Major error codes - External file list */
public static final long H5E_EFL = H5E_EFL_g();
/** Major error codes - Error API */
public static final long H5E_ERROR = H5E_ERROR_g();
/** Minor error codes - B-tree related errors - Object already exists */
public static final long H5E_EXISTS = H5E_EXISTS_g();
/** Major error codes - Fixed Array */
public static final long H5E_FARRAY = H5E_FARRAY_g();
/** Generic low-level file I/O errors - File control (fcntl) failed */
public static final long H5E_FCNTL = H5E_FCNTL_g();
/** Major error codes - File accessibility */
public static final long H5E_FILE = H5E_FILE_g();
/** Minor error codes - File accessibility errors - File already exists */
public static final long H5E_FILEEXISTS = H5E_FILEEXISTS_g();
/** Minor error codes - File accessibility errors - File already open */
public static final long H5E_FILEOPEN = H5E_FILEOPEN_g();
/** Major error codes - Free Space Manager */
public static final long H5E_FSPACE = H5E_FSPACE_g();
/** Major error codes - Function entry/exit */
public static final long H5E_FUNC = H5E_FUNC_g();
/** Major error codes - Heap */
public static final long H5E_HEAP = H5E_HEAP_g();
/** Minor error codes - Dataspace errors - Internal states are inconsistent */
public static final long H5E_INCONSISTENTSTATE = H5E_INCONSISTENTSTATE_g();
/** Major error codes - Internal error (too specific to document in detail) */
public static final long H5E_INTERNAL = H5E_INTERNAL_g();
/** Major error codes - Low-level I/O */
public static final long H5E_IO = H5E_IO_g();
/** Major error codes - Links */
public static final long H5E_LINK = H5E_LINK_g();
/** Minor error codes - Object header related errors - Bad object header link count */
public static final long H5E_LINKCOUNT = H5E_LINKCOUNT_g();
/** Minor error codes - Cache related errors - Failure in the cache logging framework */
public static final long H5E_LOGGING = H5E_LOGGING_g();
/** Major error codes - Map */
public static final long H5E_MAP = H5E_MAP_g();
/** Minor error codes - File accessibility errors - File mount error */
public static final long H5E_MOUNT = H5E_MOUNT_g();
/** Minor error codes - Parallel MPI - Some MPI function failed */
public static final long H5E_MPI = H5E_MPI_g();
/** Minor error codes - Parallel MPI - MPI Error String */
public static final long H5E_MPIERRSTR = H5E_MPIERRSTR_g();
/** Minor error codes - Link related errors - Too many soft links in path */
public static final long H5E_NLINKS = H5E_NLINKS_g();
/** Minor error codes - Parallel MPI - Can't perform independent IO */
public static final long H5E_NO_INDEPENDENT = H5E_NO_INDEPENDENT_g();
/** I/O pipeline errors - Filter present but encoding disabled */
public static final long H5E_NOENCODER = H5E_NOENCODER_g();
/** I/O pipeline errors - Requested filter is not available */
public static final long H5E_NOFILTER = H5E_NOFILTER_g();
/** Minor error codes - Object ID related errors - Out of IDs for group */
public static final long H5E_NOIDS = H5E_NOIDS_g();
/** Major error codes - No error */
public static final long H5E_NONE_MAJOR = H5E_NONE_MAJOR_g();
/** No error */
public static final long H5E_NONE_MINOR = H5E_NONE_MINOR_g();
/** Minor error codes - Resource errors - No space available for allocation */
public static final long H5E_NOSPACE = H5E_NOSPACE_g();
/** Minor error codes - Cache related errors - Metadata not currently cached */
public static final long H5E_NOTCACHED = H5E_NOTCACHED_g();
/** Minor error codes - B-tree related errors - Object not found */
public static final long H5E_NOTFOUND = H5E_NOTFOUND_g();
/** Minor error codes - File accessibility errors - Not an HDF5 file */
public static final long H5E_NOTHDF5 = H5E_NOTHDF5_g();
/** Minor error codes - Link related errors - Link class not registered */
public static final long H5E_NOTREGISTERED = H5E_NOTREGISTERED_g();
/** Minor error codes - Resource errors - Object is already open */
public static final long H5E_OBJOPEN = H5E_OBJOPEN_g();
/** Major error codes - Object header */
public static final long H5E_OHDR = H5E_OHDR_g();
/** Minor error codes - Plugin errors - Can't open directory or file */
public static final long H5E_OPENERROR = H5E_OPENERROR_g();
/** Generic low-level file I/O errors - Address overflowed */
public static final long H5E_OVERFLOW = H5E_OVERFLOW_g();
/** Major error codes - Page Buffering */
public static final long H5E_PAGEBUF = H5E_PAGEBUF_g();
/** Minor error codes - Group related errors - Problem with path to object */
public static final long H5E_PATH = H5E_PATH_g();
/** Major error codes - Data filters */
public static final long H5E_PLINE = H5E_PLINE_g();
/** Major error codes - Property lists */
public static final long H5E_PLIST = H5E_PLIST_g();
/** Major error codes - Plugin for dynamically loaded library */
public static final long H5E_PLUGIN = H5E_PLUGIN_g();
/** Minor error codes - Cache related errors - Protected metadata error */
public static final long H5E_PROTECT = H5E_PROTECT_g();
/** Generic low-level file I/O errors - Read failed */
public static final long H5E_READERROR = H5E_READERROR_g();
/** Major error codes - References */
public static final long H5E_REFERENCE = H5E_REFERENCE_g();
/** Major error codes - Resource unavailable */
public static final long H5E_RESOURCE = H5E_RESOURCE_g();
/** Major error codes - Reference Counted Strings */
public static final long H5E_RS = H5E_RS_g();
/** Generic low-level file I/O errors - Seek failed */
public static final long H5E_SEEKERROR = H5E_SEEKERROR_g();
/** Minor error codes - Property list errors - Disallowed operation */
public static final long H5E_SETDISALLOWED = H5E_SETDISALLOWED_g();
/** I/O pipeline errors - Error from filter 'set local' callback */
public static final long H5E_SETLOCAL = H5E_SETLOCAL_g();
/** Major error codes - Skip Lists */
public static final long H5E_SLIST = H5E_SLIST_g();
/** Major error codes - Shared Object Header Messages */
public static final long H5E_SOHM = H5E_SOHM_g();
/** Major error codes - Data storage */
public static final long H5E_STORAGE = H5E_STORAGE_g();
/** Major error codes - Symbol table */
public static final long H5E_SYM = H5E_SYM_g();
/** Minor error codes - System level errors - System error message */
public static final long H5E_SYSERRSTR = H5E_SYSERRSTR_g();
/** Minor error codes - Cache related errors - Internal error detected */
public static final long H5E_SYSTEM = H5E_SYSTEM_g();
/** Minor error codes - Link related errors - Link traversal failure */
public static final long H5E_TRAVERSE = H5E_TRAVERSE_g();
/** Minor error codes - File accessibility errors - File has been truncated */
public static final long H5E_TRUNCATED = H5E_TRUNCATED_g();
/** Major error codes - Ternary Search Trees */
public static final long H5E_TST = H5E_TST_g();
/** Minor error codes - Argument errors - Information is uinitialized */
public static final long H5E_UNINITIALIZED = H5E_UNINITIALIZED_g();
/** Minor error codes - Argument errors - Feature is unsupported */
public static final long H5E_UNSUPPORTED = H5E_UNSUPPORTED_g();
/** Minor error codes - Object header related errors - Wrong version number */
public static final long H5E_VERSION = H5E_VERSION_g();
/** Major error codes - Virtual File Layer */
public static final long H5E_VFL = H5E_VFL_g();
/** Major error codes - Virtual Object Layer */
public static final long H5E_VOL = H5E_VOL_g();
/** Error stack traversal direction - begin at API function, end deep */
public static final long H5E_WALK_DOWNWARD = H5E_WALK_DOWNWARD();
/** Error stack traversal direction - begin deep, end at API function */
public static final long H5E_WALK_UPWARD = H5E_WALK_UPWARD();
/** Generic low-level file I/O errors - Write failed */
public static final long H5E_WRITEERROR = H5E_WRITEERROR_g();
/** */
private static final int H5ES_STATUS_IN_PROGRESS = H5ES_STATUS_IN_PROGRESS();
/** */
private static final int H5ES_STATUS_SUCCEED = H5ES_STATUS_SUCCEED();
/** */
private static final int H5ES_STATUS_FAIL = H5ES_STATUS_FAIL();
/** */
public static final int H5F_ACC_CREAT = H5F_ACC_CREAT();
/** */
public static final int H5F_ACC_EXCL = H5F_ACC_EXCL();
/** */
public static final int H5F_ACC_RDONLY = H5F_ACC_RDONLY();
/** */
public static final int H5F_ACC_RDWR = H5F_ACC_RDWR();
/** */
public static final int H5F_ACC_TRUNC = H5F_ACC_TRUNC();
/** */
public static final int H5F_ACC_DEFAULT = H5F_ACC_DEFAULT();
/** */
public static final int H5F_ACC_SWMR_READ = H5F_ACC_SWMR_READ();
/** */
public static final int H5F_ACC_SWMR_WRITE = H5F_ACC_SWMR_WRITE();
/** */
public static final int H5F_CLOSE_DEFAULT = H5F_CLOSE_DEFAULT();
/** */
public static final int H5F_CLOSE_SEMI = H5F_CLOSE_SEMI();
/** */
public static final int H5F_CLOSE_STRONG = H5F_CLOSE_STRONG();
/** */
public static final int H5F_CLOSE_WEAK = H5F_CLOSE_WEAK();
/** */
public static final int H5F_LIBVER_ERROR = H5F_LIBVER_ERROR();
/** */
public static final int H5F_LIBVER_EARLIEST = H5F_LIBVER_EARLIEST();
/** */
public static final int H5F_LIBVER_V18 = H5F_LIBVER_V18();
/** */
public static final int H5F_LIBVER_V110 = H5F_LIBVER_V110();
/** */
public static final int H5F_LIBVER_V112 = H5F_LIBVER_V112();
/** */
public static final int H5F_LIBVER_V114 = H5F_LIBVER_V114();
/** */
public static final int H5F_LIBVER_V200 = H5F_LIBVER_V200();
/** */
public static final int H5F_LIBVER_LATEST = H5F_LIBVER_LATEST();
/** */
public static final int H5F_LIBVER_NBOUNDS = H5F_LIBVER_NBOUNDS();
/** */
public static final int H5F_OBJ_ALL = H5F_OBJ_ALL();
/** */
public static final int H5F_OBJ_ATTR = H5F_OBJ_ATTR();
/** */
public static final int H5F_OBJ_DATASET = H5F_OBJ_DATASET();
/** */
public static final int H5F_OBJ_DATATYPE = H5F_OBJ_DATATYPE();
/** */
public static final int H5F_OBJ_FILE = H5F_OBJ_FILE();
/** */
public static final int H5F_OBJ_GROUP = H5F_OBJ_GROUP();
/** */
public static final int H5F_OBJ_LOCAL = H5F_OBJ_LOCAL();
/** */
public static final int H5F_SCOPE_GLOBAL = H5F_SCOPE_GLOBAL();
/** */
public static final int H5F_SCOPE_LOCAL = H5F_SCOPE_LOCAL();
/** */
public static final long H5F_UNLIMITED = H5F_UNLIMITED();
/** */
public static final int H5F_FSPACE_STRATEGY_FSM_AGGR = H5F_FSPACE_STRATEGY_FSM_AGGR();
/** */
public static final int H5F_FSPACE_STRATEGY_AGGR = H5F_FSPACE_STRATEGY_AGGR();
/** */
public static final int H5F_FSPACE_STRATEGY_PAGE = H5F_FSPACE_STRATEGY_PAGE();
/** */
public static final int H5F_FSPACE_STRATEGY_NONE = H5F_FSPACE_STRATEGY_NONE();
/** */
public static final int H5F_FSPACE_STRATEGY_NTYPES = H5F_FSPACE_STRATEGY_NTYPES();
/** */
public static final long H5FD_CORE = H5FD_CORE_id_g();
/** */
public static final long H5FD_DIRECT = getH5FD_DIRECT();
/** */
public static final long H5FD_FAMILY = H5FD_FAMILY_id_g();
/** */
public static final long H5FD_LOG = H5FD_LOG_id_g();
/** */
public static final long H5FD_MPIO = getH5FD_MPIO();
/** */
public static final long H5FD_MULTI = H5FD_MULTI_id_g();
/** */
public static final long H5FD_ONION = H5FD_ONION_id_g();
/** */
public static final long H5FD_SEC2 = H5FD_SEC2_id_g();
/** */
public static final long H5FD_SPLITTER = H5FD_SPLITTER_id_g();
/** */
public static final long H5FD_STDIO = H5FD_STDIO_id_g();
/** */
public static final long H5FD_WINDOWS = H5FD_SEC2_id_g();
/** */
public static final long H5FD_ROS3 = getH5FD_ROS3();
/** */
public static final long H5FD_HDFS = getH5FD_HDFS();
/** */
public static final long H5FD_MIRROR = getH5FD_MIRROR();
/** */
public static final int H5FD_LOG_LOC_READ = H5FD_LOG_LOC_READ();
/** */
public static final int H5FD_LOG_LOC_WRITE = H5FD_LOG_LOC_WRITE();
/** */
public static final int H5FD_LOG_LOC_SEEK = H5FD_LOG_LOC_SEEK();
/** */
public static final int H5FD_LOG_LOC_IO = H5FD_LOG_LOC_IO();
/** */
public static final int H5FD_LOG_FILE_READ = H5FD_LOG_FILE_READ();
/** */
public static final int H5FD_LOG_FILE_WRITE = H5FD_LOG_FILE_WRITE();
/** */
public static final int H5FD_LOG_FILE_IO = H5FD_LOG_FILE_IO();
/** */
public static final int H5FD_LOG_FLAVOR = H5FD_LOG_FLAVOR();
/** */
public static final int H5FD_LOG_NUM_READ = H5FD_LOG_NUM_READ();
/** */
public static final int H5FD_LOG_NUM_WRITE = H5FD_LOG_NUM_WRITE();
/** */
public static final int H5FD_LOG_NUM_SEEK = H5FD_LOG_NUM_SEEK();
/** */
public static final int H5FD_LOG_NUM_TRUNCATE = H5FD_LOG_NUM_TRUNCATE();
/** */
public static final int H5FD_LOG_NUM_IO = H5FD_LOG_NUM_IO();
/** */
public static final int H5FD_LOG_TIME_OPEN = H5FD_LOG_TIME_OPEN();
/** */
public static final int H5FD_LOG_TIME_STAT = H5FD_LOG_TIME_STAT();
/** */
public static final int H5FD_LOG_TIME_READ = H5FD_LOG_TIME_READ();
/** */
public static final int H5FD_LOG_TIME_WRITE = H5FD_LOG_TIME_WRITE();
/** */
public static final int H5FD_LOG_TIME_SEEK = H5FD_LOG_TIME_SEEK();
/** */
public static final int H5FD_LOG_TIME_CLOSE = H5FD_LOG_TIME_CLOSE();
/** */
public static final int H5FD_LOG_TIME_IO = H5FD_LOG_TIME_IO();
/** */
public static final int H5FD_LOG_ALLOC = H5FD_LOG_ALLOC();
/** */
public static final int H5FD_LOG_ALL = H5FD_LOG_ALL();
/** */
public static final int H5FD_MEM_NOLIST = H5FD_MEM_NOLIST();
/** */
public static final int H5FD_MEM_DEFAULT = H5FD_MEM_DEFAULT();
/** */
public static final int H5FD_MEM_SUPER = H5FD_MEM_SUPER();
/** */
public static final int H5FD_MEM_BTREE = H5FD_MEM_BTREE();
/** */
public static final int H5FD_MEM_DRAW = H5FD_MEM_DRAW();
/** */
public static final int H5FD_MEM_GHEAP = H5FD_MEM_GHEAP();
/** */
public static final int H5FD_MEM_LHEAP = H5FD_MEM_LHEAP();
/** */
public static final int H5FD_MEM_OHDR = H5FD_MEM_OHDR();
/** */
public static final int H5FD_MEM_NTYPES = H5FD_MEM_NTYPES();
/** */
public static final BigInteger H5FD_BIG_MEM_NTYPES =
new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(H5FD_MEM_NTYPES()).array());
/** */
public static final BigInteger H5FD_BIG_MEM_NTYPES_MINUS =
new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(H5FD_MEM_NTYPES() - 1L).array());
/** */
public static final BigInteger H5FD_BIG_HADDR_MAX =
new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(HADDR_MAX()).array());
/** */
public static final long H5FD_DEFAULT_HADDR_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES).longValue();
/** */
public static final long H5FD_MEM_DEFAULT_SIZE = 0L;
/** */
public static final long H5FD_MEM_DEFAULT_SUPER_SIZE = 0L;
/** */
public static final long H5FD_MEM_DEFAULT_BTREE_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES_MINUS)
.multiply(new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(1).array()))
.longValue();
/** */
public static final long H5FD_MEM_DEFAULT_DRAW_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES_MINUS)
.multiply(new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(2).array()))
.longValue();
/** */
public static final long H5FD_MEM_DEFAULT_GHEAP_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES_MINUS)
.multiply(new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(3).array()))
.longValue();
/** */
public static final long H5FD_MEM_DEFAULT_LHEAP_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES_MINUS)
.multiply(new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(4).array()))
.longValue();
/** */
public static final long H5FD_MEM_DEFAULT_OHDR_SIZE =
H5FD_BIG_HADDR_MAX.divide(H5FD_BIG_MEM_NTYPES_MINUS)
.multiply(new BigInteger(1, ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(5).array()))
.longValue();
// public static final int H5G_DATASET = H5G_DATASET();
// public static final int H5G_GROUP = H5G_GROUP();
// public static final int H5G_LINK = H5G_LINK();
// public static final int H5G_UDLINK = H5G_UDLINK();
// public static final int H5G_LINK_ERROR = H5G_LINK_ERROR();
// public static final int H5G_LINK_HARD = H5G_LINK_HARD();
// public static final int H5G_LINK_SOFT = H5G_LINK_SOFT();
// public static final int H5G_NLIBTYPES = H5G_NLIBTYPES();
// public static final int H5G_NTYPES = H5G_NTYPES();
// public static final int H5G_NUSERTYPES = H5G_NUSERTYPES();
// public static final int H5G_RESERVED_5 = H5G_RESERVED_5();
// public static final int H5G_RESERVED_6 = H5G_RESERVED_6();
// public static final int H5G_RESERVED_7 = H5G_RESERVED_7();
// public static final int H5G_SAME_LOC = H5G_SAME_LOC();
// public static final int H5G_TYPE = H5G_TYPE();
// public static final int H5G_UNKNOWN = H5G_UNKNOWN();
/** */
public static final int H5G_STORAGE_TYPE_UNKNOWN = H5G_STORAGE_TYPE_UNKNOWN();
/** */
public static final int H5G_STORAGE_TYPE_SYMBOL_TABLE = H5G_STORAGE_TYPE_SYMBOL_TABLE();
/** */
public static final int H5G_STORAGE_TYPE_COMPACT = H5G_STORAGE_TYPE_COMPACT();
/** */
public static final int H5G_STORAGE_TYPE_DENSE = H5G_STORAGE_TYPE_DENSE();
/** */
public static final int H5I_ATTR = H5I_ATTR();
/** */
public static final int H5I_BADID = H5I_BADID();
/** */
public static final int H5I_DATASET = H5I_DATASET();
/** */
public static final int H5I_DATASPACE = H5I_DATASPACE();
/** */
public static final int H5I_DATATYPE = H5I_DATATYPE();
/** */
public static final int H5I_ERROR_CLASS = H5I_ERROR_CLASS();
/** */
public static final int H5I_ERROR_MSG = H5I_ERROR_MSG();
/** */
public static final int H5I_ERROR_STACK = H5I_ERROR_STACK();
/** */
public static final int H5I_FILE = H5I_FILE();
/** */
public static final int H5I_GENPROP_CLS = H5I_GENPROP_CLS();
/** */
public static final int H5I_GENPROP_LST = H5I_GENPROP_LST();
/** */
public static final int H5I_GROUP = H5I_GROUP();
/** */
public static final int H5I_INVALID_HID = H5I_INVALID_HID();
/** */
public static final int H5I_NTYPES = H5I_NTYPES();
/** */
public static final int H5I_UNINIT = H5I_UNINIT();
/** */
public static final int H5I_VFL = H5I_VFL();
/** */
public static final int H5I_VOL = H5I_VOL();
/** */
public static final int H5L_TYPE_ERROR = H5L_TYPE_ERROR();
/** */
public static final int H5L_TYPE_HARD = H5L_TYPE_HARD();
/** */
public static final int H5L_TYPE_SOFT = H5L_TYPE_SOFT();
/** */
public static final int H5L_TYPE_EXTERNAL = H5L_TYPE_EXTERNAL();
/** */
public static final int H5L_TYPE_MAX = H5L_TYPE_MAX();
/** */
public static final int H5O_COPY_SHALLOW_HIERARCHY_FLAG = H5O_COPY_SHALLOW_HIERARCHY_FLAG();
/** */
public static final int H5O_COPY_EXPAND_SOFT_LINK_FLAG = H5O_COPY_EXPAND_SOFT_LINK_FLAG();
/** */
public static final int H5O_COPY_EXPAND_EXT_LINK_FLAG = H5O_COPY_EXPAND_EXT_LINK_FLAG();
/** */
public static final int H5O_COPY_EXPAND_REFERENCE_FLAG = H5O_COPY_EXPAND_REFERENCE_FLAG();
/** */
public static final int H5O_COPY_WITHOUT_ATTR_FLAG = H5O_COPY_WITHOUT_ATTR_FLAG();
/** */
public static final int H5O_COPY_PRESERVE_NULL_FLAG = H5O_COPY_PRESERVE_NULL_FLAG();
/** */
public static final int H5O_INFO_BASIC = H5O_INFO_BASIC();
/** */
public static final int H5O_INFO_TIME = H5O_INFO_TIME();
/** */
public static final int H5O_INFO_NUM_ATTRS = H5O_INFO_NUM_ATTRS();
/** */
public static final int H5O_INFO_ALL = H5O_INFO_ALL();
/** */
public static final int H5O_NATIVE_INFO_HDR = H5O_NATIVE_INFO_HDR();
/** */
public static final int H5O_NATIVE_INFO_META_SIZE = H5O_NATIVE_INFO_META_SIZE();
/** */
public static final int H5O_NATIVE_INFO_ALL = H5O_NATIVE_INFO_ALL();
/** */
public static final int H5O_SHMESG_NONE_FLAG = H5O_SHMESG_NONE_FLAG();
/** */
public static final int H5O_SHMESG_SDSPACE_FLAG = H5O_SHMESG_SDSPACE_FLAG();
/** */
public static final int H5O_SHMESG_DTYPE_FLAG = H5O_SHMESG_DTYPE_FLAG();
/** */
public static final int H5O_SHMESG_FILL_FLAG = H5O_SHMESG_FILL_FLAG();
/** */
public static final int H5O_SHMESG_PLINE_FLAG = H5O_SHMESG_PLINE_FLAG();
/** */
public static final int H5O_SHMESG_ATTR_FLAG = H5O_SHMESG_ATTR_FLAG();
/** */
public static final int H5O_SHMESG_ALL_FLAG = H5O_SHMESG_ALL_FLAG();
/** */
public static final int H5O_TYPE_UNKNOWN = H5O_TYPE_UNKNOWN();
/** */
public static final int H5O_TYPE_GROUP = H5O_TYPE_GROUP();
/** */
public static final int H5O_TYPE_DATASET = H5O_TYPE_DATASET();
/** */
public static final int H5O_TYPE_NAMED_DATATYPE = H5O_TYPE_NAMED_DATATYPE();
/** */
public static final int H5O_TYPE_NTYPES = H5O_TYPE_NTYPES();
/** */
public static final int H5O_MAX_TOKEN_SIZE = H5O_MAX_TOKEN_SIZE();
/** H5O_token_t is derived from the MemorySegment */
public static final H5O_token_t H5O_TOKEN_UNDEF = new H5O_token_t(H5O_TOKEN_UNDEF_g());
/** */
public static final long H5P_ROOT = H5P_CLS_ROOT_ID_g();
/** */
public static final long H5P_OBJECT_CREATE = H5P_CLS_OBJECT_CREATE_ID_g();
/** */
public static final long H5P_FILE_CREATE = H5P_CLS_FILE_CREATE_ID_g();
/** */
public static final long H5P_FILE_ACCESS = H5P_CLS_FILE_ACCESS_ID_g();
/** */
public static final long H5P_DATASET_CREATE = H5P_CLS_DATASET_CREATE_ID_g();
/** */
public static final long H5P_DATASET_ACCESS = H5P_CLS_DATASET_ACCESS_ID_g();
/** */
public static final long H5P_DATASET_XFER = H5P_CLS_DATASET_XFER_ID_g();
/** */
public static final long H5P_FILE_MOUNT = H5P_CLS_FILE_MOUNT_ID_g();
/** */
public static final long H5P_GROUP_CREATE = H5P_CLS_GROUP_CREATE_ID_g();
/** */
public static final long H5P_GROUP_ACCESS = H5P_CLS_GROUP_ACCESS_ID_g();
/** */
public static final long H5P_DATATYPE_CREATE = H5P_CLS_DATATYPE_CREATE_ID_g();
/** */
public static final long H5P_DATATYPE_ACCESS = H5P_CLS_DATATYPE_ACCESS_ID_g();
/** */
public static final long H5P_MAP_CREATE = H5P_CLS_MAP_CREATE_ID_g();
/** */
public static final long H5P_MAP_ACCESS = H5P_CLS_MAP_ACCESS_ID_g();
/** */
public static final long H5P_STRING_CREATE = H5P_CLS_STRING_CREATE_ID_g();
/** */
public static final long H5P_ATTRIBUTE_CREATE = H5P_CLS_ATTRIBUTE_CREATE_ID_g();
/** */
public static final long H5P_ATTRIBUTE_ACCESS = H5P_CLS_ATTRIBUTE_ACCESS_ID_g();
/** */
public static final long H5P_OBJECT_COPY = H5P_CLS_OBJECT_COPY_ID_g();
/** */
public static final long H5P_LINK_CREATE = H5P_CLS_LINK_CREATE_ID_g();
/** */
public static final long H5P_LINK_ACCESS = H5P_CLS_LINK_ACCESS_ID_g();
/** */
public static final long H5P_VOL_INITIALIZE = H5P_CLS_VOL_INITIALIZE_ID_g();
/** */
public static final long H5P_REFERENCE_ACCESS = H5P_CLS_REFERENCE_ACCESS_ID_g();
/** */
public static final long H5P_FILE_CREATE_DEFAULT = H5P_LST_FILE_CREATE_ID_g();
/** */
public static final long H5P_FILE_ACCESS_DEFAULT = H5P_LST_FILE_ACCESS_ID_g();
/** */
public static final long H5P_DATASET_CREATE_DEFAULT = H5P_LST_DATASET_CREATE_ID_g();
/** */
public static final long H5P_DATASET_ACCESS_DEFAULT = H5P_LST_DATASET_ACCESS_ID_g();
/** */
public static final long H5P_DATASET_XFER_DEFAULT = H5P_LST_DATASET_XFER_ID_g();
/** */
public static final long H5P_FILE_MOUNT_DEFAULT = H5P_LST_FILE_MOUNT_ID_g();
/** */
public static final long H5P_GROUP_CREATE_DEFAULT = H5P_LST_GROUP_CREATE_ID_g();
/** */
public static final long H5P_GROUP_ACCESS_DEFAULT = H5P_LST_GROUP_ACCESS_ID_g();
/** */
public static final long H5P_DATATYPE_CREATE_DEFAULT = H5P_LST_DATATYPE_CREATE_ID_g();
/** */
public static final long H5P_DATATYPE_ACCESS_DEFAULT = H5P_LST_DATATYPE_ACCESS_ID_g();
/** */
public static final long H5P_MAP_CREATE_DEFAULT = H5P_LST_MAP_CREATE_ID_g();
/** */
public static final long H5P_MAP_ACCESS_DEFAULT = H5P_LST_MAP_ACCESS_ID_g();
/** */
public static final long H5P_ATTRIBUTE_CREATE_DEFAULT = H5P_LST_ATTRIBUTE_CREATE_ID_g();
/** */
public static final long H5P_ATTRIBUTE_ACCESS_DEFAULT = H5P_LST_ATTRIBUTE_ACCESS_ID_g();
/** */
public static final long H5P_OBJECT_COPY_DEFAULT = H5P_LST_OBJECT_COPY_ID_g();
/** */
public static final long H5P_LINK_CREATE_DEFAULT = H5P_LST_LINK_CREATE_ID_g();
/** */
public static final long H5P_LINK_ACCESS_DEFAULT = H5P_LST_LINK_ACCESS_ID_g();
/** */
public static final long H5P_VOL_INITIALIZE_DEFAULT = H5P_LST_VOL_INITIALIZE_ID_g();
/** */
public static final int H5P_CRT_ORDER_TRACKED = H5P_CRT_ORDER_TRACKED();
/** */
public static final int H5P_CRT_ORDER_INDEXED = H5P_CRT_ORDER_INDEXED();
/** */
public static final long H5P_DEFAULT = H5P_DEFAULT();
/** */
public static final int H5PL_TYPE_ERROR = H5PL_TYPE_ERROR();
/** */
public static final int H5PL_TYPE_FILTER = H5PL_TYPE_FILTER();
/** */
public static final int H5PL_TYPE_VOL = H5PL_TYPE_VOL();
/** */
public static final int H5PL_TYPE_NONE = H5PL_TYPE_NONE();
/** */
public static final int H5PL_FILTER_PLUGIN = H5PL_FILTER_PLUGIN();
/** */
public static final int H5PL_VOL_PLUGIN = H5PL_VOL_PLUGIN();
/** */
public static final int H5PL_ALL_PLUGIN = H5PL_ALL_PLUGIN();
/** */
public static final int H5R_ATTR = H5R_ATTR();
/** */
public static final int H5R_BADTYPE = H5R_BADTYPE();
/** */
public static final int H5R_DATASET_REGION = H5R_DATASET_REGION();
/** */
public static final int H5R_DATASET_REGION1 = H5R_DATASET_REGION1();
/** */
public static final int H5R_DATASET_REGION2 = H5R_DATASET_REGION2();
/** */
public static final int H5R_MAXTYPE = H5R_MAXTYPE();
/** */
public static final long H5R_DSET_REG_REF_BUF_SIZE = H5R_DSET_REG_REF_BUF_SIZE();
/** */
public static final long H5R_OBJ_REF_BUF_SIZE = H5R_OBJ_REF_BUF_SIZE();
/** */
public static final int H5R_REF_BUF_SIZE = H5R_REF_BUF_SIZE();
/** */
public static final int H5R_OBJECT = H5R_OBJECT();
/** */
public static final int H5R_OBJECT1 = H5R_OBJECT1();
/** */
public static final int H5R_OBJECT2 = H5R_OBJECT2();
/** Define atomic datatypes */
public static final int H5S_ALL = H5S_ALL();
/** Define user-level maximum number of dimensions */
public static final int H5S_MAX_RANK = H5S_MAX_RANK();
/** Different types of dataspaces - error */
public static final int H5S_NO_CLASS = H5S_NO_CLASS();
/** Different types of dataspaces - null dataspace */
public static final int H5S_NULL = H5S_NULL();
/** Different types of dataspaces - scalar variable */
public static final int H5S_SCALAR = H5S_SCALAR();
/** Enumerated type for the type of selection - Entire extent selected */
public static final int H5S_SEL_ALL = H5S_SEL_ALL();
/** Enumerated type for the type of selection - Error */
public static final int H5S_SEL_ERROR = H5S_SEL_ERROR();
/** Enumerated type for the type of selection - Hyperslab selected */
public static final int H5S_SEL_HYPERSLABS = H5S_SEL_HYPERSLABS();
/** Enumerated type for the type of selection - LAST */
public static final int H5S_SEL_N = H5S_SEL_N();
/** Enumerated type for the type of selection - Nothing selected */
public static final int H5S_SEL_NONE = H5S_SEL_NONE();
/** Enumerated type for the type of selection - Points / elements selected */
public static final int H5S_SEL_POINTS = H5S_SEL_POINTS();
/** Different ways of combining selections - Binary "and" operation for hyperslabs */
public static final int H5S_SELECT_AND = H5S_SELECT_AND();
/** Different ways of combining selections - Append elements to end of point selection */
public static final int H5S_SELECT_APPEND = H5S_SELECT_APPEND();
/** Different ways of combining selections - Invalid upper bound on selection operations */
public static final int H5S_SELECT_INVALID = H5S_SELECT_INVALID();
/** Different ways of combining selections - error */
public static final int H5S_SELECT_NOOP = H5S_SELECT_NOOP();
/** Different ways of combining selections - Binary "not" operation for hyperslabs */
public static final int H5S_SELECT_NOTA = H5S_SELECT_NOTA();
/** Different ways of combining selections - Binary "not" operation for hyperslabs */
public static final int H5S_SELECT_NOTB = H5S_SELECT_NOTB();
/** Different ways of combining selections - Binary "or" operation for hyperslabs */
public static final int H5S_SELECT_OR = H5S_SELECT_OR();
/** Different ways of combining selections - Prepend elements to beginning of point selection */
public static final int H5S_SELECT_PREPEND = H5S_SELECT_PREPEND();
/** Different ways of combining selections - Select "set" operation */
public static final int H5S_SELECT_SET = H5S_SELECT_SET();
/** Different ways of combining selections - Binary "xor" operation for hyperslabs */
public static final int H5S_SELECT_XOR = H5S_SELECT_XOR();
/** Different types of dataspaces - simple dataspace */
public static final int H5S_SIMPLE = H5S_SIMPLE();
/** Define atomic datatypes */
public static final long H5S_UNLIMITED = H5S_UNLIMITED();
/** */
// public static final long H5T_ALPHA_B16 = H5T_ALPHA_B16;
/** */
// public static final long H5T_ALPHA_B32 = H5T_ALPHA_B32;
/** */
// public static final long H5T_ALPHA_B64 = H5T_ALPHA_B64;
/** */
// public static final long H5T_ALPHA_B8 = H5T_ALPHA_B8;
/** */
// public static final long H5T_ALPHA_F32 = H5T_ALPHA_F32;
/** */
// public static final long H5T_ALPHA_F64 = H5T_ALPHA_F64;
/** */
// public static final long H5T_ALPHA_I16 = H5T_ALPHA_I16;
/** */
// public static final long H5T_ALPHA_I32 = H5T_ALPHA_I32;
/** */
// public static final long H5T_ALPHA_I64 = H5T_ALPHA_I64;
/** */
// public static final long H5T_ALPHA_I8 = H5T_ALPHA_I8;
/** */
// public static final long H5T_ALPHA_U16 = H5T_ALPHA_U16;
/** */
// public static final long H5T_ALPHA_U32 = H5T_ALPHA_U32;
/** */
// public static final long H5T_ALPHA_U64 = H5T_ALPHA_U64;
/** */
// public static final long H5T_ALPHA_U8 = H5T_ALPHA_U8;
/** */
public static final int H5T_ARRAY = H5T_ARRAY();
/** */
public static final int H5T_BITFIELD = H5T_BITFIELD();
/** */
public static final int H5T_BKG_NO = H5T_BKG_NO();
/** */
public static final int H5T_BKG_YES = H5T_BKG_YES();
/** */
public static final long H5T_C_S1 = H5T_C_S1_g();
/** */
public static final int H5T_COMPLEX = H5T_COMPLEX();
/** */
public static final int H5T_COMPOUND = H5T_COMPOUND();
/** */
public static final int H5T_CONV_CONV = H5T_CONV_CONV();
/** */
public static final int H5T_CONV_FREE = H5T_CONV_FREE();
/** */
public static final int H5T_CONV_INIT = H5T_CONV_INIT();
/** */
public static final long H5T_COMPLEX_IEEE_F16BE = H5T_COMPLEX_IEEE_F16BE_g();
/** */
public static final long H5T_COMPLEX_IEEE_F16LE = H5T_COMPLEX_IEEE_F16LE_g();
/** */
public static final long H5T_COMPLEX_IEEE_F32BE = H5T_COMPLEX_IEEE_F32BE_g();
/** */
public static final long H5T_COMPLEX_IEEE_F32LE = H5T_COMPLEX_IEEE_F32LE_g();
/** */
public static final long H5T_COMPLEX_IEEE_F64BE = H5T_COMPLEX_IEEE_F64BE_g();
/** */
public static final long H5T_COMPLEX_IEEE_F64LE = H5T_COMPLEX_IEEE_F64LE_g();
/** */
public static final int H5T_CSET_ERROR = H5T_CSET_ERROR();
/** */
public static final int H5T_CSET_ASCII = H5T_CSET_ASCII();
/** */
public static final int H5T_CSET_UTF8 = H5T_CSET_UTF8();
/** */
public static final int H5T_CSET_RESERVED_10 = H5T_CSET_RESERVED_10();
/** */
public static final int H5T_CSET_RESERVED_11 = H5T_CSET_RESERVED_11();
/** */
public static final int H5T_CSET_RESERVED_12 = H5T_CSET_RESERVED_12();
/** */
public static final int H5T_CSET_RESERVED_13 = H5T_CSET_RESERVED_13();
/** */
public static final int H5T_CSET_RESERVED_14 = H5T_CSET_RESERVED_14();
/** */
public static final int H5T_CSET_RESERVED_15 = H5T_CSET_RESERVED_15();
/** */
public static final int H5T_CSET_RESERVED_2 = H5T_CSET_RESERVED_2();
/** */
public static final int H5T_CSET_RESERVED_3 = H5T_CSET_RESERVED_3();
/** */
public static final int H5T_CSET_RESERVED_4 = H5T_CSET_RESERVED_4();
/** */
public static final int H5T_CSET_RESERVED_5 = H5T_CSET_RESERVED_5();
/** */
public static final int H5T_CSET_RESERVED_6 = H5T_CSET_RESERVED_6();
/** */
public static final int H5T_CSET_RESERVED_7 = H5T_CSET_RESERVED_7();
/** */
public static final int H5T_CSET_RESERVED_8 = H5T_CSET_RESERVED_8();
/** */
public static final int H5T_CSET_RESERVED_9 = H5T_CSET_RESERVED_9();
/** */
public static final int H5T_DIR_ASCEND = H5T_DIR_ASCEND();
/** */
public static final int H5T_DIR_DEFAULT = H5T_DIR_DEFAULT();
/** */
public static final int H5T_DIR_DESCEND = H5T_DIR_DESCEND();
/** */
public static final int H5T_ENUM = H5T_ENUM();
/** */
public static final int H5T_FLOAT = H5T_FLOAT();
/** */
public static final long H5T_FORTRAN_S1 = H5T_FORTRAN_S1_g();
/** */
public static final long H5T_IEEE_F16BE = H5T_IEEE_F16BE_g();
/** */
public static final long H5T_IEEE_F16LE = H5T_IEEE_F16LE_g();
/** */
public static final long H5T_IEEE_F32BE = H5T_IEEE_F32BE_g();
/** */
public static final long H5T_IEEE_F32LE = H5T_IEEE_F32LE_g();
/** */
public static final long H5T_IEEE_F64BE = H5T_IEEE_F64BE_g();
/** */
public static final long H5T_IEEE_F64LE = H5T_IEEE_F64LE_g();
/** */
public static final int H5T_INTEGER = H5T_INTEGER();
/** */
// public static final long H5T_INTEL_B16 = H5T_INTEL_B16;
/** */
// public static final long H5T_INTEL_B32 = H5T_INTEL_B32;
/** */
// public static final long H5T_INTEL_B64 = H5T_INTEL_B64;
/** */
// public static final long H5T_INTEL_B8 = H5T_INTEL_B8;
/** */
// public static final long H5T_INTEL_F32 = H5T_INTEL_F32;
/** */
// public static final long H5T_INTEL_F64 = H5T_INTEL_F64;
/** */
// public static final long H5T_INTEL_I16 = H5T_INTEL_I16;
/** */
// public static final long H5T_INTEL_I32 = H5T_INTEL_I32;
/** */
// public static final long H5T_INTEL_I64 = H5T_INTEL_I64;
/** */
// public static final long H5T_INTEL_I8 = H5T_INTEL_I8;
/** */
// public static final long H5T_INTEL_U16 = H5T_INTEL_U16;
/** */
// public static final long H5T_INTEL_U32 = H5T_INTEL_U32;
/** */
// public static final long H5T_INTEL_U64 = H5T_INTEL_U64;
/** */
// public static final long H5T_INTEL_U8 = H5T_INTEL_U8;
/** */
// public static final long H5T_MIPS_B16 = H5T_MIPS_B16;
/** */
// public static final long H5T_MIPS_B32 = H5T_MIPS_B32;
/** */
// public static final long H5T_MIPS_B64 = H5T_MIPS_B64;
/** */
// public static final long H5T_MIPS_B8 = H5T_MIPS_B8;
/** */
// public static final long H5T_MIPS_F32 = H5T_MIPS_F32;
/** */
// public static final long H5T_MIPS_F64 = H5T_MIPS_F64;
/** */
// public static final long H5T_MIPS_I16 = H5T_MIPS_I16;
/** */
// public static final long H5T_MIPS_I32 = H5T_MIPS_I32;
/** */
// public static final long H5T_MIPS_I64 = H5T_MIPS_I64;
/** */
// public static final long H5T_MIPS_I8 = H5T_MIPS_I8;
/** */
// public static final long H5T_MIPS_U16 = H5T_MIPS_U16;
/** */
// public static final long H5T_MIPS_U32 = H5T_MIPS_U32;
/** */
// public static final long H5T_MIPS_U64 = H5T_MIPS_U64;
/** */
// public static final long H5T_MIPS_U8 = H5T_MIPS_U8;
/** */
public static final long H5T_NATIVE_B16 = H5T_NATIVE_B16_g();
/** */
public static final long H5T_NATIVE_B32 = H5T_NATIVE_B32_g();
/** */
public static final long H5T_NATIVE_B64 = H5T_NATIVE_B64_g();
/** */
public static final long H5T_NATIVE_B8 = H5T_NATIVE_B8_g();
/** */
public static final long H5T_NATIVE_CHAR = (CHAR_MIN() < 0 ? H5T_NATIVE_SCHAR_g() : H5T_NATIVE_UCHAR_g());
/** */
public static final long H5T_NATIVE_DOUBLE = H5T_NATIVE_DOUBLE_g();
/** */
public static final long H5T_NATIVE_DOUBLE_COMPLEX = H5T_NATIVE_DOUBLE_COMPLEX_g();
/** */
public static final long H5T_NATIVE_FLOAT = H5T_NATIVE_FLOAT_g();
/** */
public static final long H5T_NATIVE_FLOAT16 = H5T_NATIVE_FLOAT16_g();
/** */
public static final long H5T_NATIVE_FLOAT_COMPLEX = H5T_NATIVE_FLOAT_COMPLEX_g();
/** */
public static final long H5T_NATIVE_HADDR = H5T_NATIVE_HADDR_g();
/** */
public static final long H5T_NATIVE_HBOOL = H5T_NATIVE_HBOOL_g();
/** */
public static final long H5T_NATIVE_HERR = H5T_NATIVE_HERR_g();
/** */
public static final long H5T_NATIVE_HSIZE = H5T_NATIVE_HSIZE_g();
/** */
public static final long H5T_NATIVE_HSSIZE = H5T_NATIVE_HSSIZE_g();
/** */
public static final long H5T_NATIVE_INT = H5T_NATIVE_INT_g();
/** */
public static final long H5T_NATIVE_INT_FAST16 = H5T_NATIVE_INT_FAST16_g();
/** */
public static final long H5T_NATIVE_INT_FAST32 = H5T_NATIVE_INT_FAST32_g();
/** */
public static final long H5T_NATIVE_INT_FAST64 = H5T_NATIVE_INT_FAST64_g();
/** */
public static final long H5T_NATIVE_INT_FAST8 = H5T_NATIVE_INT_FAST8_g();
/** */
public static final long H5T_NATIVE_INT_LEAST16 = H5T_NATIVE_INT_LEAST16_g();
/** */
public static final long H5T_NATIVE_INT_LEAST32 = H5T_NATIVE_INT_LEAST32_g();
/** */
public static final long H5T_NATIVE_INT_LEAST64 = H5T_NATIVE_INT_LEAST64_g();
/** */
public static final long H5T_NATIVE_INT_LEAST8 = H5T_NATIVE_INT_LEAST8_g();
/** */
public static final long H5T_NATIVE_INT16 = H5T_NATIVE_INT16_g();
/** */
public static final long H5T_NATIVE_INT32 = H5T_NATIVE_INT32_g();
/** */
public static final long H5T_NATIVE_INT64 = H5T_NATIVE_INT64_g();
/** */
public static final long H5T_NATIVE_INT8 = H5T_NATIVE_INT8_g();
/** */
public static final long H5T_NATIVE_LDOUBLE = H5T_NATIVE_LDOUBLE_g();
/** */
public static final long H5T_NATIVE_LLONG = H5T_NATIVE_LLONG_g();
/** */
public static final long H5T_NATIVE_LONG = H5T_NATIVE_LONG_g();
/** */
public static final long H5T_NATIVE_LDOUBLE_COMPLEX = H5T_NATIVE_LDOUBLE_COMPLEX_g();
/** */
public static final long H5T_NATIVE_OPAQUE = H5T_NATIVE_OPAQUE_g();
/** */
public static final long H5T_NATIVE_SCHAR = H5T_NATIVE_SCHAR_g();
/** */
public static final long H5T_NATIVE_SHORT = H5T_NATIVE_SHORT_g();
/** */
public static final long H5T_NATIVE_UCHAR = H5T_NATIVE_UCHAR_g();
/** */
public static final long H5T_NATIVE_UINT = H5T_NATIVE_UINT_g();
/** */
public static final long H5T_NATIVE_UINT_FAST16 = H5T_NATIVE_UINT_FAST16_g();
/** */
public static final long H5T_NATIVE_UINT_FAST32 = H5T_NATIVE_UINT_FAST32_g();
/** */
public static final long H5T_NATIVE_UINT_FAST64 = H5T_NATIVE_UINT_FAST64_g();
/** */
public static final long H5T_NATIVE_UINT_FAST8 = H5T_NATIVE_UINT_FAST8_g();
/** */
public static final long H5T_NATIVE_UINT_LEAST16 = H5T_NATIVE_UINT_LEAST16_g();
/** */
public static final long H5T_NATIVE_UINT_LEAST32 = H5T_NATIVE_UINT_LEAST32_g();
/** */
public static final long H5T_NATIVE_UINT_LEAST64 = H5T_NATIVE_UINT_LEAST64_g();
/** */
public static final long H5T_NATIVE_UINT_LEAST8 = H5T_NATIVE_UINT_LEAST8_g();
/** */
public static final long H5T_NATIVE_UINT16 = H5T_NATIVE_UINT16_g();
/** */
public static final long H5T_NATIVE_UINT32 = H5T_NATIVE_UINT32_g();
/** */
public static final long H5T_NATIVE_UINT64 = H5T_NATIVE_UINT64_g();
/** */
public static final long H5T_NATIVE_UINT8 = H5T_NATIVE_UINT8_g();
/** */
public static final long H5T_NATIVE_ULLONG = H5T_NATIVE_ULLONG_g();
/** */
public static final long H5T_NATIVE_ULONG = H5T_NATIVE_ULONG_g();
/** */
public static final long H5T_NATIVE_USHORT = H5T_NATIVE_USHORT_g();
/** */
public static final int H5T_NCLASSES = H5T_NCLASSES();
/** */
public static final int H5T_NO_CLASS = H5T_NO_CLASS();
/** */
public static final int H5T_NORM_ERROR = H5T_NORM_ERROR();
/** */
public static final int H5T_NORM_IMPLIED = H5T_NORM_IMPLIED();
/** */
public static final int H5T_NORM_MSBSET = H5T_NORM_MSBSET();
/** */
public static final int H5T_NORM_NONE = H5T_NORM_NONE();
/** */
public static final int H5T_NPAD = H5T_NPAD();
/** */
public static final int H5T_NSGN = H5T_NSGN();
/** */
public static final int H5T_OPAQUE = H5T_OPAQUE();
/** */
public static final int H5T_OPAQUE_TAG_MAX = H5T_OPAQUE_TAG_MAX(); /* 1.6.5 */
/** */
public static final int H5T_ORDER_BE = H5T_ORDER_BE();
/** */
public static final int H5T_ORDER_ERROR = H5T_ORDER_ERROR();
/** */
public static final int H5T_ORDER_LE = H5T_ORDER_LE();
/** */
public static final int H5T_ORDER_NONE = H5T_ORDER_NONE();
/** */
public static final int H5T_ORDER_VAX = H5T_ORDER_VAX();
/** */
public static final int H5T_PAD_BACKGROUND = H5T_PAD_BACKGROUND();
/** */
public static final int H5T_PAD_ERROR = H5T_PAD_ERROR();
/** */
public static final int H5T_PAD_ONE = H5T_PAD_ONE();
/** */
public static final int H5T_PAD_ZERO = H5T_PAD_ZERO();
/** */
public static final int H5T_PERS_DONTCARE = H5T_PERS_DONTCARE();
/** */
public static final int H5T_PERS_HARD = H5T_PERS_HARD();
/** */
public static final int H5T_PERS_SOFT = H5T_PERS_SOFT();
/** */
public static final int H5T_REFERENCE = H5T_REFERENCE();
/** */
public static final int H5T_SGN_2 = H5T_SGN_2();
/** */
public static final int H5T_SGN_ERROR = H5T_SGN_ERROR();
/** */
public static final int H5T_SGN_NONE = H5T_SGN_NONE();
/** */
public static final long H5T_STD_B16BE = H5T_STD_B16BE_g();
/** */
public static final long H5T_STD_B16LE = H5T_STD_B16LE_g();
/** */
public static final long H5T_STD_B32BE = H5T_STD_B32BE_g();
/** */
public static final long H5T_STD_B32LE = H5T_STD_B32LE_g();
/** */
public static final long H5T_STD_B64BE = H5T_STD_B64BE_g();
/** */
public static final long H5T_STD_B64LE = H5T_STD_B64LE_g();
/** */
public static final long H5T_STD_B8BE = H5T_STD_B8BE_g();
/** */
public static final long H5T_STD_B8LE = H5T_STD_B8LE_g();
/** */
public static final long H5T_STD_I16BE = H5T_STD_I16BE_g();
/** */
public static final long H5T_STD_I16LE = H5T_STD_I16LE_g();
/** */
public static final long H5T_STD_I32BE = H5T_STD_I32BE_g();
/** */
public static final long H5T_STD_I32LE = H5T_STD_I32LE_g();
/** */
public static final long H5T_STD_I64BE = H5T_STD_I64BE_g();
/** */
public static final long H5T_STD_I64LE = H5T_STD_I64LE_g();
/** */
public static final long H5T_STD_I8BE = H5T_STD_I8BE_g();
/** */
public static final long H5T_STD_I8LE = H5T_STD_I8LE_g();
/** */
public static final long H5T_STD_REF_DSETREG = H5T_STD_REF_DSETREG_g();
/** */
public static final long H5T_STD_REF_OBJ = H5T_STD_REF_OBJ_g();
/** */
public static final long H5T_STD_REF = H5T_STD_REF_g();
/** */
public static final long H5T_STD_U16BE = H5T_STD_U16BE_g();
/** */
public static final long H5T_STD_U16LE = H5T_STD_U16LE_g();
/** */
public static final long H5T_STD_U32BE = H5T_STD_U32BE_g();
/** */
public static final long H5T_STD_U32LE = H5T_STD_U32LE_g();
/** */
public static final long H5T_STD_U64BE = H5T_STD_U64BE_g();
/** */
public static final long H5T_STD_U64LE = H5T_STD_U64LE_g();
/** */
public static final long H5T_STD_U8BE = H5T_STD_U8BE_g();
/** */
public static final long H5T_STD_U8LE = H5T_STD_U8LE_g();
/** */
public static final int H5T_STR_ERROR = H5T_STR_ERROR();
/** */
public static final int H5T_STR_NULLPAD = H5T_STR_NULLPAD();
/** */
public static final int H5T_STR_NULLTERM = H5T_STR_NULLTERM();
/** */
public static final int H5T_STR_RESERVED_10 = H5T_STR_RESERVED_10();
/** */
public static final int H5T_STR_RESERVED_11 = H5T_STR_RESERVED_11();
/** */
public static final int H5T_STR_RESERVED_12 = H5T_STR_RESERVED_12();
/** */
public static final int H5T_STR_RESERVED_13 = H5T_STR_RESERVED_13();
/** */
public static final int H5T_STR_RESERVED_14 = H5T_STR_RESERVED_14();
/** */
public static final int H5T_STR_RESERVED_15 = H5T_STR_RESERVED_15();
/** */
public static final int H5T_STR_RESERVED_3 = H5T_STR_RESERVED_3();
/** */
public static final int H5T_STR_RESERVED_4 = H5T_STR_RESERVED_4();
/** */
public static final int H5T_STR_RESERVED_5 = H5T_STR_RESERVED_5();
/** */
public static final int H5T_STR_RESERVED_6 = H5T_STR_RESERVED_6();
/** */
public static final int H5T_STR_RESERVED_7 = H5T_STR_RESERVED_7();
/** */
public static final int H5T_STR_RESERVED_8 = H5T_STR_RESERVED_8();
/** */
public static final int H5T_STR_RESERVED_9 = H5T_STR_RESERVED_9();
/** */
public static final int H5T_STR_SPACEPAD = H5T_STR_SPACEPAD();
/** */
public static final int H5T_STRING = H5T_STRING();
/** */
public static final int H5T_TIME = H5T_TIME();
/** */
public static final long H5T_UNIX_D32BE = H5T_UNIX_D32BE_g();
/** */
public static final long H5T_UNIX_D32LE = H5T_UNIX_D32LE_g();
/** */
public static final long H5T_UNIX_D64BE = H5T_UNIX_D64BE_g();
/** */
public static final long H5T_UNIX_D64LE = H5T_UNIX_D64LE_g();
/** */
public static final long H5T_VARIABLE = H5T_VARIABLE();
/** */
public static final int H5T_VLEN = H5T_VLEN();
/** */
public static final int H5VL_CAP_FLAG_NONE = H5VL_CAP_FLAG_NONE();
/** */
public static final int H5VL_CAP_FLAG_THREADSAFE = H5VL_CAP_FLAG_THREADSAFE();
/** */
public static final long H5VL_NATIVE = H5VL_NATIVE_g();
/** */
public static final String H5VL_NATIVE_NAME = H5VL_NATIVE_NAME().getString(0);
/** */
public static final int H5VL_NATIVE_VALUE = H5VL_NATIVE_VALUE();
/** */
public static final int H5VL_NATIVE_VERSION = H5VL_NATIVE_VERSION();
/** */
public static final int H5_VOL_INVALID = H5_VOL_INVALID();
/** */
public static final int H5_VOL_NATIVE = H5_VOL_NATIVE();
/** */
public static final int H5_VOL_RESERVED = H5_VOL_RESERVED();
/** */
public static final int H5_VOL_MAX = H5_VOL_MAX();
/** Return values for filter callback function */
public static final int H5Z_CB_CONT = H5Z_CB_CONT();
/** Return values for filter callback function */
public static final int H5Z_CB_ERROR = H5Z_CB_ERROR();
/** Return values for filter callback function */
public static final int H5Z_CB_FAIL = H5Z_CB_FAIL();
/** Return values for filter callback function */
public static final int H5Z_CB_NO = H5Z_CB_NO();
/** Values to decide if EDC is enabled for reading data */
public static final int H5Z_DISABLE_EDC = H5Z_DISABLE_EDC();
/** Values to decide if EDC is enabled for reading data */
public static final int H5Z_ENABLE_EDC = H5Z_ENABLE_EDC();
/** Values to decide if EDC is enabled for reading data */
public static final int H5Z_ERROR_EDC = H5Z_ERROR_EDC();
/** Filter IDs - deflation like gzip */
public static final int H5Z_FILTER_DEFLATE = H5Z_FILTER_DEFLATE();
/** Filter IDs - no filter */
public static final int H5Z_FILTER_ERROR = H5Z_FILTER_ERROR();
/** Filter IDs - fletcher32 checksum of EDC */
public static final int H5Z_FILTER_FLETCHER32 = H5Z_FILTER_FLETCHER32();
/** Filter IDs - maximum filter id */
public static final int H5Z_FILTER_MAX = H5Z_FILTER_MAX();
/** Filter IDs - nbit compression */
public static final int H5Z_FILTER_NBIT = H5Z_FILTER_NBIT();
/** Filter IDs - reserved indefinitely */
public static final int H5Z_FILTER_NONE = H5Z_FILTER_NONE();
/** Filter IDs - filter ids below this value are reserved for library use */
public static final int H5Z_FILTER_RESERVED = H5Z_FILTER_RESERVED();
/** Filter IDs - scale+offset compression */
public static final int H5Z_FILTER_SCALEOFFSET = H5Z_FILTER_SCALEOFFSET();
/** Filter IDs - shuffle the data */
public static final int H5Z_FILTER_SHUFFLE = H5Z_FILTER_SHUFFLE();
/** Filter IDs - szip compression */
public static final int H5Z_FILTER_SZIP = H5Z_FILTER_SZIP();
/**
* Flags for filter definition (stored)
* definition flag mask
*/
public static final int H5Z_FLAG_DEFMASK = H5Z_FLAG_DEFMASK();
/**
* Additional flags for filter invocation (not stored)
* invocation flag mask
*/
public static final int H5Z_FLAG_INVMASK = H5Z_FLAG_INVMASK();
/**
* Flags for filter definition (stored)
* filter is mandatory
*/
public static final int H5Z_FLAG_MANDATORY = H5Z_FLAG_MANDATORY();
/**
* Flags for filter definition (stored)
* filter is optional
*/
public static final int H5Z_FLAG_OPTIONAL = H5Z_FLAG_OPTIONAL();
/**
* Additional flags for filter invocation (not stored)
* reverse direction; read
*/
public static final int H5Z_FLAG_REVERSE = H5Z_FLAG_REVERSE();
/**
* Additional flags for filter invocation (not stored)
* skip EDC filters for read
*/
public static final int H5Z_FLAG_SKIP_EDC = H5Z_FLAG_SKIP_EDC();
/** Symbol to remove all filters in H5Premove_filter */
public static final int H5Z_FILTER_ALL = H5Z_FILTER_ALL();
/** Maximum number of filters allowed in a pipeline */
public static final int H5Z_MAX_NFILTERS = H5Z_MAX_NFILTERS();
/** Values to decide if EDC is enabled for reading data */
public static final int H5Z_NO_EDC = H5Z_NO_EDC();
/** Bit flags for H5Zget_filter_info */
public static final int H5Z_FILTER_CONFIG_ENCODE_ENABLED = H5Z_FILTER_CONFIG_ENCODE_ENABLED();
/** Bit flags for H5Zget_filter_info */
public static final int H5Z_FILTER_CONFIG_DECODE_ENABLED = H5Z_FILTER_CONFIG_DECODE_ENABLED();
/** Special parameters for ScaleOffset filter*/
public static final int H5Z_SO_INT_MINBITS_DEFAULT = H5Z_SO_INT_MINBITS_DEFAULT();
/** Special parameters for ScaleOffset filter*/
public static final int H5Z_SO_FLOAT_DSCALE = H5Z_SO_FLOAT_DSCALE();
/** Special parameters for ScaleOffset filter*/
public static final int H5Z_SO_FLOAT_ESCALE = H5Z_SO_FLOAT_ESCALE();
/** Special parameters for ScaleOffset filter*/
public static final int H5Z_SO_INT = H5Z_SO_INT();
/** shuffle filter - Number of parameters that users can set */
public static final int H5Z_SHUFFLE_USER_NPARMS = H5Z_SHUFFLE_USER_NPARMS();
/** shuffle filter - Total number of parameters for filter */
public static final int H5Z_SHUFFLE_TOTAL_NPARMS = H5Z_SHUFFLE_TOTAL_NPARMS();
/** szip filter - Number of parameters that users can set */
public static final int H5Z_SZIP_USER_NPARMS = H5Z_SZIP_USER_NPARMS();
/** szip filter - Total number of parameters for filter */
public static final int H5Z_SZIP_TOTAL_NPARMS = H5Z_SZIP_TOTAL_NPARMS();
/** szip filter - "User" parameter for option mask */
public static final int H5Z_SZIP_PARM_MASK = H5Z_SZIP_PARM_MASK();
/** szip filter - "User" parameter for pixels-per-block */
public static final int H5Z_SZIP_PARM_PPB = H5Z_SZIP_PARM_PPB();
/** szip filter - "Local" parameter for bits-per-pixel */
public static final int H5Z_SZIP_PARM_BPP = H5Z_SZIP_PARM_BPP();
/** szip filter - "Local" parameter for pixels-per-scanline */
public static final int H5Z_SZIP_PARM_PPS = H5Z_SZIP_PARM_PPS();
/** nbit filter - Number of parameters that users can set */
public static final int H5Z_NBIT_USER_NPARMS = H5Z_NBIT_USER_NPARMS();
/** scale offset filter - Number of parameters that users can set */
public static final int H5Z_SCALEOFFSET_USER_NPARMS = H5Z_SCALEOFFSET_USER_NPARMS();
/**
* Helper method to get H5FD_DIRECT VFD identifier using reflection.
* Returns H5I_INVALID_HID if Direct VFD is not available (e.g., on Windows or when H5_HAVE_DIRECT is not
* defined).
*
* @return the H5FD_DIRECT VFD identifier, or H5I_INVALID_HID if not available
*/
private static long getH5FD_DIRECT()
{
try {
// Use reflection to call H5FD_DIRECT_id_g() if it exists
// This method only exists if H5_HAVE_DIRECT is defined (Linux with Direct I/O)
java.lang.reflect.Method method =
org.hdfgroup.javahdf5.hdf5_h.class.getMethod("H5FD_DIRECT_id_g");
return (long)method.invoke(null);
}
catch (NoSuchMethodException e) {
// Method doesn't exist - Direct VFD not available on this platform
return H5I_INVALID_HID();
}
catch (Exception e) {
// Other error (shouldn't happen)
return H5I_INVALID_HID();
}
}
/**
* Helper method to get H5FD_MPIO VFD identifier using reflection.
* Returns H5I_INVALID_HID if MPIO VFD is not available (e.g., when parallel/MPI support is not enabled).
*
* @return the H5FD_MPIO VFD identifier, or H5I_INVALID_HID if not available
*/
private static long getH5FD_MPIO()
{
try {
// Use reflection to call H5FD_MPIO_id_g() if it exists
// This method only exists if parallel/MPI support is enabled
java.lang.reflect.Method method = org.hdfgroup.javahdf5.hdf5_h.class.getMethod("H5FD_MPIO_id_g");
return (long)method.invoke(null);
}
catch (NoSuchMethodException e) {
// Method doesn't exist - MPIO VFD not available (parallel not enabled)
return H5I_INVALID_HID();
}
catch (Exception e) {
// Other error (shouldn't happen)
return H5I_INVALID_HID();
}
}
/**
* Helper method to get H5FD_ROS3 VFD identifier using reflection.
* Returns H5I_INVALID_HID if ROS3 VFD is not available (e.g., when HDF5_ENABLE_ROS3_VFD is not enabled).
*
* @return the H5FD_ROS3 VFD identifier, or H5I_INVALID_HID if not available
*/
private static long getH5FD_ROS3()
{
try {
// Use reflection to call H5FD_ROS3_id_g() if it exists
// This method only exists if ROS3 VFD support is enabled (H5_HAVE_ROS3_VFD)
java.lang.reflect.Method method = org.hdfgroup.javahdf5.hdf5_h.class.getMethod("H5FD_ROS3_id_g");
return (long)method.invoke(null);
}
catch (NoSuchMethodException e) {
// Method doesn't exist - ROS3 VFD not available
return H5I_INVALID_HID();
}
catch (Exception e) {
// Other error (shouldn't happen)
return H5I_INVALID_HID();
}
}
/**
* Helper method to get H5FD_HDFS VFD identifier using reflection.
* Returns H5I_INVALID_HID if HDFS VFD is not available (e.g., when H5_HAVE_LIBHDFS is not defined).
*
* @return the H5FD_HDFS VFD identifier, or H5I_INVALID_HID if not available
*/
private static long getH5FD_HDFS()
{
try {
// Use reflection to call H5FD_HDFS_id_g() if it exists
// This method only exists if HDFS support is enabled (H5_HAVE_LIBHDFS)
java.lang.reflect.Method method = org.hdfgroup.javahdf5.hdf5_h.class.getMethod("H5FD_HDFS_id_g");
return (long)method.invoke(null);
}
catch (NoSuchMethodException e) {
// Method doesn't exist - HDFS VFD not available
return H5I_INVALID_HID();
}
catch (Exception e) {
// Other error (shouldn't happen)
return H5I_INVALID_HID();
}
}
/**
* Helper method to get H5FD_MIRROR VFD identifier using reflection.
* Returns H5I_INVALID_HID if Mirror VFD is not available (e.g., when H5_HAVE_MIRROR_VFD is not defined).
*
* @return the H5FD_MIRROR VFD identifier, or H5I_INVALID_HID if not available
*/
private static long getH5FD_MIRROR()
{
try {
// Use reflection to call H5FD_MIRROR_id_g() if it exists
// This method only exists if Mirror VFD support is enabled (H5_HAVE_MIRROR_VFD)
java.lang.reflect.Method method =
org.hdfgroup.javahdf5.hdf5_h.class.getMethod("H5FD_MIRROR_id_g");
return (long)method.invoke(null);
}
catch (NoSuchMethodException e) {
// Method doesn't exist - Mirror VFD not available
return H5I_INVALID_HID();
}
catch (Exception e) {
// Other error (shouldn't happen)
return H5I_INVALID_HID();
}
}
}
+1056
View File
@@ -0,0 +1,1056 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;
import hdf.hdf5lib.exceptions.HDF5Exception;
import hdf.hdf5lib.exceptions.HDF5JavaException;
/**
* \page HDFARRAY Java Array Conversion This is a class for handling multidimensional arrays for HDF.
* <p>
* The purpose is to allow the storage and retrieval of arbitrary array types containing scientific data.
* <p>
* The methods support the conversion of an array to and from Java to a one-dimensional array of bytes
* suitable for I/O by the C library. <p> This class heavily uses the
*
* @ref HDFNATIVE class to convert between Java and C representations.
*/
public class HDFArray {
private Object _theArray = null;
private ArrayDescriptor _desc = null;
private byte[] _barray = null;
// public HDFArray() {}
/**
* The input must be a Java Array (possibly multidimensional) of primitive numbers or sub-classes of
* Number. <p> The input is analysed to determine the number of dimensions and size of each dimension, as
* well as the type of the elements. <p> The description is saved in private variables, and used to
* convert data.
*
* @param anArray The array object.
* @exception hdf.hdf5lib.exceptions.HDF5JavaException object is not an array.
*/
public HDFArray(Object anArray) throws HDF5JavaException
{
if (anArray == null) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: array is null?: ");
}
Class tc = anArray.getClass();
if (tc.isArray() == false) {
/* exception: not an array */
HDF5JavaException ex = new HDF5JavaException("HDFArray: not an array?: ");
throw(ex);
}
_theArray = anArray;
_desc = new ArrayDescriptor(_theArray);
/* extra error checking -- probably not needed */
if (_desc == null) {
HDF5JavaException ex =
new HDF5JavaException("HDFArray: internal error: array description failed?: ");
throw(ex);
}
}
/**
* Allocate a one-dimensional array of bytes sufficient to store the array.
*
* @return A one-D array of bytes, filled with zeroes. The bytes are sufficient to hold the data of the
* Array passed
* to the constructor.
* @exception hdf.hdf5lib.exceptions.HDF5JavaException Allocation failed.
*/
public byte[] emptyBytes() throws HDF5JavaException
{
byte[] b = null;
if ((ArrayDescriptor.dims == 1) && (ArrayDescriptor.NT == 'B')) {
b = (byte[])_theArray;
}
else {
b = new byte[ArrayDescriptor.totalSize];
}
if (b == null) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: emptyBytes: allocation failed");
throw(ex);
}
return (b);
}
/**
* Given a Java array of numbers, convert it to a one-dimensional array of bytes in correct native order.
*
* @return A one-D array of bytes, constructed from the Array passed to the constructor.
* @exception hdf.hdf5lib.exceptions.HDF5JavaException the object not an array or other internal error.
*/
public byte[] byteify() throws HDF5JavaException
{
if (_barray != null) {
return _barray;
}
if (_theArray == null) {
/* exception: not an array */
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify not an array?: ");
throw(ex);
}
if (ArrayDescriptor.dims == 1) {
/* special case */
if (ArrayDescriptor.NT == 'B') {
/* really special case! */
_barray = (byte[])_theArray;
return _barray;
}
else {
try {
_barray = new byte[ArrayDescriptor.totalSize];
byte[] therow;
if (ArrayDescriptor.NT == 'I') {
ByteBuffer byteBuffer = ByteBuffer.allocate(ArrayDescriptor.dimlen[1] * Integer.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put((int[])_theArray);
therow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'S') {
ByteBuffer byteBuffer = ByteBuffer.allocate(ArrayDescriptor.dimlen[1] * Short.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
shortBuffer.put((short[])_theArray);
therow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'F') {
ByteBuffer byteBuffer = ByteBuffer.allocate(ArrayDescriptor.dimlen[1] * Float.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
floatBuffer.put((float[])_theArray);
therow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'J') {
ByteBuffer byteBuffer = ByteBuffer.allocate(ArrayDescriptor.dimlen[1] * Long.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
LongBuffer longBuffer = byteBuffer.asLongBuffer();
longBuffer.put((long[])_theArray);
therow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'D') {
ByteBuffer byteBuffer = ByteBuffer.allocate(ArrayDescriptor.dimlen[1] * Double.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
DoubleBuffer doubleBuffer = byteBuffer.asDoubleBuffer();
doubleBuffer.put((double[])_theArray);
therow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'L') {
if (ArrayDescriptor.className.equals("java.lang.Byte")) {
therow = ByteObjToByte((Byte[])_theArray);
}
else if (ArrayDescriptor.className.equals("java.lang.Integer")) {
therow = IntegerToByte((Integer[])_theArray);
}
else if (ArrayDescriptor.className.equals("java.lang.Short")) {
therow = ShortToByte((Short[])_theArray);
}
else if (ArrayDescriptor.className.equals("java.lang.Float")) {
therow = FloatObjToByte((Float[])_theArray);
}
else if (ArrayDescriptor.className.equals("java.lang.Double")) {
therow = DoubleObjToByte((Double[])_theArray);
}
else if (ArrayDescriptor.className.equals("java.lang.Long")) {
therow = LongObjToByte((Long[])_theArray);
}
else {
HDF5JavaException ex = new HDF5JavaException("HDFArray: unknown type of Object?");
throw(ex);
}
}
else {
HDF5JavaException ex = new HDF5JavaException("HDFArray: unknown type of data?");
throw(ex);
}
System.arraycopy(therow, 0, _barray, 0,
(ArrayDescriptor.dimlen[1] * ArrayDescriptor.NTsize));
return _barray;
}
catch (OutOfMemoryError err) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
throw(ex);
}
}
}
try {
_barray = new byte[ArrayDescriptor.totalSize];
}
catch (OutOfMemoryError err) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
throw(ex);
}
Object oo = _theArray;
int n = 0; /* the current byte */
int index = 0;
int i;
while (n < ArrayDescriptor.totalSize) {
oo = ArrayDescriptor.objs[0];
index = n / ArrayDescriptor.bytetoindex[0];
index %= ArrayDescriptor.dimlen[0];
for (i = 0; i < (ArrayDescriptor.dims); i++) {
index = n / ArrayDescriptor.bytetoindex[i];
index %= ArrayDescriptor.dimlen[i];
if (index == ArrayDescriptor.currentindex[i]) {
/* then use cached copy */
oo = ArrayDescriptor.objs[i];
}
else {
/* check range of index */
if (index > (ArrayDescriptor.dimlen[i] - 1)) {
throw new java.lang.IndexOutOfBoundsException("HDFArray: byteify index OOB?");
}
oo = java.lang.reflect.Array.get(oo, index);
ArrayDescriptor.currentindex[i] = index;
ArrayDescriptor.objs[i] = oo;
}
}
/* byte-ify */
byte arow[];
try {
if (ArrayDescriptor.NT == 'J') {
ByteBuffer byteBuffer =
ByteBuffer.allocate(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * Long.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
LongBuffer longBuffer = byteBuffer.asLongBuffer();
longBuffer.put((long[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
arow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'I') {
ByteBuffer byteBuffer =
ByteBuffer.allocate(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * Integer.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put((int[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
arow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'S') {
ByteBuffer byteBuffer =
ByteBuffer.allocate(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * Short.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
shortBuffer.put((short[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
arow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'B') {
arow = (byte[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1];
}
else if (ArrayDescriptor.NT == 'F') {
/* 32 bit float */
ByteBuffer byteBuffer =
ByteBuffer.allocate(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * Float.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
floatBuffer.put((float[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
arow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'D') {
/* 64 bit float */
ByteBuffer byteBuffer =
ByteBuffer.allocate(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * Double.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
DoubleBuffer doubleBuffer = byteBuffer.asDoubleBuffer();
doubleBuffer.put((double[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
arow = byteBuffer.array();
}
else if (ArrayDescriptor.NT == 'L') {
if (ArrayDescriptor.className.equals("java.lang.Byte")) {
arow = ByteObjToByte((Byte[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else if (ArrayDescriptor.className.equals("java.lang.Integer")) {
arow = IntegerToByte((Integer[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else if (ArrayDescriptor.className.equals("java.lang.Short")) {
arow = ShortToByte((Short[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else if (ArrayDescriptor.className.equals("java.lang.Float")) {
arow = FloatObjToByte((Float[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else if (ArrayDescriptor.className.equals("java.lang.Double")) {
arow = DoubleObjToByte((Double[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else if (ArrayDescriptor.className.equals("java.lang.Long")) {
arow = LongObjToByte((Long[])ArrayDescriptor.objs[ArrayDescriptor.dims - 1]);
}
else {
HDF5JavaException ex =
new HDF5JavaException("HDFArray: byteify Object type not implemented?");
throw(ex);
}
}
else {
HDF5JavaException ex =
new HDF5JavaException("HDFArray: byteify unknown type not implemented?");
throw(ex);
}
System.arraycopy(arow, 0, _barray, n,
(ArrayDescriptor.dimlen[ArrayDescriptor.dims] * ArrayDescriptor.NTsize));
n += ArrayDescriptor.bytetoindex[ArrayDescriptor.dims - 1];
}
catch (OutOfMemoryError err) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: byteify array too big?");
throw(ex);
}
}
/* assert: the whole array is completed--currentindex should == len - 1 */
/* error checks */
if (n < ArrayDescriptor.totalSize) {
throw new java.lang.InternalError(
new String("HDFArray::byteify: Panic didn't complete all input data: n= " + n +
" size = " + ArrayDescriptor.totalSize));
}
for (i = 0; i < ArrayDescriptor.dims; i++) {
if (ArrayDescriptor.currentindex[i] != ArrayDescriptor.dimlen[i] - 1) {
throw new java.lang.InternalError(new String("Panic didn't complete all data: currentindex[" +
i + "] = " + ArrayDescriptor.currentindex[i] +
" (should be " +
(ArrayDescriptor.dimlen[i] - 1) + " ?)"));
}
}
return _barray;
}
/**
* Given a one-dimensional array of bytes representing numbers, convert it to a java array of the shape
* and size passed to the constructor.
*
* @param bytes The bytes to construct the Array.
* @return An Array (possibly multidimensional) of primitive or number objects.
* @exception hdf.hdf5lib.exceptions.HDF5JavaException the object not an array or other internal error.
*/
public Object arrayify(byte[] bytes) throws HDF5JavaException
{
if (_theArray == null) {
/* exception: not an array */
HDF5JavaException ex = new HDF5JavaException("arrayify: not an array?: ");
throw(ex);
}
if (java.lang.reflect.Array.getLength(bytes) != ArrayDescriptor.totalSize) {
/* exception: array not right size */
HDF5JavaException ex = new HDF5JavaException("arrayify: array is wrong size?: ");
throw(ex);
}
_barray = bytes; /* hope that the bytes are correct.... */
Object oo = _theArray;
int n = 0; /* the current byte */
int m = 0; /* the current array index */
int index = 0;
int i;
Object flattenedArray = null;
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(_barray);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // Set byte order to little-endian
switch (ArrayDescriptor.NT) {
case 'J': {
// Calculate the size of the new long array
int longArraySize = _barray.length / Long.BYTES;
long[] flatArray = new long[longArraySize];
// Populate the long array
for (i = 0; i < longArraySize; i++) {
flatArray[i] = byteBuffer.getLong();
}
flattenedArray = (Object)flatArray;
} break;
case 'S': {
// Calculate the size of the new short array
int shortArraySize = _barray.length / Short.BYTES;
short[] flatArray = new short[shortArraySize];
// Populate the short array
for (i = 0; i < shortArraySize; i++) {
flatArray[i] = byteBuffer.getShort();
}
flattenedArray = (Object)flatArray;
} break;
case 'I': {
// Calculate the size of the new int array
int intArraySize = _barray.length / Integer.BYTES;
int[] flatArray = new int[intArraySize];
// Populate the int array
for (i = 0; i < intArraySize; i++) {
flatArray[i] = byteBuffer.getInt();
}
flattenedArray = (Object)flatArray;
} break;
case 'F': {
// Calculate the size of the new float array
int floatArraySize = _barray.length / Float.BYTES;
float[] flatArray = new float[floatArraySize];
// Populate the float array
for (i = 0; i < floatArraySize; i++) {
flatArray[i] = byteBuffer.getFloat();
}
flattenedArray = (Object)flatArray;
} break;
case 'D': {
// Calculate the size of the new double array
int doubleArraySize = _barray.length / Double.BYTES;
double[] flatArray = new double[doubleArraySize];
// Populate the double array
for (i = 0; i < doubleArraySize; i++) {
flatArray[i] = byteBuffer.getDouble();
}
flattenedArray = (Object)flatArray;
} break;
case 'B':
flattenedArray = (Object)_barray;
break;
case 'L': {
if (ArrayDescriptor.className.equals("java.lang.Byte"))
flattenedArray = (Object)ByteToByteObj(_barray);
else if (ArrayDescriptor.className.equals("java.lang.Short"))
flattenedArray = (Object)ByteToShort(_barray);
else if (ArrayDescriptor.className.equals("java.lang.Integer"))
flattenedArray = (Object)ByteToInteger(_barray);
else if (ArrayDescriptor.className.equals("java.lang.Long"))
flattenedArray = (Object)ByteToLongObj(_barray);
else if (ArrayDescriptor.className.equals("java.lang.Float"))
flattenedArray = (Object)ByteToFloatObj(_barray);
else if (ArrayDescriptor.className.equals("java.lang.Double"))
flattenedArray = (Object)ByteToDoubleObj(_barray);
else {
HDF5JavaException ex =
new HDF5JavaException("HDFArray: unsupported Object type: " + ArrayDescriptor.NT);
throw(ex);
}
break;
} // end of statement for arrays of boxed objects
default:
HDF5JavaException ex =
new HDF5JavaException("HDFArray: unknown or unsupported type: " + ArrayDescriptor.NT);
throw(ex);
} // end of switch statement for arrays of primitives
while (n < ArrayDescriptor.totalSize) {
oo = ArrayDescriptor.objs[0];
index = n / ArrayDescriptor.bytetoindex[0];
index %= ArrayDescriptor.dimlen[0];
for (i = 0; i < (ArrayDescriptor.dims); i++) {
index = n / ArrayDescriptor.bytetoindex[i];
index %= ArrayDescriptor.dimlen[i];
if (index == ArrayDescriptor.currentindex[i]) {
/* then use cached copy */
oo = ArrayDescriptor.objs[i];
}
else {
/* check range of index */
if (index > (ArrayDescriptor.dimlen[i] - 1)) {
System.out.println("out of bounds?");
return null;
}
oo = java.lang.reflect.Array.get(oo, index);
ArrayDescriptor.currentindex[i] = index;
ArrayDescriptor.objs[i] = oo;
}
}
/* array-ify */
try {
Object arow = null;
int mm = m + ArrayDescriptor.dimlen[ArrayDescriptor.dims];
switch (ArrayDescriptor.NT) {
case 'B':
arow = (Object)Arrays.copyOfRange((byte[])flattenedArray, m, mm);
break;
case 'S':
arow = (Object)Arrays.copyOfRange((short[])flattenedArray, m, mm);
break;
case 'I':
arow = (Object)Arrays.copyOfRange((int[])flattenedArray, m, mm);
break;
case 'J':
arow = (Object)Arrays.copyOfRange((long[])flattenedArray, m, mm);
break;
case 'F':
arow = (Object)Arrays.copyOfRange((float[])flattenedArray, m, mm);
break;
case 'D':
arow = (Object)Arrays.copyOfRange((double[])flattenedArray, m, mm);
break;
case 'L': {
if (ArrayDescriptor.className.equals("java.lang.Byte"))
arow = (Object)Arrays.copyOfRange((Byte[])flattenedArray, m, mm);
else if (ArrayDescriptor.className.equals("java.lang.Short"))
arow = (Object)Arrays.copyOfRange((Short[])flattenedArray, m, mm);
else if (ArrayDescriptor.className.equals("java.lang.Integer"))
arow = (Object)Arrays.copyOfRange((Integer[])flattenedArray, m, mm);
else if (ArrayDescriptor.className.equals("java.lang.Long"))
arow = (Object)Arrays.copyOfRange((Long[])flattenedArray, m, mm);
else if (ArrayDescriptor.className.equals("java.lang.Float"))
arow = (Object)Arrays.copyOfRange((Float[])flattenedArray, m, mm);
else if (ArrayDescriptor.className.equals("java.lang.Double"))
arow = (Object)Arrays.copyOfRange((Double[])flattenedArray, m, mm);
else {
HDF5JavaException ex =
new HDF5JavaException("HDFArray: unsupported Object type: " + ArrayDescriptor.NT);
throw(ex);
}
break;
} // end of statement for arrays of boxed numerics
} // end of switch statement for arrays of primitives
if (ArrayDescriptor.dims > 1) {
java.lang.reflect.Array.set(ArrayDescriptor.objs[ArrayDescriptor.dims - 2],
(ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1]),
arow);
}
n += ArrayDescriptor.bytetoindex[ArrayDescriptor.dims - 1];
ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1]++;
m = mm;
}
catch (OutOfMemoryError err) {
HDF5JavaException ex = new HDF5JavaException("HDFArray: arrayify array too big?");
throw(ex);
}
}
/* assert: the whole array is completed--currentindex should == len - 1 */
/* error checks */
if (n < ArrayDescriptor.totalSize) {
throw new java.lang.InternalError(
new String("HDFArray::arrayify Panic didn't complete all input data: n= " + n +
" size = " + ArrayDescriptor.totalSize));
}
for (i = 0; i <= ArrayDescriptor.dims - 2; i++) {
if (ArrayDescriptor.currentindex[i] != ArrayDescriptor.dimlen[i] - 1) {
throw new java.lang.InternalError(
new String("HDFArray::arrayify Panic didn't complete all data: currentindex[" + i +
"] = " + ArrayDescriptor.currentindex[i] + " (should be " +
(ArrayDescriptor.dimlen[i] - 1) + "?"));
}
}
if (ArrayDescriptor.currentindex[ArrayDescriptor.dims - 1] !=
ArrayDescriptor.dimlen[ArrayDescriptor.dims - 1]) {
throw new java.lang.InternalError(new String(
"HDFArray::arrayify Panic didn't complete all data: currentindex[" + i + "] = " +
ArrayDescriptor.currentindex[i] + " (should be " + (ArrayDescriptor.dimlen[i]) + "?"));
}
return _theArray;
}
public static byte[] intToBytes(int value)
{
ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
// Put the integer value into the buffer
byteBuffer.putInt(value);
// System.out.println("intToBytes: int= " + value + " bytes= " + Arrays.toString(byteBuffer.array()));
// Return the backing byte array
return byteBuffer.array();
}
public static int bytesToInt(byte[] bytes) throws HDF5Exception
{
if (bytes.length != Integer.BYTES) {
throw new HDF5Exception("Invalid byte array length for an integer: " + bytes.length);
}
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
// Read and return the integer value from the buffer
return byteBuffer.getInt();
}
public static byte[] IntegerToByte(Integer in[])
{
int nelems = java.lang.reflect.Array.getLength(in);
byte[] byteArray = new byte[nelems * Integer.BYTES];
for (int i = 0; i < nelems; i++) {
int out = in[i].intValue();
byte[] tmp = intToBytes(out);
// System.out.println("IntegerToByte: " + i + " of " + nelems + " int= " + out + " bytes= " +
// Arrays.toString(tmp));
System.arraycopy(tmp, 0, byteArray, i * Integer.BYTES, Integer.BYTES);
}
return byteArray;
}
public static Integer[] ByteToInteger(byte[] bin)
{
int nelems = bin.length / Integer.BYTES;
byte in[] = new byte[Integer.BYTES];
Integer[] out = new Integer[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Integer.BYTES, in, 0, Integer.BYTES);
out[i] = Integer.valueOf(bytesToInt(in));
}
return out;
}
public static byte[] shortToBytes(short value)
{
ByteBuffer byteBuffer = ByteBuffer.allocate(Short.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
// Put the short value into the buffer
byteBuffer.putShort(value);
// Return the backing byte array
return byteBuffer.array();
}
public static short bytesToShort(byte[] bytes) throws HDF5Exception
{
if (bytes.length != Short.BYTES) {
throw new HDF5Exception("Invalid byte array length for an short: " + bytes.length);
}
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
// Read and return the short value from the buffer
return byteBuffer.getShort();
}
public static byte[] ShortToByte(Short in[])
{
int nelems = java.lang.reflect.Array.getLength(in);
byte[] byteArray = new byte[nelems * Short.BYTES];
for (int i = 0; i < nelems; i++) {
short out = in[i].shortValue();
System.arraycopy(shortToBytes(out), 0, byteArray, i * Short.BYTES, Short.BYTES);
}
return byteArray;
}
public static Short[] ByteToShort(byte[] bin)
{
int nelems = bin.length / Short.BYTES;
byte in[] = new byte[Short.BYTES];
Short[] out = new Short[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Short.BYTES, in, 0, Short.BYTES);
out[i] = Short.valueOf(bytesToShort(in));
}
return out;
}
public static byte[] ByteObjToByte(Byte in[])
{
int nelems = java.lang.reflect.Array.getLength((Object)in);
byte[] out = new byte[nelems];
for (int i = 0; i < nelems; i++) {
out[i] = in[i].byteValue();
}
return out;
}
public static Byte[] ByteToByteObj(byte[] bin)
{
int nelems = java.lang.reflect.Array.getLength((Object)bin);
Byte[] out = new Byte[nelems];
for (int i = 0; i < nelems; i++) {
out[i] = Byte.valueOf(bin[0]);
}
return out;
}
public static Byte[] ByteToByteObj(int start, int len, byte[] bin)
{
Byte[] out = new Byte[len];
for (int i = 0; i < len; i++) {
out[i] = Byte.valueOf(bin[0]);
}
return out;
}
public static byte[] floatToBytes(float value)
{
ByteBuffer byteBuffer = ByteBuffer.allocate(Float.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
// Put the float value into the buffer
byteBuffer.putFloat(value);
// Return the backing byte array
return byteBuffer.array();
}
public static float bytesToFloat(byte[] bytes) throws HDF5Exception
{
if (bytes.length != Float.BYTES) {
throw new HDF5Exception("Invalid byte array length for an float: " + bytes.length);
}
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
// Read and return the float value from the buffer
return byteBuffer.getFloat();
}
public static byte[] FloatObjToByte(Float in[])
{
int nelems = java.lang.reflect.Array.getLength((Object)in);
byte[] byteArray = new byte[nelems * Float.BYTES];
for (int i = 0; i < nelems; i++) {
float out = in[i].floatValue();
System.arraycopy(floatToBytes(out), 0, byteArray, i * Float.BYTES, Float.BYTES);
}
return byteArray;
}
public static Float[] ByteToFloatObj(byte[] bin)
{
int nelems = bin.length / Float.BYTES;
byte in[] = new byte[Float.BYTES];
Float[] out = new Float[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Float.BYTES, in, 0, Float.BYTES);
out[i] = Float.valueOf(bytesToFloat(in));
}
return out;
}
public static byte[] doubleToBytes(double value)
{
// Allocate a ByteBuffer with a capacity of 8 bytes (for a double)
ByteBuffer byteBuffer = ByteBuffer.allocate(Double.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
// Put the double value into the buffer
byteBuffer.putDouble(value);
// Return the backing byte array
return byteBuffer.array();
}
public static double bytesToDouble(byte[] bytes) throws HDF5Exception
{
if (bytes.length != Double.BYTES) {
throw new HDF5Exception("Invalid byte array length for an double: " + bytes.length);
}
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
// Read and return the double value from the buffer
return byteBuffer.getDouble();
}
public static byte[] DoubleToByte(Double in[])
{
int nelems = java.lang.reflect.Array.getLength(in);
byte[] byteArray = new byte[nelems * Double.BYTES];
for (int i = 0; i < nelems; i++) {
double out = in[i].doubleValue();
System.arraycopy(doubleToBytes(out), 0, byteArray, i * Double.BYTES, Double.BYTES);
}
return byteArray;
}
public static Double[] ByteToDouble(byte[] bin)
{
int nelems = bin.length / Double.BYTES;
byte in[] = new byte[Double.BYTES];
Double[] out = new Double[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Double.BYTES, in, 0, Double.BYTES);
out[i] = Double.valueOf(bytesToDouble(in));
}
return out;
}
public static byte[] DoubleObjToByte(Double in[])
{
int nelems = java.lang.reflect.Array.getLength((Object)in);
byte[] byteArray = new byte[nelems * Double.BYTES];
for (int i = 0; i < nelems; i++) {
double out = in[i].doubleValue();
System.arraycopy(doubleToBytes(out), 0, byteArray, i * Double.BYTES, Double.BYTES);
}
return byteArray;
}
public static Double[] ByteToDoubleObj(byte[] bin)
{
int nelems = bin.length / Double.BYTES;
byte in[] = new byte[Double.BYTES];
Double[] out = new Double[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Double.BYTES, in, 0, Double.BYTES);
out[i] = Double.valueOf(bytesToDouble(in));
}
return out;
}
public static byte[] longToBytes(long value)
{
ByteBuffer byteBuffer = ByteBuffer.allocate(Long.BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
// Put the long value into the buffer
byteBuffer.putLong(value);
// Return the backing byte array
return byteBuffer.array();
}
public static long bytesToLong(byte[] bytes) throws HDF5Exception
{
if (bytes.length != Long.BYTES) {
throw new HDF5Exception("Invalid byte array length for an long: " + bytes.length);
}
// Wrap the byte array in a ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
// Read and return the long value from the buffer
return byteBuffer.getLong();
}
public static byte[] LongObjToByte(Long in[])
{
int nelems = java.lang.reflect.Array.getLength((Object)in);
byte[] byteArray = new byte[nelems * Long.BYTES];
for (int i = 0; i < nelems; i++) {
long out = in[i].longValue();
System.arraycopy(longToBytes(out), 0, byteArray, i * Long.BYTES, Long.BYTES);
}
return byteArray;
}
public static Long[] ByteToLongObj(byte[] bin)
{
int nelems = bin.length / Long.BYTES;
byte in[] = new byte[Long.BYTES];
Long[] out = new Long[nelems];
for (int i = 0; i < nelems; i++) {
System.arraycopy(bin, i * Long.BYTES, in, 0, Long.BYTES);
out[i] = Long.valueOf(bytesToLong(in));
}
return out;
}
}
/**
* This private class is used by HDFArray to discover the shape and type of an arbitrary array.
* <p>
* We use java.lang.reflection here.
*/
class ArrayDescriptor {
static String theType = "";
static Class theClass = null;
static int[] dimlen = null;
static int[] dimstart = null;
static int[] currentindex = null;
static int[] bytetoindex = null;
static int totalSize = 0;
static int totalElements = 0;
static Object[] objs = null;
static char NT = ' '; /* must be B,S,I,L,F,D, else error */
static int NTsize = 0;
static int dims = 0;
static String className;
public ArrayDescriptor(Object anArray) throws HDF5JavaException
{
Class tc = anArray.getClass();
if (tc.isArray() == false) {
/* exception: not an array */
HDF5JavaException ex = new HDF5JavaException("ArrayDescriptor: not an array?: ");
throw(ex);
}
theClass = tc;
/*
* parse the type descriptor to discover the shape of the array
*/
String ss = tc.toString();
theType = ss;
int n = 6;
dims = 0;
char c = ' ';
while (n < ss.length()) {
c = ss.charAt(n);
n++;
if (c == '[') {
dims++;
}
}
String css = ss.substring(ss.lastIndexOf('[') + 1);
Class compC = tc.getComponentType();
String cs = compC.toString();
NT = c; /* must be B,S,I,L,F,D, else error */
if (NT == 'B') {
NTsize = 1;
}
else if (NT == 'S') {
NTsize = 2;
}
else if ((NT == 'I') || (NT == 'F')) {
NTsize = 4;
}
else if ((NT == 'J') || (NT == 'D')) {
NTsize = 8;
}
else if (css.startsWith("Ljava.lang.Byte")) {
NT = 'L';
className = "java.lang.Byte";
NTsize = 1;
}
else if (css.startsWith("Ljava.lang.Short")) {
NT = 'L';
className = "java.lang.Short";
NTsize = 2;
}
else if (css.startsWith("Ljava.lang.Integer")) {
NT = 'L';
className = "java.lang.Integer";
NTsize = 4;
}
else if (css.startsWith("Ljava.lang.Float")) {
NT = 'L';
className = "java.lang.Float";
NTsize = 4;
}
else if (css.startsWith("Ljava.lang.Double")) {
NT = 'L';
className = "java.lang.Double";
NTsize = 8;
}
else if (css.startsWith("Ljava.lang.Long")) {
NT = 'L';
className = "java.lang.Long";
NTsize = 8;
}
else if (css.startsWith("Ljava.lang.String")) {
NT = 'L';
className = "java.lang.String";
NTsize = 1;
throw new HDF5JavaException(
new String("ArrayDesciptor: Warning: String array not fully supported yet"));
}
else {
/*
* exception: not a numeric type
*/
throw new HDF5JavaException(
new String("ArrayDesciptor: Error: array is not numeric (type is " + css + ") ?"));
}
/* fill in the table */
dimlen = new int[dims + 1];
dimstart = new int[dims + 1];
currentindex = new int[dims + 1];
bytetoindex = new int[dims + 1];
objs = new Object[dims + 1];
Object o = anArray;
objs[0] = o;
dimlen[0] = 1;
dimstart[0] = 0;
currentindex[0] = 0;
int elements = 1;
int i;
for (i = 1; i <= dims; i++) {
dimlen[i] = java.lang.reflect.Array.getLength((Object)o);
o = java.lang.reflect.Array.get((Object)o, 0);
objs[i] = o;
dimstart[i] = 0;
currentindex[i] = 0;
elements *= dimlen[i];
}
totalElements = elements;
int j;
int dd;
bytetoindex[dims] = NTsize;
for (i = dims; i >= 0; i--) {
dd = NTsize;
for (j = i; j < dims; j++) {
dd *= dimlen[j + 1];
}
bytetoindex[i] = dd;
}
totalSize = bytetoindex[0];
}
/**
* Debug dump
*/
public void dumpInfo()
{
System.out.println("Type: " + theType);
System.out.println("Class: " + theClass);
System.out.println("NT: " + NT + " NTsize: " + NTsize);
System.out.println("Array has " + dims + " dimensions (" + totalSize + " bytes, " + totalElements +
" elements)");
int i;
for (i = 0; i <= dims; i++) {
Class tc = objs[i].getClass();
String ss = tc.toString();
System.out.println(i + ": start " + dimstart[i] + ": len " + dimlen[i] + " current " +
currentindex[i] + " bytetoindex " + bytetoindex[i] + " object " + objs[i] +
" otype " + ss);
}
}
}
+2171
View File
@@ -0,0 +1,2171 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import hdf.hdf5lib.exceptions.HDF5JavaException;
import org.hdfgroup.javahdf5.hvl_t;
/**
* Utility class for converting between Java ArrayList arrays and HDF5 hvl_t structures
* for variable-length (VL) data operations in the FFM implementation.
*/
public class VLDataConverter {
// Logging removed for compilation simplicity - can add back if needed
/**
* Container for raw VL data copied from HDF5-managed memory.
* This prevents any access to HDF5 memory after H5Treclaim.
*/
private static class RawVLData {
public final byte[] data;
public final int length;
public RawVLData(byte[] data, int length)
{
this.data = data;
this.length = length;
}
}
/**
* Convert Java ArrayList array to HDF5 hvl_t MemorySegment array
*
* @param javaData Array of ArrayLists containing the variable-length data
* @param arena Arena for memory allocation
* @return MemorySegment containing hvl_t array
* @throws HDF5JavaException if conversion fails
*/
public static MemorySegment convertToHVL(ArrayList[] javaData, Arena arena) throws HDF5JavaException
{
if (javaData == null || javaData.length == 0) {
throw new HDF5JavaException("Input data array is null or empty");
}
MemorySegment hvlArray = hvl_t.allocateArray(javaData.length, arena);
for (int i = 0; i < javaData.length; i++) {
MemorySegment hvlElement = hvl_t.asSlice(hvlArray, i);
convertSingleElement(javaData[i], hvlElement, arena);
}
return hvlArray;
}
/**
* Convert HDF5 hvl_t MemorySegment array back to Java ArrayList array.
* Uses two-phase approach: immediately extract all raw data from HDF5 memory,
* then process the copied data to prevent access after H5Treclaim.
*
* @param hvlArray MemorySegment containing hvl_t array
* @param arrayLength Number of elements in the array
* @param elementType HDF5 datatype of the elements (for type inference)
* @return Array of ArrayLists
* @throws HDF5JavaException if conversion fails
*/
public static ArrayList[] convertFromHVL(MemorySegment hvlArray, int arrayLength, long elementType)
throws HDF5JavaException
{
if (hvlArray == null) {
throw new HDF5JavaException("Input hvl_t array is null");
}
ArrayList[] result = new ArrayList[arrayLength];
RawVLData[] rawDataArray = new RawVLData[arrayLength];
boolean isStringType = isStringType(elementType) || isVLOfStrings(elementType);
for (int i = 0; i < arrayLength; i++) {
MemorySegment hvlElement = hvl_t.asSlice(hvlArray, i);
long len = hvl_t.len(hvlElement);
MemorySegment dataPtr = hvl_t.p(hvlElement);
if (len == 0 || dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
rawDataArray[i] = new RawVLData(new byte[0], 0);
}
else {
if (isStringType) {
// For VL strings, hvl_t.p contains a char* directly
try {
ArrayList<String> directResult = new ArrayList<>(1);
if (dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
directResult.add("");
}
else {
String str = dataPtr.getString(0, java.nio.charset.StandardCharsets.UTF_8);
directResult.add(str);
}
result[i] = directResult;
rawDataArray[i] = null;
}
catch (Exception e) {
rawDataArray[i] = copyStringVLDataImmediately(dataPtr, (int)len);
}
}
else {
rawDataArray[i] = copyRawVLData(dataPtr, (int)len, elementType);
}
}
}
long baseElementType = elementType;
boolean needToCloseBaseType = false;
try {
if (isVLType(elementType)) {
baseElementType = getVLBaseType(elementType);
needToCloseBaseType = true;
}
}
catch (Exception e) {
}
try {
for (int i = 0; i < arrayLength; i++) {
if (rawDataArray[i] != null) {
result[i] = convertRawDataToArrayList(rawDataArray[i], baseElementType);
}
}
}
finally {
if (needToCloseBaseType && baseElementType != elementType) {
try {
H5.H5Tclose(baseElementType);
}
catch (Exception e) {
}
}
}
return result;
}
/**
* Convert a single ArrayList to hvl_t structure
*/
private static void convertSingleElement(ArrayList<?> list, MemorySegment hvlElement, Arena arena)
throws HDF5JavaException
{
if (list == null) {
// Empty VL element
hvl_t.len(hvlElement, 0);
hvl_t.p(hvlElement, MemorySegment.NULL);
return;
}
int size = list.size();
hvl_t.len(hvlElement, size);
if (size == 0) {
hvl_t.p(hvlElement, MemorySegment.NULL);
return;
}
Object firstElement = list.get(0);
Class<?> elementType = firstElement.getClass();
if (elementType == Integer.class) {
MemorySegment dataArray = convertIntegerVL(list, arena);
hvl_t.p(hvlElement, dataArray);
}
else if (elementType == Double.class) {
MemorySegment dataArray = convertDoubleVL(list, arena);
hvl_t.p(hvlElement, dataArray);
}
else if (elementType == String.class) {
MemorySegment dataArray = convertStringVL(list, arena);
hvl_t.p(hvlElement, dataArray);
}
else if (elementType == byte[].class) {
MemorySegment dataArray = convertByteArrayVL(list, arena);
hvl_t.p(hvlElement, dataArray);
}
else if (firstElement instanceof ArrayList) {
// Nested VL structure
MemorySegment dataArray = convertNestedVL(list, arena);
hvl_t.p(hvlElement, dataArray);
}
else {
throw new HDF5JavaException("Unsupported ArrayList element type: " + elementType.getName());
}
}
/**
* Convert ArrayList<Integer> to native int array
*/
@SuppressWarnings("unchecked")
private static MemorySegment convertIntegerVL(ArrayList<?> list, Arena arena)
{
ArrayList<Integer> intList = (ArrayList<Integer>)list;
MemorySegment dataArray = arena.allocate(ValueLayout.JAVA_INT, intList.size());
for (int i = 0; i < intList.size(); i++) {
dataArray.setAtIndex(ValueLayout.JAVA_INT, i, intList.get(i));
}
return dataArray;
}
/**
* Convert ArrayList<Double> to native double array
*/
@SuppressWarnings("unchecked")
private static MemorySegment convertDoubleVL(ArrayList<?> list, Arena arena)
{
ArrayList<Double> doubleList = (ArrayList<Double>)list;
MemorySegment dataArray = arena.allocate(ValueLayout.JAVA_DOUBLE, doubleList.size());
for (int i = 0; i < doubleList.size(); i++) {
dataArray.setAtIndex(ValueLayout.JAVA_DOUBLE, i, doubleList.get(i));
}
return dataArray;
}
/**
* Convert ArrayList<String> to native array format for HDF5 array datatypes
* For array datatypes, each ArrayList<String> becomes a fixed-size array of string pointers
*/
@SuppressWarnings("unchecked")
private static MemorySegment convertStringVL(ArrayList<?> list, Arena arena)
{
ArrayList<String> stringList = (ArrayList<String>)list;
// For array datatypes containing strings, create a packed array of string pointers
// This is different from VL strings - array types have fixed size arrays
MemorySegment stringArray = arena.allocate(ValueLayout.ADDRESS, stringList.size());
for (int i = 0; i < stringList.size(); i++) {
String str = stringList.get(i);
if (str != null) {
MemorySegment stringSegment = arena.allocateFrom(str, StandardCharsets.UTF_8);
stringArray.setAtIndex(ValueLayout.ADDRESS, i, stringSegment);
}
else {
stringArray.setAtIndex(ValueLayout.ADDRESS, i, MemorySegment.NULL);
}
}
return stringArray;
}
/**
* Convert ArrayList<byte[]> to native array format for HDF5
* Used for VL reference data where each element is a byte array (reference)
*/
@SuppressWarnings("unchecked")
private static MemorySegment convertByteArrayVL(ArrayList<?> list, Arena arena)
{
ArrayList<byte[]> byteArrayList = (ArrayList<byte[]>)list;
// Calculate total size needed for all byte arrays
long totalSize = 0;
for (byte[] array : byteArrayList) {
if (array != null) {
totalSize += array.length;
}
}
if (totalSize == 0) {
return MemorySegment.NULL;
}
// For VL reference data, we need to create a contiguous array of all bytes
// References are typically fixed-size, so we can pack them sequentially
MemorySegment dataArray = arena.allocate(totalSize);
long offset = 0;
for (byte[] array : byteArrayList) {
if (array != null && array.length > 0) {
MemorySegment arraySegment = MemorySegment.ofArray(array);
dataArray.asSlice(offset, array.length).copyFrom(arraySegment);
offset += array.length;
}
}
return dataArray;
}
/**
* Convert ArrayList array to array datatype buffer (not hvl_t)
* Used for H5T_ARRAY datatypes where each element is a fixed-size array
*/
public static MemorySegment convertArrayDatatype(ArrayList[] data, long mem_type_id, Arena arena)
throws HDF5JavaException
{
try {
// Get the array type information
long baseTypeId = org.hdfgroup.javahdf5.hdf5_h.H5Tget_super(mem_type_id);
if (baseTypeId < 0) {
throw new HDF5JavaException("Failed to get array base type");
}
// Get array dimensions
int ndims = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_ndims(mem_type_id);
if (ndims != 1) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Only 1D arrays are supported, got " + ndims + "D");
}
// Get the array size (number of elements per array)
MemorySegment dims = arena.allocate(ValueLayout.JAVA_LONG, 1);
int result = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_dims2(mem_type_id, dims);
if (result < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to get array dimensions");
}
int arraySize = (int)dims.get(ValueLayout.JAVA_LONG, 0);
// Check if the base type is variable-length string
int isVLStringResult = org.hdfgroup.javahdf5.hdf5_h.H5Tis_variable_str(baseTypeId);
boolean isVLString = isVLStringResult > 0;
if (isVLString) {
// Each entry in data[] is an ArrayList<String> with arraySize elements
// Pack as array of string pointers
MemorySegment buffer = arena.allocate(ValueLayout.ADDRESS, data.length * arraySize);
for (int i = 0; i < data.length; i++) {
ArrayList<String> stringArray = (ArrayList<String>)data[i];
if (stringArray.size() != arraySize) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Array element " + i + " has " + stringArray.size() +
" elements, expected " + arraySize);
}
// Pack string pointers for this array element
for (int j = 0; j < arraySize; j++) {
String str = stringArray.get(j);
if (str != null) {
MemorySegment stringSegment = arena.allocateFrom(str, StandardCharsets.UTF_8);
buffer.setAtIndex(ValueLayout.ADDRESS, i * arraySize + j, stringSegment);
}
else {
buffer.setAtIndex(ValueLayout.ADDRESS, i * arraySize + j, MemorySegment.NULL);
}
}
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return buffer;
}
else {
// Check for other supported base types
int baseTypeClass = org.hdfgroup.javahdf5.hdf5_h.H5Tget_class(baseTypeId);
if (baseTypeClass == HDF5Constants.H5T_INTEGER) {
// Support integer arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_INT, data.length * arraySize);
for (int i = 0; i < data.length; i++) {
ArrayList<Integer> intArray = (ArrayList<Integer>)data[i];
if (intArray.size() != arraySize) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Array element " + i + " has " + intArray.size() +
" elements, expected " + arraySize);
}
for (int j = 0; j < arraySize; j++) {
Integer val = intArray.get(j);
buffer.setAtIndex(ValueLayout.JAVA_INT, i * arraySize + j, val != null ? val : 0);
}
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return buffer;
}
else if (baseTypeClass == HDF5Constants.H5T_FLOAT) {
// Support double arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_DOUBLE, data.length * arraySize);
for (int i = 0; i < data.length; i++) {
ArrayList<Double> doubleArray = (ArrayList<Double>)data[i];
if (doubleArray.size() != arraySize) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Array element " + i + " has " + doubleArray.size() +
" elements, expected " + arraySize);
}
for (int j = 0; j < arraySize; j++) {
Double val = doubleArray.get(j);
buffer.setAtIndex(ValueLayout.JAVA_DOUBLE, i * arraySize + j,
val != null ? val : 0.0);
}
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return buffer;
}
else if (baseTypeClass == HDF5Constants.H5T_ENUM) {
// Support enum arrays - treat enums as integers
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_INT, data.length * arraySize);
for (int i = 0; i < data.length; i++) {
ArrayList<Integer> enumArray = (ArrayList<Integer>)data[i];
if (enumArray.size() != arraySize) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Array element " + i + " has " + enumArray.size() +
" elements, expected " + arraySize);
}
for (int j = 0; j < arraySize; j++) {
Integer val = enumArray.get(j);
buffer.setAtIndex(ValueLayout.JAVA_INT, i * arraySize + j, val != null ? val : 0);
}
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return buffer;
}
else {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Unsupported array base type for FFM conversion: " +
baseTypeClass);
}
}
}
catch (Exception e) {
if (e instanceof HDF5JavaException) {
throw e;
}
throw new HDF5JavaException("Array datatype conversion failed: " + e.getMessage());
}
}
/**
* Read array datatype data from HDF5 attribute (not hvl_t)
* Used for H5T_ARRAY datatypes where each element is a fixed-size array
*/
public static ArrayList[] readArrayDatatype(long attr_id, long mem_type_id, int count, Arena arena)
throws HDF5JavaException
{
try {
// Get the array type information
long baseTypeId = org.hdfgroup.javahdf5.hdf5_h.H5Tget_super(mem_type_id);
if (baseTypeId < 0) {
throw new HDF5JavaException("Failed to get array base type");
}
// Get array dimensions
int ndims = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_ndims(mem_type_id);
if (ndims != 1) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Only 1D arrays are supported, got " + ndims + "D");
}
// Get the array size (number of elements per array)
MemorySegment dims = arena.allocate(ValueLayout.JAVA_LONG, 1);
int result = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_dims2(mem_type_id, dims);
if (result < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to get array dimensions");
}
int arraySize = (int)dims.get(ValueLayout.JAVA_LONG, 0);
// Check if the base type is variable-length string
int isVLStringResult = org.hdfgroup.javahdf5.hdf5_h.H5Tis_variable_str(baseTypeId);
boolean isVLString = isVLStringResult > 0;
if (isVLString) {
// Allocate buffer for array of string pointers
MemorySegment buffer = arena.allocate(ValueLayout.ADDRESS, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Aread(attr_id, mem_type_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read VL string array data");
}
// IMMEDIATELY copy string data before any potential reclaim
String[][] copiedStringData = new String[count][arraySize];
for (int i = 0; i < count; i++) {
for (int j = 0; j < arraySize; j++) {
MemorySegment stringPtr = buffer.getAtIndex(ValueLayout.ADDRESS, i * arraySize + j);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
try {
// Reinterpret the pointer with global scope to access the string data
MemorySegment stringData =
MemorySegment.ofAddress(stringPtr.address()).reinterpret(Long.MAX_VALUE);
copiedStringData[i][j] = stringData.getString(0, StandardCharsets.UTF_8);
}
catch (Exception e) {
copiedStringData[i][j] = null;
}
}
else {
copiedStringData[i][j] = null;
}
}
}
// Clean up VL string memory AFTER copying
long space_id = org.hdfgroup.javahdf5.hdf5_h.H5Aget_space(attr_id);
if (space_id >= 0) {
try {
// Reclaim memory
int reclaim_status = org.hdfgroup.javahdf5.hdf5_h.H5Treclaim(
mem_type_id, space_id, HDF5Constants.H5P_DEFAULT, buffer);
if (reclaim_status < 0) {
System.err.println("Warning: Failed to reclaim VL string memory");
}
}
finally {
org.hdfgroup.javahdf5.hdf5_h.H5Sclose(space_id);
}
}
// Convert copied string data to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<String> stringArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
stringArray.add(copiedStringData[i][j]);
}
resultArray[i] = stringArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else {
// Check for other supported base types
int baseTypeClass = org.hdfgroup.javahdf5.hdf5_h.H5Tget_class(baseTypeId);
if (baseTypeClass == HDF5Constants.H5T_INTEGER) {
// Support integer arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_INT, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Aread(attr_id, mem_type_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// Convert to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<Integer> intArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
int value = buffer.getAtIndex(ValueLayout.JAVA_INT, i * arraySize + j);
intArray.add(value);
}
resultArray[i] = intArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else if (baseTypeClass == HDF5Constants.H5T_FLOAT) {
// Support double arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_DOUBLE, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Aread(attr_id, mem_type_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// Convert to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<Double> doubleArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
double value = buffer.getAtIndex(ValueLayout.JAVA_DOUBLE, i * arraySize + j);
doubleArray.add(value);
}
resultArray[i] = doubleArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Unsupported array base type for FFM reading: " +
baseTypeClass);
}
}
}
catch (Exception e) {
if (e instanceof HDF5JavaException) {
throw e;
}
throw new HDF5JavaException("Array datatype reading failed: " + e.getMessage());
}
}
/**
* Read array datatype data from HDF5 dataset (not hvl_t)
* Used for H5T_ARRAY datatypes where each element is a fixed-size array
*/
public static ArrayList[] readArrayDatatypeFromDataset(long dataset_id, long mem_type_id,
long mem_space_id, long file_space_id,
long xfer_plist_id, int count, Arena arena)
throws HDF5JavaException
{
try {
// Get the array type information
long baseTypeId = org.hdfgroup.javahdf5.hdf5_h.H5Tget_super(mem_type_id);
if (baseTypeId < 0) {
throw new HDF5JavaException("Failed to get array base type");
}
// Get array dimensions
int ndims = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_ndims(mem_type_id);
if (ndims != 1) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Only 1D arrays are supported, got " + ndims + "D");
}
// Get the array size (number of elements per array)
MemorySegment dims = arena.allocate(ValueLayout.JAVA_LONG, 1);
int result = org.hdfgroup.javahdf5.hdf5_h.H5Tget_array_dims2(mem_type_id, dims);
if (result < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to get array dimensions");
}
int arraySize = (int)dims.get(ValueLayout.JAVA_LONG, 0);
// Check if the base type is variable-length string
int isVLStringResult = org.hdfgroup.javahdf5.hdf5_h.H5Tis_variable_str(baseTypeId);
boolean isVLString = isVLStringResult > 0;
if (isVLString) {
// Allocate buffer for array of string pointers
MemorySegment buffer = arena.allocate(ValueLayout.ADDRESS, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// IMMEDIATELY copy string data before any potential reclaim
String[][] copiedStringData = new String[count][arraySize];
for (int i = 0; i < count; i++) {
for (int j = 0; j < arraySize; j++) {
MemorySegment stringPtr = buffer.getAtIndex(ValueLayout.ADDRESS, i * arraySize + j);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
// Reinterpret the pointer with global scope to access the string data
MemorySegment stringData =
MemorySegment.ofAddress(stringPtr.address()).reinterpret(Long.MAX_VALUE);
copiedStringData[i][j] = stringData.getString(0, StandardCharsets.UTF_8);
}
else {
copiedStringData[i][j] = null;
}
}
}
// Clean up VL string memory AFTER copying
long space_id = (mem_space_id >= 0) ? mem_space_id : file_space_id;
try {
org.hdfgroup.javahdf5.hdf5_h.H5Treclaim(
mem_type_id, space_id, org.hdfgroup.javahdf5.hdf5_h.H5P_DEFAULT(), buffer);
}
finally {
// space_id is parameter, don't close it
}
// Now convert copied data to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<String> stringArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
stringArray.add(copiedStringData[i][j]);
}
resultArray[i] = stringArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else {
// Check for other supported base types
int baseTypeClass = org.hdfgroup.javahdf5.hdf5_h.H5Tget_class(baseTypeId);
if (baseTypeClass == HDF5Constants.H5T_INTEGER) {
// Support integer arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_INT, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// Convert to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<Integer> intArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
int value = buffer.getAtIndex(ValueLayout.JAVA_INT, i * arraySize + j);
intArray.add(value);
}
resultArray[i] = intArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else if (baseTypeClass == HDF5Constants.H5T_FLOAT) {
// Support double arrays
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_DOUBLE, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// Convert to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<Double> doubleArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
double value = buffer.getAtIndex(ValueLayout.JAVA_DOUBLE, i * arraySize + j);
doubleArray.add(value);
}
resultArray[i] = doubleArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else if (baseTypeClass == HDF5Constants.H5T_ENUM) {
// Support enum arrays - treat enums as integers
MemorySegment buffer = arena.allocate(ValueLayout.JAVA_INT, count * arraySize);
// Read data from HDF5
int status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, buffer);
if (status < 0) {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Failed to read array data");
}
// Convert to ArrayList array
ArrayList[] resultArray = new ArrayList[count];
for (int i = 0; i < count; i++) {
ArrayList<Integer> enumArray = new ArrayList<>(arraySize);
for (int j = 0; j < arraySize; j++) {
int value = buffer.getAtIndex(ValueLayout.JAVA_INT, i * arraySize + j);
enumArray.add(value);
}
resultArray[i] = enumArray;
}
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
return resultArray;
}
else {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseTypeId);
throw new HDF5JavaException("Unsupported array base type for FFM reading: " +
baseTypeClass);
}
}
}
catch (Exception e) {
if (e instanceof HDF5JavaException) {
throw e;
}
throw new HDF5JavaException("Array datatype reading failed: " + e.getMessage());
}
}
/**
* Convert nested ArrayList<ArrayList<?>> to hvl_t array
*/
@SuppressWarnings("unchecked")
private static MemorySegment convertNestedVL(ArrayList<?> list, Arena arena) throws HDF5JavaException
{
ArrayList<ArrayList<?>> nestedList = (ArrayList<ArrayList<?>>)list;
MemorySegment nestedHvlArray = hvl_t.allocateArray(nestedList.size(), arena);
for (int i = 0; i < nestedList.size(); i++) {
MemorySegment hvlElement = hvl_t.asSlice(nestedHvlArray, i);
convertSingleElement(nestedList.get(i), hvlElement, arena);
}
return nestedHvlArray;
}
/**
* Copy raw bytes from HDF5-managed memory to Java-managed memory immediately.
*/
private static RawVLData copyRawVLData(MemorySegment dataPtr, int len, long elementType)
throws HDF5JavaException
{
if (len == 0 || dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
return new RawVLData(new byte[0], 0);
}
try {
long baseType = elementType;
boolean needToCloseBaseType = false;
try {
if (hdf.hdf5lib.H5.H5Tdetect_class(elementType, hdf.hdf5lib.HDF5Constants.H5T_VLEN)) {
baseType = org.hdfgroup.javahdf5.hdf5_h.H5Tget_super(elementType);
needToCloseBaseType = true;
}
}
catch (Exception e) {
}
try {
long elementSize = org.hdfgroup.javahdf5.hdf5_h.H5Tget_size(baseType);
long totalSize = (long)len * elementSize;
if (elementSize == 0) {
throw new RuntimeException("Zero element size - trigger fallback");
}
byte[] rawData = copyWithReinterpret(dataPtr, totalSize, len);
if (rawData.length > 0) {
return new RawVLData(rawData, len);
}
return new RawVLData(new byte[0], len);
}
finally {
if (needToCloseBaseType && baseType != elementType) {
try {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(baseType);
}
catch (Exception ex) {
}
}
}
}
catch (Exception e) {
try {
byte[] rawData = copyWithReinterpret(dataPtr, (long)len * 8, len);
if (rawData.length > 0) {
return new RawVLData(rawData, len);
}
rawData = copyWithReinterpret(dataPtr, (long)len * 4, len);
if (rawData.length > 0) {
return new RawVLData(rawData, len);
}
}
catch (Exception fallbackEx) {
}
return new RawVLData(new byte[0], len);
}
}
/**
* Copy data using FFM reinterpret with proper sizing.
*/
private static byte[] copyWithReinterpret(MemorySegment dataPtr, long totalSize, int len)
{
try {
MemorySegment reinterpretedSegment = dataPtr.reinterpret(totalSize, Arena.global(), null);
byte[] rawData = new byte[(int)totalSize];
for (int i = 0; i < totalSize; i++) {
rawData[i] = reinterpretedSegment.get(ValueLayout.JAVA_BYTE, i);
}
return rawData;
}
catch (Exception e) {
return new byte[0];
}
}
/**
* Copy string VL data immediately, extracting actual string content.
*/
private static RawVLData copyStringVLDataImmediately(MemorySegment dataPtr, int len)
throws HDF5JavaException
{
if (len == 0 || dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
return new RawVLData(new byte[0], 0);
}
try {
java.util.List<Byte> allStringBytes = new java.util.ArrayList<>();
allStringBytes.add((byte)(len & 0xFF));
allStringBytes.add((byte)((len >> 8) & 0xFF));
allStringBytes.add((byte)((len >> 16) & 0xFF));
allStringBytes.add((byte)((len >> 24) & 0xFF));
try {
String str = dataPtr.getString(0, StandardCharsets.UTF_8);
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
allStringBytes.set(0, (byte)1);
allStringBytes.set(1, (byte)0);
allStringBytes.set(2, (byte)0);
allStringBytes.set(3, (byte)0);
int strLen = strBytes.length;
allStringBytes.add((byte)(strLen & 0xFF));
allStringBytes.add((byte)((strLen >> 8) & 0xFF));
allStringBytes.add((byte)((strLen >> 16) & 0xFF));
allStringBytes.add((byte)((strLen >> 24) & 0xFF));
for (byte b : strBytes) {
allStringBytes.add(b);
}
}
catch (Exception directStringEx) {
try {
long pointerArraySize = (long)len * 8;
MemorySegment reinterpretedArray =
dataPtr.reinterpret(pointerArraySize, Arena.global(), null);
for (int i = 0; i < len; i++) {
try {
MemorySegment stringPtr = reinterpretedArray.getAtIndex(ValueLayout.ADDRESS, i);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
String str = stringPtr.getString(0, StandardCharsets.UTF_8);
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
int strLen = strBytes.length;
allStringBytes.add((byte)(strLen & 0xFF));
allStringBytes.add((byte)((strLen >> 8) & 0xFF));
allStringBytes.add((byte)((strLen >> 16) & 0xFF));
allStringBytes.add((byte)((strLen >> 24) & 0xFF));
for (byte b : strBytes) {
allStringBytes.add(b);
}
}
else {
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
}
}
catch (Exception e) {
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
}
}
}
catch (Exception reinterpretEx) {
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
allStringBytes.add((byte)0);
}
}
byte[] result = new byte[allStringBytes.size()];
for (int i = 0; i < result.length; i++) {
result[i] = allStringBytes.get(i);
}
return new RawVLData(result, 1);
}
catch (Exception e) {
throw new HDF5JavaException("Failed to copy string VL data: " + e.getMessage());
}
}
/**
* Convert copied raw data to ArrayList using Java-managed memory only.
*/
private static ArrayList<?> convertRawDataToArrayList(RawVLData rawData, long elementType)
throws HDF5JavaException
{
if (rawData.length == 0) {
return new ArrayList<>();
}
if (rawData.data.length == 0 && rawData.length > 0) {
ArrayList<Object> fallback = new ArrayList<>(rawData.length);
for (int i = 0; i < rawData.length; i++) {
fallback.add(null);
}
return fallback;
}
try {
if (isIntegerType(elementType)) {
return convertRawDataToIntegerList(rawData);
}
else if (isDoubleType(elementType)) {
return convertRawDataToDoubleList(rawData);
}
else if (isStringType(elementType)) {
return convertRawDataToStringList(rawData);
}
else if (isReferenceType(elementType)) {
return convertRawDataToByteArrayList(rawData);
}
else if (isVLType(elementType)) {
return convertRawDataToNestedVLList(rawData, elementType);
}
else {
return detectAndConvertUnknownType(rawData, elementType);
}
}
catch (Exception e) {
ArrayList<Object> fallback = new ArrayList<>();
for (int i = 0; i < rawData.length; i++) {
fallback.add(null);
}
return fallback;
}
}
/**
* Convert raw bytes to Integer ArrayList
*/
private static ArrayList<Integer> convertRawDataToIntegerList(RawVLData rawData)
{
ArrayList<Integer> result = new ArrayList<>(rawData.length);
byte[] data = rawData.data;
int bytesPerInt = Integer.BYTES;
int maxInts = Math.min(rawData.length, data.length / bytesPerInt);
for (int i = 0; i < maxInts; i++) {
int offset = i * bytesPerInt;
if (offset + bytesPerInt <= data.length) {
// Reconstruct integer from bytes (little-endian)
int value = (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8) |
((data[offset + 2] & 0xFF) << 16) | (data[offset + 3] << 24);
result.add(value);
}
}
return result;
}
/**
* Convert raw bytes to Double ArrayList
*/
private static ArrayList<Double> convertRawDataToDoubleList(RawVLData rawData)
{
ArrayList<Double> result = new ArrayList<>(rawData.length);
byte[] data = rawData.data;
int bytesPerDouble = Double.BYTES;
int maxDoubles = Math.min(rawData.length, data.length / bytesPerDouble);
for (int i = 0; i < maxDoubles; i++) {
int offset = i * bytesPerDouble;
if (offset + bytesPerDouble <= data.length) {
// Reconstruct double from bytes (little-endian)
long longBits = 0;
for (int j = 0; j < 8; j++) {
longBits |= ((long)(data[offset + j] & 0xFF)) << (j * 8);
}
double value = Double.longBitsToDouble(longBits);
result.add(value);
}
}
return result;
}
/**
* Convert raw bytes to String ArrayList, decoding packed format.
*/
private static ArrayList<String> convertRawDataToStringList(RawVLData rawData)
{
ArrayList<String> result = new ArrayList<>();
if (rawData.length == 0 || rawData.data.length < 4) {
for (int i = 0; i < rawData.length; i++) {
result.add("");
}
return result;
}
byte[] data = rawData.data;
try {
if (data.length >= 4) {
int numStrings =
(data[0] & 0xFF) | ((data[1] & 0xFF) << 8) | ((data[2] & 0xFF) << 16) | (data[3] << 24);
if (numStrings == rawData.length && numStrings > 0) {
int offset = 4;
for (int i = 0; i < numStrings && offset + 4 <= data.length; i++) {
int strLen = (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8) |
((data[offset + 2] & 0xFF) << 16) | (data[offset + 3] << 24);
offset += 4;
if (strLen == 0) {
result.add("");
}
else if (offset + strLen <= data.length) {
byte[] strBytes = new byte[strLen];
System.arraycopy(data, offset, strBytes, 0, strLen);
String str = new String(strBytes, StandardCharsets.UTF_8);
result.add(str);
offset += strLen;
}
else {
result.add("");
}
}
}
}
while (result.size() < rawData.length) {
result.add("");
}
}
catch (Exception e) {
result.clear();
for (int i = 0; i < rawData.length; i++) {
result.add("");
}
}
return result;
}
/**
* Convert raw bytes to byte array ArrayList (for HDF5 references).
*/
private static ArrayList<byte[]> convertRawDataToByteArrayList(RawVLData rawData)
{
ArrayList<byte[]> result = new ArrayList<>();
if (rawData.length == 0 || rawData.data.length == 0) {
return result;
}
byte[] data = rawData.data;
try {
if (data.length >= 4) {
int numRefs =
(data[0] & 0xFF) | ((data[1] & 0xFF) << 8) | ((data[2] & 0xFF) << 16) | (data[3] << 24);
if (numRefs == rawData.length && numRefs > 0) {
int offset = 4;
for (int i = 0; i < numRefs && offset + 4 <= data.length; i++) {
int refLen = (data[offset] & 0xFF) | ((data[offset + 1] & 0xFF) << 8) |
((data[offset + 2] & 0xFF) << 16) | (data[offset + 3] << 24);
offset += 4;
if (offset + refLen <= data.length) {
byte[] refData = new byte[refLen];
System.arraycopy(data, offset, refData, 0, refLen);
result.add(refData);
offset += refLen;
}
else {
result.add(new byte[0]);
}
}
}
else {
result.add(data.clone());
}
}
else {
result.add(data.clone());
}
}
catch (Exception e) {
result.clear();
result.add(data.clone());
}
return result;
}
/**
* Convert raw bytes to nested VL ArrayList.
*/
private static ArrayList<ArrayList<?>> convertRawDataToNestedVLList(RawVLData rawData, long elementType)
throws HDF5JavaException
{
ArrayList<ArrayList<?>> result = new ArrayList<>(rawData.length);
if (rawData.length == 0 || rawData.data.length == 0) {
return result;
}
try {
Arena tempArena = Arena.global();
byte[] data = rawData.data;
int hvlSize = 16;
int maxStructs = data.length / hvlSize;
int actualStructs = Math.min(maxStructs, rawData.length);
if (actualStructs > 0) {
MemorySegment reconstructedHvlArray = tempArena.allocate(data.length);
reconstructedHvlArray.copyFrom(MemorySegment.ofArray(data));
result = convertNestedVLImmediately(reconstructedHvlArray, actualStructs, elementType);
}
while (result.size() < rawData.length) {
result.add(new ArrayList<>());
}
}
catch (Exception e) {
result.clear();
for (int i = 0; i < rawData.length; i++) {
result.add(new ArrayList<>());
}
}
return result;
}
/**
* Detect and convert unknown HDF5 datatypes by examining the raw data
*/
private static ArrayList<?> detectAndConvertUnknownType(RawVLData rawData, long elementType)
{
// Try to detect the data type from content
if (rawData.data.length == 0) {
return new ArrayList<>();
}
// Check if it looks like packed string data (starts with count)
if (rawData.data.length >= 4) {
int possibleCount = (rawData.data[0] & 0xFF) | ((rawData.data[1] & 0xFF) << 8) |
((rawData.data[2] & 0xFF) << 16) | (rawData.data[3] << 24);
if (possibleCount == rawData.length && possibleCount > 0 && possibleCount < 1000) {
// Looks like string data
return convertRawDataToStringList(rawData);
}
}
// Check if it looks like integer data
if (rawData.data.length >= rawData.length * 4) {
try {
return convertRawDataToIntegerList(rawData);
}
catch (Exception e) {
// Not integer data
}
}
// Check if it looks like double data
if (rawData.data.length >= rawData.length * 8) {
try {
return convertRawDataToDoubleList(rawData);
}
catch (Exception e) {
// Not double data
}
}
// Fallback: create empty list
ArrayList<Object> result = new ArrayList<>();
for (int i = 0; i < rawData.length; i++) {
result.add(""); // Use empty string as safe fallback
}
return result;
}
/**
* IMMEDIATE conversion that extracts all data before any H5Treclaim can invalidate memory
* This follows the JNI translate pattern of immediate data copying.
* DEPRECATED: Use the two-phase approach instead
*/
@Deprecated
private static ArrayList<?> convertSingleElementImmediately(MemorySegment dataPtr, int len,
long elementType) throws HDF5JavaException
{
if (len == 0 || dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
return new ArrayList<>();
}
// IMMEDIATE data extraction based on HDF5 datatype
if (isIntegerType(elementType)) {
return convertIntegerVLFromHVL(dataPtr, len);
}
else if (isDoubleType(elementType)) {
return convertDoubleVLFromHVL(dataPtr, len);
}
else if (isStringType(elementType)) {
return convertStringVLFromHVL(dataPtr, len);
}
else if (isVLType(elementType)) {
// For nested VL, we need to extract all nested hvl_t data IMMEDIATELY
return convertNestedVLImmediately(dataPtr, len, elementType);
}
else {
throw new HDF5JavaException("Unsupported HDF5 datatype for VL conversion: " + elementType);
}
}
/**
* Legacy method kept for compatibility - now delegates to immediate conversion
* CRITICAL: This method should not be used for new code - use convertSingleElementImmediately instead
* This method exists only for backward compatibility and should be avoided
*/
@Deprecated
private static ArrayList<?> convertSingleElementFromHVL(MemorySegment hvlElement, long elementType)
throws HDF5JavaException
{
// CRITICAL: Extract hvl_t data IMMEDIATELY to prevent access after H5Treclaim
long len = hvl_t.len(hvlElement);
MemorySegment dataPtr = hvl_t.p(hvlElement);
return convertSingleElementImmediately(dataPtr, (int)len, elementType);
}
/**
* Convert native int array back to ArrayList<Integer>
*/
private static ArrayList<Integer> convertIntegerVLFromHVL(MemorySegment dataPtr, int len)
{
ArrayList<Integer> result = new ArrayList<>(len);
// Check if we have a valid memory segment
if (dataPtr == null || dataPtr.equals(MemorySegment.NULL) || len <= 0) {
return result;
}
// IMPORTANT: For nested VL structures, we cannot trust the byteSize()
// since HDF5 may invalidate memory at any time. We must be more defensive.
long requiredBytes = (long)len * Integer.BYTES;
// Use safe bounds checking without relying on byteSize() for HDF5 managed memory
boolean canCheckSize = true;
try {
// Only check size for non-HDF5 managed memory segments
if (dataPtr.byteSize() != Long.MAX_VALUE && dataPtr.byteSize() > 0) {
if (dataPtr.byteSize() < requiredBytes) {
throw new HDF5JavaException("Memory segment too small: has " + dataPtr.byteSize() +
" bytes, need " + requiredBytes + " for " + len +
" integers");
}
}
}
catch (Exception e) {
// If we can't check the size safely, proceed with caution
canCheckSize = false;
}
for (int i = 0; i < len; i++) {
// Handle unaligned memory by reading as bytes and reconstructing integer
long offset = (long)i * Integer.BYTES;
int value;
try {
value = dataPtr.getAtIndex(ValueLayout.JAVA_INT, i);
}
catch (IllegalArgumentException e) {
// Memory is not aligned for direct int access, read as bytes with bounds checking
try {
// Extra safety: check if we can read each byte before accessing
if (offset + 3 >= 0) { // Basic sanity check
byte b0 = dataPtr.get(ValueLayout.JAVA_BYTE, offset);
byte b1 = dataPtr.get(ValueLayout.JAVA_BYTE, offset + 1);
byte b2 = dataPtr.get(ValueLayout.JAVA_BYTE, offset + 2);
byte b3 = dataPtr.get(ValueLayout.JAVA_BYTE, offset + 3);
// Reconstruct integer in native byte order (little-endian on x86)
value = (b0 & 0xFF) | ((b1 & 0xFF) << 8) | ((b2 & 0xFF) << 16) | (b3 << 24);
}
else {
throw new HDF5JavaException("Invalid offset for integer at index " + i);
}
}
catch (Exception ex) {
// If we get a SIGSEGV-type error, the memory is no longer valid
throw new HDF5JavaException("Memory access violation at index " + i + " (offset " +
offset +
") - memory may have been freed by HDF5: " + ex.getMessage());
}
}
catch (Exception e) {
// Catch any other access violations
throw new HDF5JavaException("Memory access error at index " + i +
" - memory segment may be invalid: " + e.getMessage());
}
result.add(value);
}
return result;
}
/**
* Convert native double array back to ArrayList<Double>
*/
private static ArrayList<Double> convertDoubleVLFromHVL(MemorySegment dataPtr, int len)
{
ArrayList<Double> result = new ArrayList<>(len);
// Check if we have a valid memory segment
if (dataPtr == null || dataPtr.equals(MemorySegment.NULL) || len <= 0) {
return result;
}
// IMPORTANT: For nested VL structures, we cannot trust the byteSize()
// since HDF5 may invalidate memory at any time. We must be more defensive.
long requiredBytes = (long)len * Double.BYTES;
// Use safe bounds checking without relying on byteSize() for HDF5 managed memory
boolean canCheckSize = true;
try {
// Only check size for non-HDF5 managed memory segments
if (dataPtr.byteSize() != Long.MAX_VALUE && dataPtr.byteSize() > 0) {
if (dataPtr.byteSize() < requiredBytes) {
throw new HDF5JavaException("Memory segment too small: has " + dataPtr.byteSize() +
" bytes, need " + requiredBytes + " for " + len + " doubles");
}
}
}
catch (Exception e) {
// If we can't check the size safely, proceed with caution
canCheckSize = false;
}
for (int i = 0; i < len; i++) {
// Handle unaligned memory by reading as bytes and reconstructing double
long offset = (long)i * Double.BYTES;
double value;
try {
value = dataPtr.getAtIndex(ValueLayout.JAVA_DOUBLE, i);
}
catch (IllegalArgumentException e) {
// Memory is not aligned for direct double access, read as bytes with bounds checking
try {
long longBits = 0;
for (int j = 0; j < 8; j++) {
byte b = dataPtr.get(ValueLayout.JAVA_BYTE, offset + j);
longBits |= ((long)(b & 0xFF)) << (j * 8);
}
value = Double.longBitsToDouble(longBits);
}
catch (Exception ex) {
throw new HDF5JavaException("Failed to read double at index " + i + " (offset " + offset +
"): " + ex.getMessage());
}
}
result.add(value);
}
return result;
}
/**
* Convert native char** array back to ArrayList<String>
*/
private static ArrayList<String> convertStringVLFromHVL(MemorySegment dataPtr, int len)
{
// For variable-length strings (H5T_C_S1 + H5T_VARIABLE),
// the hvl_t structure is interpreted differently than for regular VL data
ArrayList<String> result = new ArrayList<>(1);
// Check if we have a valid memory segment
if (dataPtr == null || dataPtr.equals(MemorySegment.NULL)) {
result.add(""); // Add empty string for invalid data
return result;
}
try {
// For VL strings, check if 'len' might be a string pointer address
if (len > 0x1000000) {
try {
MemorySegment stringPtr =
MemorySegment.ofAddress(len).reinterpret(100, Arena.global(), null);
String str = stringPtr.getString(0, java.nio.charset.StandardCharsets.UTF_8);
result.add(str);
return result;
}
catch (Exception addrException) {
// Fall through to direct read
}
}
String str = dataPtr.getString(0, java.nio.charset.StandardCharsets.UTF_8);
result.add(str);
}
catch (Exception e) {
result.add("");
}
return result;
}
/**
* Extract nested VL data immediately before H5Treclaim.
*/
private static ArrayList<ArrayList<?>> convertNestedVLImmediately(MemorySegment dataPtr, int len,
long elementType)
throws HDF5JavaException
{
ArrayList<ArrayList<?>> result = new ArrayList<>(len);
long baseType = getVLBaseType(elementType);
try {
for (int i = 0; i < len; i++) {
MemorySegment nestedHvlElement = hvl_t.asSlice(dataPtr, i);
long nestedLen = hvl_t.len(nestedHvlElement);
MemorySegment nestedDataPtr = hvl_t.p(nestedHvlElement);
if (nestedLen == 0 || nestedDataPtr == null || nestedDataPtr.equals(MemorySegment.NULL)) {
result.add(new ArrayList<>());
continue;
}
ArrayList<?> nestedList =
convertSingleElementImmediately(nestedDataPtr, (int)nestedLen, baseType);
result.add(nestedList);
}
}
finally {
try {
H5.H5Tclose(baseType);
}
catch (Exception e) {
}
}
return result;
}
/**
* Legacy nested VL conversion - now delegates to immediate version
*/
private static ArrayList<ArrayList<?>> convertNestedVLFromHVL(MemorySegment dataPtr, int len,
long elementType) throws HDF5JavaException
{
return convertNestedVLImmediately(dataPtr, len, elementType);
}
/**
* Safely convert a nested VL element by immediately copying data
*/
private static ArrayList<?> convertNestedElementSafely(MemorySegment dataPtr, int len, long elementType)
throws HDF5JavaException
{
// Type detection based on HDF5 datatype
if (isIntegerType(elementType)) {
return convertIntegerVLFromHVL(dataPtr, len);
}
else if (isDoubleType(elementType)) {
return convertDoubleVLFromHVL(dataPtr, len);
}
else if (isStringType(elementType)) {
return convertStringVLFromHVL(dataPtr, len);
}
else if (isVLType(elementType)) {
// Recursively nested VL - handle with care
long baseType = getVLBaseType(elementType);
try {
return convertNestedVLFromHVL(dataPtr, len, baseType);
}
finally {
// CRITICAL: Close the base type to prevent memory leaks
try {
H5.H5Tclose(baseType);
}
catch (Exception e) {
// Log but don't fail - we've already done the main work
}
}
}
else {
throw new HDF5JavaException("Unsupported nested HDF5 datatype for VL conversion: " + elementType);
}
}
// Helper methods for HDF5 datatype detection
private static boolean isIntegerType(long datatype)
{
try {
return H5.H5Tget_class(datatype) == HDF5Constants.H5T_INTEGER;
}
catch (Exception e) {
return false;
}
}
private static boolean isDoubleType(long datatype)
{
try {
return H5.H5Tget_class(datatype) == HDF5Constants.H5T_FLOAT;
}
catch (Exception e) {
return false;
}
}
private static boolean isStringType(long datatype)
{
try {
return H5.H5Tget_class(datatype) == HDF5Constants.H5T_STRING;
}
catch (Exception e) {
return false;
}
}
private static boolean isVLType(long datatype)
{
try {
return H5.H5Tget_class(datatype) == HDF5Constants.H5T_VLEN;
}
catch (Exception e) {
return false;
}
}
private static boolean isReferenceType(long datatype)
{
try {
return H5.H5Tget_class(datatype) == HDF5Constants.H5T_REFERENCE;
}
catch (Exception e) {
return false;
}
}
private static boolean isVLOfStrings(long datatype)
{
try {
// Check if this is a VL type
if (H5.H5Tget_class(datatype) != HDF5Constants.H5T_VLEN) {
return false;
}
// Get the base type
long baseType = H5.H5Tget_super(datatype);
// Check if base type is a string
boolean isVLOfString = H5.H5Tget_class(baseType) == HDF5Constants.H5T_STRING;
H5.H5Tclose(baseType);
return isVLOfString;
}
catch (Exception e) {
return false;
}
}
private static long getVLBaseType(long vlDatatype) throws HDF5JavaException
{
try {
return H5.H5Tget_super(vlDatatype);
}
catch (Exception e) {
throw new HDF5JavaException("Failed to get VL base type: " + e.getMessage());
}
}
/**
* Convert ArrayList[] of strings to variable-length string array for HDF5
* Variable-length strings use string pointer arrays, not hvl_t structures
*
* @param javaData Array of ArrayLists containing string data
* @param arena Arena for memory allocation
* @return MemorySegment containing string pointer array
* @throws HDF5JavaException if conversion fails
*/
public static MemorySegment convertVLStrings(ArrayList[] javaData, Arena arena) throws HDF5JavaException
{
if (javaData == null || javaData.length == 0) {
throw new HDF5JavaException("Input data array is null or empty");
}
// Allocate array of string pointers using Arena (this part is OK)
MemorySegment stringArray = arena.allocate(ValueLayout.ADDRESS, javaData.length);
for (int i = 0; i < javaData.length; i++) {
if (javaData[i] == null || javaData[i].size() == 0) {
// Set null pointer for empty/null strings
stringArray.setAtIndex(ValueLayout.ADDRESS, i, MemorySegment.NULL);
}
else {
// Get the first string from the ArrayList (VL string format)
String str = (String)javaData[i].get(0);
if (str == null) {
stringArray.setAtIndex(ValueLayout.ADDRESS, i, MemorySegment.NULL);
}
else {
// CRITICAL FIX: Use HDF5's memory allocator instead of Arena
// This prevents conflicts between HDF5's VL memory cleanup and Java's Arena
byte[] strBytes = str.getBytes(java.nio.charset.StandardCharsets.UTF_8);
// Allocate with extra byte for null terminator
MemorySegment hdf5StringMem =
org.hdfgroup.javahdf5.hdf5_h.H5allocate_memory(strBytes.length + 1, false);
if (hdf5StringMem == null || hdf5StringMem.equals(MemorySegment.NULL)) {
throw new HDF5JavaException("Failed to allocate HDF5 memory for string: " + str);
}
// Copy string bytes with proper scope management
MemorySegment boundedMem =
hdf5StringMem.reinterpret(strBytes.length + 1, Arena.global(), null);
boundedMem.copyFrom(MemorySegment.ofArray(strBytes));
// Add null terminator
boundedMem.set(ValueLayout.JAVA_BYTE, strBytes.length, (byte)0);
stringArray.setAtIndex(ValueLayout.ADDRESS, i, boundedMem);
}
}
}
return stringArray;
}
/**
* Read variable-length strings from HDF5 dataset
* Variable-length strings are read as string pointer arrays, not hvl_t structures
*
* @param dataset_id HDF5 dataset identifier
* @param mem_type_id Memory datatype identifier
* @param mem_space_id Memory dataspace identifier
* @param file_space_id File dataspace identifier
* @param xfer_plist_id Transfer property list identifier
* @param arrayLength Number of strings to read
* @param arena Arena for memory allocation
* @return ArrayList array containing the read strings
* @throws HDF5JavaException if reading fails
*/
public static ArrayList[] readVLStrings(long dataset_id, long mem_type_id, long mem_space_id,
long file_space_id, long xfer_plist_id, int arrayLength,
Arena arena) throws HDF5JavaException
{
// Allocate array of string pointers for reading
MemorySegment stringArray = arena.allocate(ValueLayout.ADDRESS, arrayLength);
try {
// Call native H5Dread to read string pointers
int status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, stringArray);
if (status < 0) {
throw new HDF5JavaException("H5Dread failed for VL strings");
}
// Convert string pointers to ArrayList array
ArrayList[] result = new ArrayList[arrayLength];
for (int i = 0; i < arrayLength; i++) {
result[i] = new ArrayList<String>();
MemorySegment stringPtr = stringArray.getAtIndex(ValueLayout.ADDRESS, i);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
try {
// Read null-terminated string from pointer with bounds checking
String str = stringPtr.getString(0, java.nio.charset.StandardCharsets.UTF_8);
result[i].add(str);
}
catch (Exception e) {
// If string reading fails, add empty string
result[i].add("");
}
}
else {
// Empty string case
result[i].add("");
}
}
return result;
}
catch (Exception e) {
throw new HDF5JavaException("Failed to read VL strings: " + e.getMessage());
}
}
/**
* Read variable-length strings from HDF5 attribute
* Attributes and datasets may handle VL strings slightly differently
*
* @param attr_id HDF5 attribute identifier
* @param mem_type_id Memory datatype identifier
* @param arrayLength Number of strings to read
* @param arena Arena for memory allocation
* @return ArrayList array containing the read strings
* @throws HDF5JavaException if reading fails
*/
public static ArrayList[] readVLStringsFromAttribute(long attr_id, long mem_type_id, int arrayLength,
Arena arena) throws HDF5JavaException
{
// For attributes, allocate array of string pointers for reading
MemorySegment stringArray = arena.allocate(ValueLayout.ADDRESS, arrayLength);
try {
// Call native H5Aread to read string pointers
int status = org.hdfgroup.javahdf5.hdf5_h.H5Aread(attr_id, mem_type_id, stringArray);
if (status < 0) {
throw new HDF5JavaException("H5Aread failed for VL strings");
}
// Convert string pointers to ArrayList array
ArrayList[] result = new ArrayList[arrayLength];
for (int i = 0; i < arrayLength; i++) {
result[i] = new ArrayList<String>();
MemorySegment stringPtr = stringArray.getAtIndex(ValueLayout.ADDRESS, i);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
try {
// Read null-terminated string from pointer with bounds checking
String str = stringPtr.getString(0, java.nio.charset.StandardCharsets.UTF_8);
result[i].add(str);
}
catch (Exception e) {
// If string reading fails, add empty string
result[i].add("");
}
}
else {
// Empty string case
result[i].add("");
}
}
return result;
}
catch (Exception e) {
throw new HDF5JavaException("Failed to read VL strings from attribute: " + e.getMessage());
}
}
/**
* Convert ArrayList array with heterogeneous types to compound datatype buffer
* Used for H5T_COMPOUND datatypes where each ArrayList contains mixed field types
*
* @param data Array of ArrayLists containing compound field data
* @param mem_type_id HDF5 compound datatype identifier
* @param arena Arena for memory allocation
* @return MemorySegment containing packed compound structures
* @throws HDF5JavaException if conversion fails
*/
public static MemorySegment convertCompoundDatatype(ArrayList[] data, long mem_type_id, Arena arena)
throws HDF5JavaException
{
try {
// Get compound type information
int nmembers = org.hdfgroup.javahdf5.hdf5_h.H5Tget_nmembers(mem_type_id);
if (nmembers < 0) {
throw new HDF5JavaException("Failed to get number of compound members");
}
// Get total compound structure size
long compoundSize = org.hdfgroup.javahdf5.hdf5_h.H5Tget_size(mem_type_id);
if (compoundSize < 0) {
throw new HDF5JavaException("Failed to get compound size");
}
// Allocate buffer for all compound structures
MemorySegment buffer = arena.allocate(compoundSize * data.length);
// Get member information for each field
long[] memberTypeIds = new long[nmembers];
int[] memberClasses = new int[nmembers];
long[] memberOffsets = new long[nmembers];
long[] memberSizes = new long[nmembers];
boolean[] isVLStrings = new boolean[nmembers];
for (int i = 0; i < nmembers; i++) {
memberTypeIds[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_member_type(mem_type_id, i);
memberClasses[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_class(memberTypeIds[i]);
memberOffsets[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_member_offset(mem_type_id, i);
memberSizes[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_size(memberTypeIds[i]);
isVLStrings[i] = (memberClasses[i] == HDF5Constants.H5T_STRING &&
org.hdfgroup.javahdf5.hdf5_h.H5Tis_variable_str(memberTypeIds[i]) > 0);
}
try {
// Pack each ArrayList into the compound buffer
for (int structIdx = 0; structIdx < data.length; structIdx++) {
ArrayList<?> record = data[structIdx];
if (record == null || record.size() != nmembers) {
throw new HDF5JavaException("ArrayList at index " + structIdx + " has " +
(record == null ? "null" : record.size()) +
" elements, expected " + nmembers);
}
long structOffset = structIdx * compoundSize;
// Pack each field into the compound structure
for (int fieldIdx = 0; fieldIdx < nmembers; fieldIdx++) {
Object fieldValue = record.get(fieldIdx);
long fieldOffset = structOffset + memberOffsets[fieldIdx];
int memberClass = memberClasses[fieldIdx];
long memberSize = memberSizes[fieldIdx];
boolean isVLString = isVLStrings[fieldIdx];
if (memberClass == HDF5Constants.H5T_INTEGER) {
// Integer field - write bytes for unaligned HDF5 compound offsets
int intValue = (fieldValue instanceof Integer) ? (Integer)fieldValue : 0;
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset, (byte)(intValue & 0xFF));
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + 1,
(byte)((intValue >> 8) & 0xFF));
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + 2,
(byte)((intValue >> 16) & 0xFF));
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + 3,
(byte)((intValue >> 24) & 0xFF));
}
else if (memberClass == HDF5Constants.H5T_FLOAT) {
// Double field - write bytes for unaligned HDF5 compound offsets
double doubleValue = (fieldValue instanceof Double) ? (Double)fieldValue : 0.0;
long longBits = Double.doubleToRawLongBits(doubleValue);
for (int byteIdx = 0; byteIdx < 8; byteIdx++) {
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + byteIdx,
(byte)((longBits >> (byteIdx * 8)) & 0xFF));
}
}
else if (memberClass == HDF5Constants.H5T_STRING) {
if (isVLString) {
// Variable-length string - store as pointer
String strValue = (fieldValue instanceof String) ? (String)fieldValue : "";
byte[] strBytes = strValue.getBytes(StandardCharsets.UTF_8);
// Allocate with HDF5's memory allocator for VL strings
MemorySegment hdf5StringMem = org.hdfgroup.javahdf5.hdf5_h.H5allocate_memory(
strBytes.length + 1, false);
if (hdf5StringMem == null || hdf5StringMem.equals(MemorySegment.NULL)) {
throw new HDF5JavaException(
"Failed to allocate HDF5 memory for string: " + strValue);
}
MemorySegment boundedMem =
hdf5StringMem.reinterpret(strBytes.length + 1, Arena.global(), null);
boundedMem.copyFrom(MemorySegment.ofArray(strBytes));
boundedMem.set(ValueLayout.JAVA_BYTE, strBytes.length, (byte)0);
// Store pointer
buffer.set(ValueLayout.ADDRESS, fieldOffset, boundedMem);
}
else {
// Fixed-length string - copy bytes directly
String strValue = (fieldValue instanceof String) ? (String)fieldValue : "";
byte[] strBytes = strValue.getBytes(StandardCharsets.UTF_8);
int copyLen = (int)Math.min(strBytes.length, memberSize);
// Copy string bytes
for (int j = 0; j < copyLen; j++) {
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + j, strBytes[j]);
}
// Pad with zeros
for (int j = copyLen; j < memberSize; j++) {
buffer.set(ValueLayout.JAVA_BYTE, fieldOffset + j, (byte)0);
}
}
}
else {
throw new HDF5JavaException("Unsupported compound member type class: " +
memberClass);
}
}
}
}
finally {
// Close member type IDs
for (int i = 0; i < nmembers; i++) {
if (memberTypeIds[i] >= 0) {
try {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(memberTypeIds[i]);
}
catch (Exception e) {
// Ignore close errors
}
}
}
}
return buffer;
}
catch (Exception e) {
if (e instanceof HDF5JavaException) {
throw e;
}
throw new HDF5JavaException("Compound datatype conversion failed: " + e.getMessage());
}
}
/**
* Read compound datatype data from HDF5 attribute or dataset
* Used for H5T_COMPOUND datatypes where each ArrayList contains mixed field types
*
* @param attr_or_dataset_id HDF5 attribute or dataset identifier
* @param mem_type_id HDF5 compound datatype identifier
* @param count Number of compound structures to read
* @param arena Arena for memory allocation
* @param isDataset true if reading from dataset, false if reading from attribute
* @param mem_space_id Memory dataspace (for datasets only)
* @param file_space_id File dataspace (for datasets only)
* @param xfer_plist_id Transfer property list (for datasets only)
* @return ArrayList array containing compound field data
* @throws HDF5JavaException if reading fails
*/
public static ArrayList[] readCompoundDatatype(long attr_or_dataset_id, long mem_type_id, int count,
Arena arena, boolean isDataset, long mem_space_id,
long file_space_id, long xfer_plist_id)
throws HDF5JavaException
{
try {
// Get compound type information
int nmembers = org.hdfgroup.javahdf5.hdf5_h.H5Tget_nmembers(mem_type_id);
if (nmembers < 0) {
throw new HDF5JavaException("Failed to get number of compound members");
}
// Get total compound structure size
long compoundSize = org.hdfgroup.javahdf5.hdf5_h.H5Tget_size(mem_type_id);
if (compoundSize < 0) {
throw new HDF5JavaException("Failed to get compound size");
}
// Get member information for each field
long[] memberTypeIds = new long[nmembers];
int[] memberClasses = new int[nmembers];
long[] memberOffsets = new long[nmembers];
long[] memberSizes = new long[nmembers];
boolean[] isVLStrings = new boolean[nmembers];
for (int i = 0; i < nmembers; i++) {
memberTypeIds[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_member_type(mem_type_id, i);
memberClasses[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_class(memberTypeIds[i]);
memberOffsets[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_member_offset(mem_type_id, i);
memberSizes[i] = org.hdfgroup.javahdf5.hdf5_h.H5Tget_size(memberTypeIds[i]);
isVLStrings[i] = (memberClasses[i] == HDF5Constants.H5T_STRING &&
org.hdfgroup.javahdf5.hdf5_h.H5Tis_variable_str(memberTypeIds[i]) > 0);
}
// Allocate buffer for all compound structures
MemorySegment buffer = arena.allocate(compoundSize * count);
// Read data from HDF5
int status;
if (isDataset) {
status = org.hdfgroup.javahdf5.hdf5_h.H5Dread(attr_or_dataset_id, mem_type_id, mem_space_id,
file_space_id, xfer_plist_id, buffer);
}
else {
status = org.hdfgroup.javahdf5.hdf5_h.H5Aread(attr_or_dataset_id, mem_type_id, buffer);
}
if (status < 0) {
throw new HDF5JavaException("H5 read failed with status: " + status);
}
// Parse buffer into ArrayList array
ArrayList[] result = new ArrayList[count];
try {
for (int structIdx = 0; structIdx < count; structIdx++) {
ArrayList<Object> record = new ArrayList<>();
long structOffset = structIdx * compoundSize;
// Read each field from the compound structure
for (int fieldIdx = 0; fieldIdx < nmembers; fieldIdx++) {
long fieldOffset = structOffset + memberOffsets[fieldIdx];
int memberClass = memberClasses[fieldIdx];
long memberSize = memberSizes[fieldIdx];
boolean isVLString = isVLStrings[fieldIdx];
if (memberClass == HDF5Constants.H5T_INTEGER) {
// Read integer field (little-endian byte order)
int intValue =
(buffer.get(ValueLayout.JAVA_BYTE, fieldOffset) & 0xFF) |
((buffer.get(ValueLayout.JAVA_BYTE, fieldOffset + 1) & 0xFF) << 8) |
((buffer.get(ValueLayout.JAVA_BYTE, fieldOffset + 2) & 0xFF) << 16) |
(buffer.get(ValueLayout.JAVA_BYTE, fieldOffset + 3) << 24);
record.add(intValue);
}
else if (memberClass == HDF5Constants.H5T_FLOAT) {
// Read double field (8 bytes, little-endian)
long longBits = 0;
for (int byteIdx = 0; byteIdx < 8; byteIdx++) {
long byteVal =
buffer.get(ValueLayout.JAVA_BYTE, fieldOffset + byteIdx) & 0xFFL;
longBits |= (byteVal << (byteIdx * 8));
}
double doubleValue = Double.longBitsToDouble(longBits);
record.add(doubleValue);
}
else if (memberClass == HDF5Constants.H5T_STRING) {
if (isVLString) {
// Variable-length string - read pointer
MemorySegment stringPtr = buffer.get(ValueLayout.ADDRESS, fieldOffset);
if (stringPtr != null && !stringPtr.equals(MemorySegment.NULL)) {
try {
String str = stringPtr.getString(0, StandardCharsets.UTF_8);
record.add(str);
}
catch (Exception e) {
record.add("");
}
}
else {
record.add("");
}
}
else {
// Fixed-length string - read bytes
byte[] strBytes = new byte[(int)memberSize];
for (int j = 0; j < memberSize; j++) {
strBytes[j] = buffer.get(ValueLayout.JAVA_BYTE, fieldOffset + j);
}
// Convert to string and trim null terminators
String strValue = new String(strBytes, StandardCharsets.UTF_8);
int nullIdx = strValue.indexOf('\0');
if (nullIdx >= 0) {
strValue = strValue.substring(0, nullIdx);
}
record.add(strValue);
}
}
else {
throw new HDF5JavaException("Unsupported compound member type class for read: " +
memberClass);
}
}
result[structIdx] = record;
}
}
finally {
// Close member type IDs
for (int i = 0; i < nmembers; i++) {
if (memberTypeIds[i] >= 0) {
try {
org.hdfgroup.javahdf5.hdf5_h.H5Tclose(memberTypeIds[i]);
}
catch (Exception e) {
// Ignore close errors
}
}
}
}
return result;
}
catch (Exception e) {
if (e instanceof HDF5JavaException) {
throw e;
}
throw new HDF5JavaException("Compound datatype read failed: " + e.getMessage());
}
}
}
@@ -0,0 +1,47 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Aiterate.
*
*/
public interface H5A_iterate_cb extends org.hdfgroup.javahdf5.H5A_operator2_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each attribute
*
* @param loc_id the ID for the group or dataset being iterated over
* @param name the name of the current attribute about the object
* @param info the attribute's "info" struct
* @param op_data the operator data passed in to H5Aiterate
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(long location_id, MemorySegment attr_name, MemorySegment ainfo, MemorySegment op_data);
}
@@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Aiterate.
*
*/
public interface H5A_iterate_t {
/**
* public ArrayList iterdata = new ArrayList();
* Any derived interfaces must define the single public variable as above.
*/
}
@@ -0,0 +1,46 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Pset/get_append_flush.
*
*/
public interface H5D_append_cb extends H5D_append_cb_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each dataset access property list
*
* @param dataset_id the ID for the dataset being iterated over
* @param cur_dims the dimension sizes for determining boundary
* @param op_data the operator data passed in to H5Pset/get_append_flush
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(long dataset_id, MemorySegment cur_dims, MemorySegment op_data);
}
@@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Dappend.
*
*/
public interface H5D_append_t {
/**
* public ArrayList iterdata = new ArrayList();
* Any derived interfaces must define the single public variable as above.
*/
}
@@ -0,0 +1,48 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Diterate.
*
*/
public interface H5D_iterate_cb extends org.hdfgroup.javahdf5.H5D_operator_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each dataset element
*
* @param elem the pointer to the element in memory containing the current point
* @param elem_type the datatype ID for the elements stored in elem
* @param ndim the number of dimensions for POINT array
* @param point the array containing the location of the element within the original dataspace
* @param op_data the operator data passed in to H5Diterate
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(MemorySegment elem, long type_id, int ndim, MemorySegment point, MemorySegment operator_data);
}
@@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Diterate.
*
*/
public interface H5D_iterate_t {
/**
* public ArrayList iterdata = new ArrayList();
* Any derived interfaces must define the single public variable as above.
*/
}
@@ -0,0 +1,46 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Ewalk.
*
*/
public interface H5E_walk_cb extends H5E_walk2_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each error stack element
*
* @param nidx the index of the current error stack element
* @param info the error stack "info" struct
* @param op_data the operator data passed in to H5Ewalk
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(int n, MemorySegment err_desc, MemorySegment client_data);
}
@@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Ewalk.
*
*/
public interface H5E_walk_t {
/**
* public ArrayList iterdata = new ArrayList();
* Any derived interfaces must define the single public variable as above.
*/
}
@@ -0,0 +1,24 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Lvisit/H5Lvisit_by_name.
*
*/
public interface H5L_iterate_opdata_t {
}
@@ -0,0 +1,47 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Lvisit/H5Lvisit_by_name.
*
*/
public interface H5L_iterate_t extends H5L_iterate2_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each group
*
* @param loc_id the ID for the group being iterated over
* @param name the name of the current link
* @param info the link's "info" struct
* @param op_data the operator data passed in to H5Literate
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(long group, MemorySegment name, MemorySegment info, MemorySegment op_data);
}
@@ -0,0 +1,24 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Ovisit/H5Ovisit_by_name.
*
*/
public interface H5O_iterate_opdata_t {
}
@@ -0,0 +1,47 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Ovisit/H5Ovisit_by_name.
*
*/
public interface H5O_iterate_t extends H5O_iterate2_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each group
*
* @param loc_id the ID for the group or dataset being iterated over
* @param name the name of the current object
* @param info the object's "info" struct
* @param op_data the operator data passed in to H5Oiterate
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(long obj, MemorySegment name, MemorySegment info, MemorySegment op_data);
}
@@ -0,0 +1,46 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.*;
/**
* Information class for link callback for H5Piterate.
*
*/
public interface H5P_iterate_cb extends org.hdfgroup.javahdf5.H5P_iterate_t.Function {
/**
* @ingroup JCALLBK
*
* application callback for each property list
*
* @param plist the ID for the property list being iterated over
* @param name the name of the current property list
* @param op_data the operator data passed in to H5Piterate
*
* @return operation status
* A. Zero causes the iterator to continue, returning zero when all
* attributes have been processed.
* B. Positive causes the iterator to immediately return that positive
* value, indicating short-circuit success. The iterator can be
* restarted at the next attribute.
* C. Negative causes the iterator to immediately return that value,
* indicating failure. The iterator can be restarted at the next
* attribute.
*/
int apply(long id, MemorySegment name, MemorySegment iter_data);
}
@@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.callbacks;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import org.hdfgroup.javahdf5.*;
/**
* Data class for link callback for H5Piterate.
*
*/
public interface H5P_iterate_t {
/**
* public ArrayList iterdata = new ArrayList();
* Any derived interfaces must define the single public variable as above.
*/
}
@@ -0,0 +1,76 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.exceptions;
/**
* \page ERRORS Errors and Exceptions
* The class HDF5Exception returns errors from the Java HDF5 Interface.
*
* Two sub-classes of HDF5Exception are defined:
* <ol>
* <li>
* HDF5LibraryException -- errors raised by the HDF5 library code
* <li>
* HDF5JavaException -- errors raised by the HDF5 Java wrapper code
* </ol>
*
* These exceptions are sub-classed to represent specific error conditions, as
* needed. In particular, HDF5LibraryException has a sub-class for each major
* error code returned by the HDF5 library.
*
* @defgroup JERR HDF5 Library Exception Interface
*
*/
public class HDF5Exception extends RuntimeException {
/**
* the specified detail message of this exception
*/
protected String detailMessage = null;
/**
* @ingroup JERR
*
* Constructs an <code>HDF5Exception</code> with no specified detail
* message.
*/
public HDF5Exception() { super(); }
/**
* @ingroup JERR
*
* Constructs an <code>HDF5Exception</code> with the specified detail
* message.
*
* @param message
* the detail message.
*/
public HDF5Exception(String message)
{
super();
detailMessage = message;
}
/**
* @ingroup JERR
*
* Returns the detail message of this exception
*
* @return the detail message or <code>null</code> if this object does not
* have a detail message.
*/
@Override
public String getMessage()
{
return detailMessage;
}
}
@@ -0,0 +1,527 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.exceptions;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemoryLayout.PathElement;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.StructLayout;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.VarHandle;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import hdf.hdf5lib.H5;
import hdf.hdf5lib.HDF5Constants;
import org.hdfgroup.javahdf5.*;
/**
* \page ERRORSLIB HDF5 Library Errors and Exceptions
* The class HDF5LibraryException returns errors raised by the HDF5 library.
*
* Each major error code from the HDF5 Library is represented by a sub-class of
* this class, and by default the 'detailedMessage' is set according to the
* minor error code from the HDF5 Library.
* <p>
* For major and minor error codes, @see <b>@ref H5E</b> in the HDF5 library.
*
* @defgroup JERRLIB HDF5 Library JNI Exception Interface
*
*/
@SuppressWarnings("serial")
public class HDF5LibraryException extends HDF5Exception {
/** major error number of the first error on the HDF5 library error stack. */
private long majorErrorNumber = 0;
/** minor error number of the first error on the HDF5 library error stack. */
private long minorErrorNumber = 0;
static class WalkData {
public String err_desc = null;
public String func_name = null;
public int line = -1;
WalkData(String desc, String func, int lineno)
{
this.err_desc = new String(desc);
this.func_name = new String(func);
this.line = lineno;
}
}
static class H5EWalkCallback implements H5E_walk2_t.Function {
private static final ArrayList<WalkData> walkDataList = new ArrayList<>();
/** major error number of the first error on the HDF5 library error stack. */
private long majorErrorNumber = 0;
/** minor error number of the first error on the HDF5 library error stack. */
private long minorErrorNumber = 0;
public long getMajor() { return this.majorErrorNumber; }
public long getMinor() { return this.minorErrorNumber; }
/* major and minor error numbers */
final StructLayout H5E_num_t = MemoryLayout.structLayout(ValueLayout.JAVA_LONG.withName("maj_num"),
ValueLayout.JAVA_LONG.withName("min_num"));
/**
* This method is called by the HDF5 library during the error stack walk. It extracts the error
* description, function name, and line number from the H5E_error2_t structure and stores it in a
* list.
*
* @param nidx The index of the error in the stack.
* @param err_desc A MemorySegment containing the error description.
* @param err_nums The major and minor error numbers not used.
* @return 0 to continue walking the stack.
*/
// err_desc is a pointer to the H5E_error2_t structure
public int apply(int nidx, MemorySegment err_desc, MemorySegment err_nums)
{
try (Arena arena = Arena.ofConfined()) {
// Extract error information from the native structure
String errDesc = H5E_error2_t.desc(err_desc).getString(0);
String funcName = H5E_error2_t.func_name(err_desc).getString(0);
int line = H5E_error2_t.line(err_desc);
walkDataList.add(new WalkData(errDesc, funcName, line));
this.majorErrorNumber = H5E_error2_t.maj_num(err_desc);
this.minorErrorNumber = H5E_error2_t.min_num(err_desc);
}
return 0; // Continue walking
}
}
/**
* @ingroup JERRLIB
*
* Constructs an <code>HDF5LibraryException</code> with no specified detail
* message.
*/
public HDF5LibraryException()
{
super();
H5EWalkCallback callback = new H5EWalkCallback();
long stk_id = H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment callbackSegment = H5E_walk2_t.allocate(callback, arena);
final StructLayout H5E_num_t = MemoryLayout.structLayout(
ValueLayout.JAVA_LONG.withName("maj_num"), ValueLayout.JAVA_LONG.withName("min_num"));
// Walk the error stack
MemorySegment errorNums = arena.allocate(H5E_num_t); // For maj_num and min_num
/* Save current stack contents for future use */
if ((stk_id = H5Eget_current_stack()) >= 0) {
/* This will clear current stack */
int walkResult = (int)H5Ewalk2(stk_id, H5E_WALK_DOWNWARD(), callbackSegment, errorNums);
if (walkResult < 0) {
throw new IllegalStateException("Failed to walk HDF5 error stack.");
}
H5Eset_current_stack(stk_id);
}
else
throw new IllegalStateException("Failed to get current HDF5 error stack.");
this.majorErrorNumber = callback.getMajor();
this.minorErrorNumber = callback.getMinor();
if (detailMessage == null)
detailMessage = getMinorError(this.minorErrorNumber);
}
catch (Throwable e) {
e.printStackTrace();
}
}
/**
* @ingroup JERRLIB
*
* Constructs an <code>HDF5LibraryException</code> with the specified detail
* message.
*
* @param s
* the detail message.
*/
public HDF5LibraryException(String s)
{
this();
detailMessage = s;
}
/**
* @ingroup JERRLIB
*
* Get the major error number of the first error on the HDF5 library error
* stack.
*
* @return the major error number
*/
public long getMajorErrorNumber() { return this.majorErrorNumber; }
/**
* @ingroup JERRLIB
*
* Get the minor error number of the first error on the HDF5 library error
* stack.
*
* @return the minor error number
*/
public long getMinorErrorNumber() { return this.minorErrorNumber; }
/**
* @ingroup JERRLIB
*
* Return an error message for the minor error number.
*
* These messages come from <b>@ref H5E</b>.
*
* @param err_code
* the error code
*
* @return the string of the minor error
*/
public String getMinorError(long err_code)
{
if (err_code == 0) {
return "special zero no error";
}
else if (err_code == HDF5Constants.H5E_UNINITIALIZED) {
return "information is uninitialized";
}
else if (err_code == HDF5Constants.H5E_UNSUPPORTED) {
return "feature is unsupported";
}
else if (err_code == HDF5Constants.H5E_BADTYPE) {
return "incorrect type found";
}
else if (err_code == HDF5Constants.H5E_BADRANGE) {
return "argument out of range";
}
else if (err_code == HDF5Constants.H5E_BADVALUE) {
return "bad value for argument";
}
else if (err_code == HDF5Constants.H5E_NOSPACE) {
return "no space available for allocation";
}
else if (err_code == HDF5Constants.H5E_CANTCOPY) {
return "unable to copy object";
}
else if (err_code == HDF5Constants.H5E_CANTFREE) {
return "unable to free object";
}
else if (err_code == HDF5Constants.H5E_ALREADYEXISTS) {
return "Object already exists";
}
else if (err_code == HDF5Constants.H5E_CANTLOCK) {
return "Unable to lock object";
}
else if (err_code == HDF5Constants.H5E_CANTUNLOCK) {
return "Unable to unlock object";
}
else if (err_code == HDF5Constants.H5E_FILEEXISTS) {
return "file already exists";
}
else if (err_code == HDF5Constants.H5E_FILEOPEN) {
return "file already open";
}
else if (err_code == HDF5Constants.H5E_CANTCREATE) {
return "Can't create file";
}
else if (err_code == HDF5Constants.H5E_CANTOPENFILE) {
return "Can't open file";
}
else if (err_code == HDF5Constants.H5E_CANTCLOSEFILE) {
return "Can't close file";
}
else if (err_code == HDF5Constants.H5E_NOTHDF5) {
return "not an HDF5 format file";
}
else if (err_code == HDF5Constants.H5E_BADFILE) {
return "bad file ID accessed";
}
else if (err_code == HDF5Constants.H5E_TRUNCATED) {
return "file has been truncated";
}
else if (err_code == HDF5Constants.H5E_MOUNT) {
return "file mount error";
}
else if (err_code == HDF5Constants.H5E_CANTDELETEFILE) {
return "Unable to delete file";
}
else if (err_code == HDF5Constants.H5E_SEEKERROR) {
return "seek failed";
}
else if (err_code == HDF5Constants.H5E_READERROR) {
return "read failed";
}
else if (err_code == HDF5Constants.H5E_WRITEERROR) {
return "write failed";
}
else if (err_code == HDF5Constants.H5E_CLOSEERROR) {
return "close failed";
}
else if (err_code == HDF5Constants.H5E_OVERFLOW) {
return "address overflowed";
}
else if (err_code == HDF5Constants.H5E_FCNTL) {
return "file fcntl failed";
}
else if (err_code == HDF5Constants.H5E_CANTINIT) {
return "Can't initialize object";
}
else if (err_code == HDF5Constants.H5E_ALREADYINIT) {
return "object already initialized";
}
else if (err_code == HDF5Constants.H5E_CANTRELEASE) {
return "Can't release object";
}
else if (err_code == HDF5Constants.H5E_BADID) {
return "Can't find ID information";
}
else if (err_code == HDF5Constants.H5E_BADGROUP) {
return "Can't find group information";
}
else if (err_code == HDF5Constants.H5E_CANTREGISTER) {
return "Can't register new ID";
}
else if (err_code == HDF5Constants.H5E_CANTINC) {
return "Can't increment reference count";
}
else if (err_code == HDF5Constants.H5E_CANTDEC) {
return "Can't decrement reference count";
}
else if (err_code == HDF5Constants.H5E_NOIDS) {
return "Out of IDs for group";
}
else if (err_code == HDF5Constants.H5E_CANTFLUSH) {
return "Can't flush object from cache";
}
else if (err_code == HDF5Constants.H5E_CANTLOAD) {
return "Can't load object into cache";
}
else if (err_code == HDF5Constants.H5E_PROTECT) {
return "protected object error";
}
else if (err_code == HDF5Constants.H5E_NOTCACHED) {
return "object not currently cached";
}
else if (err_code == HDF5Constants.H5E_NOTFOUND) {
return "object not found";
}
else if (err_code == HDF5Constants.H5E_EXISTS) {
return "object already exists";
}
else if (err_code == HDF5Constants.H5E_CANTENCODE) {
return "Can't encode value";
}
else if (err_code == HDF5Constants.H5E_CANTDECODE) {
return "Can't decode value";
}
else if (err_code == HDF5Constants.H5E_CANTSPLIT) {
return "Can't split node";
}
else if (err_code == HDF5Constants.H5E_CANTINSERT) {
return "Can't insert object";
}
else if (err_code == HDF5Constants.H5E_CANTLIST) {
return "Can't list node";
}
else if (err_code == HDF5Constants.H5E_LINKCOUNT) {
return "bad object header link count";
}
else if (err_code == HDF5Constants.H5E_VERSION) {
return "wrong version number";
}
else if (err_code == HDF5Constants.H5E_ALIGNMENT) {
return "alignment error";
}
else if (err_code == HDF5Constants.H5E_BADMESG) {
return "unrecognized message";
}
else if (err_code == HDF5Constants.H5E_CANTDELETE) {
return "Can't delete message";
}
else if (err_code == HDF5Constants.H5E_CANTOPENOBJ) {
return "Can't open object";
}
else if (err_code == HDF5Constants.H5E_COMPLEN) {
return "name component is too long";
}
else if (err_code == HDF5Constants.H5E_LINK) {
return "link count failure";
}
else if (err_code == HDF5Constants.H5E_CANTCONVERT) {
return "Can't convert datatypes";
}
else if (err_code == HDF5Constants.H5E_BADSIZE) {
return "Bad size for object";
}
else if (err_code == HDF5Constants.H5E_CANTCLIP) {
return "Can't clip hyperslab region";
}
else if (err_code == HDF5Constants.H5E_CANTCOUNT) {
return "Can't count elements";
}
else if (err_code == HDF5Constants.H5E_CANTSELECT) {
return "Can't select hyperslab";
}
else if (err_code == HDF5Constants.H5E_CANTNEXT) {
return "Can't move to next iterator location";
}
else if (err_code == HDF5Constants.H5E_BADSELECT) {
return "Invalid selection";
}
else if (err_code == HDF5Constants.H5E_CANTGET) {
return "Can't get value";
}
else if (err_code == HDF5Constants.H5E_CANTSET) {
return "Can't set value";
}
else if (err_code == HDF5Constants.H5E_DUPCLASS) {
return "Duplicate class name in parent class";
}
else if (err_code == HDF5Constants.H5E_MPI) {
return "some MPI function failed";
}
else if (err_code == HDF5Constants.H5E_MPIERRSTR) {
return "MPI Error String";
}
else if (err_code == HDF5Constants.H5E_CANTRECV) {
return "can't receive messages from processes";
}
else if (err_code == HDF5Constants.H5E_CANTALLOC) {
return "can't allocate from file";
}
else if (err_code == HDF5Constants.H5E_NOFILTER) {
return "requested filter is not available";
}
else if (err_code == HDF5Constants.H5E_CALLBACK) {
return "callback failed";
}
else if (err_code == HDF5Constants.H5E_CANAPPLY) {
return "error from filter \"can apply\" callback";
}
else if (err_code == HDF5Constants.H5E_SETLOCAL) {
return "error from filter \"set local\" callback";
}
else {
return "undefined error(" + err_code + ")";
}
}
/**
* @ingroup JERRLIB
*
* Prints this <code>HDF5LibraryException</code>, the HDF5 Library error
* stack, and and the Java stack trace to the standard error stream.
*/
@Override
public void printStackTrace()
{
System.err.println(this);
printStackTrace0(null); // the HDF5 Library error stack
super.printStackTrace(); // the Java stack trace
}
/**
* @ingroup JERRLIB
*
* Prints this <code>HDF5LibraryException</code> the HDF5 Library error
* stack, and and the Java stack trace to the specified print stream.
*
* @param f
* the file print stream.
*/
public void printStackTrace(java.io.File f)
{
if ((f == null) || !f.exists() || f.isDirectory() || !f.canWrite()) {
printStackTrace();
}
else {
try {
java.io.FileOutputStream o = new java.io.FileOutputStream(f);
java.io.PrintWriter p = new java.io.PrintWriter(o);
p.println(this);
p.close();
}
catch (Exception ex) {
System.err.println(this);
};
// the HDF5 Library error stack
printStackTrace0(f.getPath());
super.printStackTrace(); // the Java stack trace
}
}
/*
* This private method calls the HDF5 library to extract the error codes
* and error stack.
*/
private void printStackTrace0(String file_name)
{
hdf.hdf5lib.H5.H5Eprint2(HDF5Constants.H5E_DEFAULT, null);
}
/*
* throwHDF5LibraryException() throws the sub-class Exception
* corresponding to the HDF5 error code.
*/
public static void throwHDF5LibraryException(long err_num, String errorMessage)
throws HDF5LibraryException
{
if (HDF5Constants.H5E_ARGS == err_num)
throw new HDF5FunctionArgumentException(errorMessage);
else if (HDF5Constants.H5E_RESOURCE == err_num)
throw new HDF5ResourceUnavailableException(errorMessage);
else if (HDF5Constants.H5E_INTERNAL == err_num)
throw new HDF5InternalErrorException(errorMessage);
else if (HDF5Constants.H5E_FILE == err_num)
throw new HDF5FileInterfaceException(errorMessage);
else if (HDF5Constants.H5E_IO == err_num)
throw new HDF5LowLevelIOException(errorMessage);
else if (HDF5Constants.H5E_FUNC == err_num)
throw new HDF5FunctionEntryExitException(errorMessage);
else if (HDF5Constants.H5E_ID == err_num)
throw new HDF5IdException(errorMessage);
else if (HDF5Constants.H5E_CACHE == err_num)
throw new HDF5MetaDataCacheException(errorMessage);
else if (HDF5Constants.H5E_BTREE == err_num)
throw new HDF5BtreeException(errorMessage);
else if (HDF5Constants.H5E_SYM == err_num)
throw new HDF5SymbolTableException(errorMessage);
else if (HDF5Constants.H5E_HEAP == err_num)
throw new HDF5HeapException(errorMessage);
else if (HDF5Constants.H5E_OHDR == err_num)
throw new HDF5ObjectHeaderException(errorMessage);
else if (HDF5Constants.H5E_DATATYPE == err_num)
throw new HDF5DatatypeInterfaceException(errorMessage);
else if (HDF5Constants.H5E_DATASPACE == err_num)
throw new HDF5DataspaceInterfaceException(errorMessage);
else if (HDF5Constants.H5E_DATASET == err_num)
throw new HDF5DatasetInterfaceException(errorMessage);
else if (HDF5Constants.H5E_STORAGE == err_num)
throw new HDF5DataStorageException(errorMessage);
else if (HDF5Constants.H5E_PLIST == err_num)
throw new HDF5PropertyListInterfaceException(errorMessage);
else if (HDF5Constants.H5E_ATTR == err_num)
throw new HDF5AttributeException(errorMessage);
else if (HDF5Constants.H5E_PLINE == err_num)
throw new HDF5DataFiltersException(errorMessage);
else if (HDF5Constants.H5E_EFL == err_num)
throw new HDF5ExternalFileListException(errorMessage);
else if (HDF5Constants.H5E_REFERENCE == err_num)
throw new HDF5ReferenceException(errorMessage);
throw new HDF5LibraryException(errorMessage);
}
}
+201
View File
@@ -0,0 +1,201 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hdfgroup</groupId>
<artifactId>@HDF5_JAVA_ARTIFACT_ID@</artifactId>
<version>@HDF5_PACKAGE_VERSION@@HDF5_MAVEN_VERSION_SUFFIX@</version>
<packaging>jar</packaging>
<name>HDF5 Java Bindings</name>
<description>Java bindings for the HDF5 scientific data format library</description>
<url>https://github.com/HDFGroup/hdf5</url>
<licenses>
<license>
<name>BSD-style License</name>
<url>https://github.com/HDFGroup/hdf5/blob/develop/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<organization>The HDF Group</organization>
<organizationUrl>https://www.hdfgroup.org</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:https://github.com/HDFGroup/hdf5.git</connection>
<developerConnection>scm:git:git@github.com:HDFGroup/hdf5.git</developerConnection>
<url>https://github.com/HDFGroup/hdf5</url>
<tag>@HDF5_PACKAGE_VERSION@</tag>
</scm>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/HDFGroup/hdf5/issues</url>
</issueManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hdf5.version>@HDF5_PACKAGE_VERSION@</hdf5.version>
<hdf5.platform>@HDF5_MAVEN_PLATFORM@</hdf5.platform>
<hdf5.architecture>@HDF5_MAVEN_ARCHITECTURE@</hdf5.architecture>
</properties>
<dependencies>
<!-- SLF4J API for logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Enable-Native-Access>ALL-UNNAMED</Enable-Native-Access>
<HDF5-Version>${hdf5.version}</HDF5-Version>
<HDF5-Platform>${hdf5.platform}</HDF5-Platform>
<HDF5-Architecture>${hdf5.architecture}</HDF5-Architecture>
<Build-Time>@CMAKE_CONFIGURE_DATE@</Build-Time>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<source>11</source>
<failOnError>false</failOnError>
<quiet>true</quiet>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<!-- Platform-specific profiles for native library inclusion -->
<profile>
<id>linux-x86_64</id>
<activation>
<property>
<name>hdf5.platform</name>
<value>linux-x86_64</value>
</property>
</activation>
<properties>
<classifier>linux-x86_64</classifier>
</properties>
</profile>
<profile>
<id>windows-x86_64</id>
<activation>
<property>
<name>hdf5.platform</name>
<value>windows-x86_64</value>
</property>
</activation>
<properties>
<classifier>windows-x86_64</classifier>
</properties>
</profile>
<profile>
<id>macos-x86_64</id>
<activation>
<property>
<name>hdf5.platform</name>
<value>macos-x86_64</value>
</property>
</activation>
<properties>
<classifier>macos-x86_64</classifier>
</properties>
</profile>
<profile>
<id>macos-aarch64</id>
<activation>
<property>
<name>hdf5.platform</name>
<value>macos-aarch64</value>
</property>
</activation>
<properties>
<classifier>macos-aarch64</classifier>
</properties>
</profile>
<!-- Development snapshot profile -->
<profile>
<id>snapshot</id>
<activation>
<property>
<name>maven.deploy.snapshot</name>
<value>true</value>
</property>
</activation>
<properties>
<hdf5.version.suffix>-SNAPSHOT</hdf5.version.suffix>
</properties>
</profile>
</profiles>
</project>
@@ -0,0 +1,330 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
/**
* Information struct for H5Pget_mdc_config/H5Pset_mdc_config
*
*/
public class H5AC_cache_config_t implements Serializable {
private static final long serialVersionUID = -6748085696476149972L;
// general configuration fields
/**
* version: Integer field containing the version number of this version
* of the H5AC_cache_config_t structure. Any instance of
* H5AC_cache_config_t passed to the cache must have a known
* version number, or an error will be flagged.
*/
public int version;
/**
* rpt_fcn_enabled: Boolean field used to enable and disable the default
* reporting function. This function is invoked every time the
* automatic cache resize code is run, and reports on its activities.
*
* This is a debugging function, and should normally be turned off.
*/
public boolean rpt_fcn_enabled;
/**
* open_trace_file: Boolean field indicating whether the trace_file_name
* field should be used to open a trace file for the cache.
*
* *** DEPRECATED *** Use H5Fstart/stop logging functions instead
*/
public boolean open_trace_file;
/**
* close_trace_file: Boolean field indicating whether the current trace
* file (if any) should be closed.
*
* *** DEPRECATED *** Use H5Fstart/stop logging functions instead
*/
public boolean close_trace_file;
/**
* trace_file_name: Full path of the trace file to be opened if the
* open_trace_file field is TRUE.
*
* *** DEPRECATED *** Use H5Fstart/stop logging functions instead
*/
public String trace_file_name;
/**
* evictions_enabled: Boolean field used to either report the current
* evictions enabled status of the cache, or to set the cache's
* evictions enabled status.
*/
public boolean evictions_enabled;
/**
* set_initial_size: Boolean flag indicating whether the size of the
* initial size of the cache is to be set to the value given in
* the initial_size field. If set_initial_size is FALSE, the
* initial_size field is ignored.
*/
public boolean set_initial_size;
/**
* initial_size: If enabled, this field contain the size the cache is
* to be set to upon receipt of this structure. Needless to say,
* initial_size must lie in the closed interval [min_size, max_size].
*/
public long initial_size;
/**
* min_clean_fraction: double in the range 0 to 1 indicating the fraction
* of the cache that is to be kept clean. This field is only used
* in parallel mode. Typical values are 0.1 to 0.5.
*/
public double min_clean_fraction;
/**
* max_size: Maximum size to which the cache can be adjusted. The
* supplied value must fall in the closed interval
* [MIN_MAX_CACHE_SIZE, MAX_MAX_CACHE_SIZE]. Also, max_size must
* be greater than or equal to min_size.
*/
public long max_size;
/**
* min_size: Minimum size to which the cache can be adjusted. The
* supplied value must fall in the closed interval
* [H5C__MIN_MAX_CACHE_SIZE, H5C__MAX_MAX_CACHE_SIZE]. Also, min_size
* must be less than or equal to max_size.
*/
public long min_size;
/**
* epoch_length: Number of accesses on the cache over which to collect
* hit rate stats before running the automatic cache resize code,
* if it is enabled.
*/
public long epoch_length;
// size increase control fields
/**
* incr_mode: Instance of the H5C_cache_incr_mode enumerated type whose
* value indicates how we determine whether the cache size should be
* increased. At present there are two possible values.
*/
public int incr_mode;
/**
* lower_hr_threshold: Lower hit rate threshold. If the increment mode
* (incr_mode) is H5C_incr__threshold and the hit rate drops below the
* value supplied in this field in an epoch, increment the cache size by
* size_increment. Note that cache size may not be incremented above
* max_size, and that the increment may be further restricted by the
* max_increment field if it is enabled.
*/
public double lower_hr_threshold;
/**
* increment: Double containing the multiplier used to derive the new
* cache size from the old if a cache size increment is triggered.
* The increment must be greater than 1.0, and should not exceed 2.0.
*/
public double increment;
/**
* apply_max_increment: Boolean flag indicating whether the max_increment
* field should be used to limit the maximum cache size increment.
*/
public boolean apply_max_increment;
/**
* max_increment: If enabled by the apply_max_increment field described
* above, this field contains the maximum number of bytes by which the
* cache size can be increased in a single re-size.
*/
public long max_increment;
/**
* flash_incr_mode: Instance of the H5C_cache_flash_incr_mode enumerated
* type whose value indicates whether and by which algorithm we should
* make flash increases in the size of the cache to accommodate insertion
* of large entries and large increases in the size of a single entry.
*/
public int flash_incr_mode;
/**
* flash_multiple: Double containing the multiple described above in the
* H5C_flash_incr__add_space section of the discussion of the
* flash_incr_mode section. This field is ignored unless flash_incr_mode
* is H5C_flash_incr__add_space.
*/
public double flash_multiple;
/**
* flash_threshold: Double containing the factor by which current max cache
* size is multiplied to obtain the size threshold for the add_space flash
* increment algorithm. The field is ignored unless flash_incr_mode is
* H5C_flash_incr__add_space.
*/
public double flash_threshold;
// size decrease control fields
/**
* decr_mode: Instance of the H5C_cache_decr_mode enumerated type whose
* value indicates how we determine whether the cache size should be
* decreased. At present there are four possibilities.
*/
public int decr_mode;
/**
* upper_hr_threshold: Upper hit rate threshold. The use of this field
* varies according to the current decr_mode.
*/
public double upper_hr_threshold;
/**
* decrement: This field is only used when the decr_mode is
* H5C_decr__threshold.
*/
public double decrement;
/**
* apply_max_decrement: Boolean flag used to determine whether decrements
* in cache size are to be limited by the max_decrement field.
*/
public boolean apply_max_decrement;
/**
* max_decrement: Maximum number of bytes by which the cache size can be
* decreased in a single re-size. Note that decrements may also be
* restricted by the min_size of the cache, and (in age out modes) by
* the empty_reserve field.
*/
public long max_decrement;
/**
* epochs_before_eviction: Integer field used in H5C_decr__age_out and
* H5C_decr__age_out_with_threshold decrement modes.
*/
public int epochs_before_eviction;
/**
* apply_empty_reserve: Boolean field controlling whether the empty_reserve
* field is to be used in computing the new cache size when the
* decr_mode is H5C_decr__age_out or H5C_decr__age_out_with_threshold.
*/
public boolean apply_empty_reserve;
/**
* empty_reserve: To avoid a constant racheting down of cache size by small
* amounts in the H5C_decr__age_out and H5C_decr__age_out_with_threshold
* modes, this field allows one to require that any cache size
* reductions leave the specified fraction of unused space in the cache.
*/
public double empty_reserve;
// parallel configuration fields
/**
* dirty_bytes_threshold: Threshold of dirty byte creation used to
* synchronize updates between caches.
*/
public long dirty_bytes_threshold;
/**
* metadata_write_strategy: Integer field containing a code indicating the
* desired metadata write strategy.
*/
public int metadata_write_strategy;
/**
* H5AC_cache_config_t is a public structure intended for use in public APIs.
* At least in its initial incarnation, it is basically a copy of struct
* H5C_auto_size_ctl_t, minus the report_fcn field, and plus the
* dirty_bytes_threshold field.
*
* @param version: Integer field containing the version number of this version
* @param rpt_fcn_enabled: Boolean field used to enable and disable the default reporting function.
* @param open_trace_file: Boolean field indicating whether the trace_file_name
* field should be used to open a trace file for the cache.
* @param close_trace_file: Boolean field indicating whether the current trace
* file (if any) should be closed.
* @param trace_file_name: Full path of the trace file to be opened if the
* open_trace_file field is TRUE.
* @param evictions_enabled: Boolean field used to either report or set the current
* evictions enabled status of the cache.
* @param set_initial_size: Boolean flag indicating whether the size of the
* initial size of the cache is to be set to the value given in
* the initial_size field.
* @param initial_size: If enabled, this field contain the size the cache is
* to be set to upon receipt of this structure.
* @param min_clean_fraction: double in the range 0 to 1 indicating the fraction
* of the cache that is to be kept clean.
* @param max_size: Maximum size to which the cache can be adjusted.
* @param min_size: Minimum size to which the cache can be adjusted.
* @param epoch_length: Number of accesses on the cache over which to collect
* hit rate stats before running the automatic cache resize code.
* @param incr_mode: Instance of the H5C_cache_incr_mode enumerated type.
* @param lower_hr_threshold: Lower hit rate threshold.
* @param increment: Double containing the multiplier used to derive the new
* cache size from the old if a cache size increment is triggered.
* @param apply_max_increment: Boolean flag indicating whether the max_increment
* field should be used to limit the maximum cache size increment.
* @param max_increment: If enabled by the apply_max_increment field described
* above, this field contains the maximum number of bytes by which the
* cache size can be increased in a single re-size.
* @param flash_incr_mode: Instance of the H5C_cache_flash_incr_mode enumerated
* type whose value indicates whether and by which algorithm we should
* make flash increases in the size of the cache to accommodate insertion
* of large entries and large increases in the size of a single entry.
* @param flash_multiple: Double containing the multiple described above in the
* H5C_flash_incr__add_space section of the discussion of the
* flash_incr_mode section.
* @param flash_threshold: Double containing the factor by which current max cache
* size is multiplied to obtain the size threshold for the add_space flash
* increment algorithm.
* @param decr_mode: Instance of the H5C_cache_decr_mode enumerated type whose
* value indicates how we determine whether the cache size should be
* decreased.
* @param upper_hr_threshold: Upper hit rate threshold. The use of this field
* varies according to the current decr_mode.
* @param decrement: This field is only used when the decr_mode is
* H5C_decr__threshold.
* @param apply_max_decrement: Boolean flag used to determine whether decrements
* in cache size are to be limited by the max_decrement field.
* @param max_decrement: Maximum number of bytes by which the cache size can be
* decreased in a single re-size.
* @param epochs_before_eviction: Integer field used in H5C_decr__age_out and
* H5C_decr__age_out_with_threshold decrement modes.
* @param apply_empty_reserve: Boolean field controlling whether the empty_reserve
* field is to be used in computing the new cache size when the
* decr_mode is H5C_decr__age_out or H5C_decr__age_out_with_threshold.
* @param empty_reserve: To avoid a constant racheting down of cache size by small
* amounts in the H5C_decr__age_out and H5C_decr__age_out_with_threshold
* modes.
* @param dirty_bytes_threshold: Threshold of dirty byte creation used to
* synchronize updates between caches.
* @param metadata_write_strategy: Integer field containing a code indicating the
* desired metadata write strategy.
*/
public H5AC_cache_config_t(int version, boolean rpt_fcn_enabled, boolean open_trace_file,
boolean close_trace_file, String trace_file_name, boolean evictions_enabled,
boolean set_initial_size, long initial_size, double min_clean_fraction,
long max_size, long min_size, long epoch_length, int incr_mode,
double lower_hr_threshold, double increment, boolean apply_max_increment,
long max_increment, int flash_incr_mode, double flash_multiple,
double flash_threshold, int decr_mode, double upper_hr_threshold,
double decrement, boolean apply_max_decrement, long max_decrement,
int epochs_before_eviction, boolean apply_empty_reserve, double empty_reserve,
long dirty_bytes_threshold, int metadata_write_strategy)
{
this.version = version;
this.rpt_fcn_enabled = rpt_fcn_enabled;
this.open_trace_file = open_trace_file;
this.close_trace_file = close_trace_file;
this.trace_file_name = trace_file_name;
this.evictions_enabled = evictions_enabled;
this.set_initial_size = set_initial_size;
this.initial_size = initial_size;
this.min_clean_fraction = min_clean_fraction;
this.max_size = max_size;
this.min_size = min_size;
this.epoch_length = epoch_length;
this.incr_mode = incr_mode;
this.lower_hr_threshold = lower_hr_threshold;
this.increment = increment;
this.apply_max_increment = apply_max_increment;
this.max_increment = max_increment;
this.flash_incr_mode = flash_incr_mode;
this.flash_multiple = flash_multiple;
this.flash_threshold = flash_threshold;
this.decr_mode = decr_mode;
this.upper_hr_threshold = upper_hr_threshold;
this.decrement = decrement;
this.apply_max_decrement = apply_max_decrement;
this.max_decrement = max_decrement;
this.epochs_before_eviction = epochs_before_eviction;
this.apply_empty_reserve = apply_empty_reserve;
this.empty_reserve = empty_reserve;
this.dirty_bytes_threshold = dirty_bytes_threshold;
this.metadata_write_strategy = metadata_write_strategy;
}
}
+39
View File
@@ -0,0 +1,39 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
/**
* Information struct for Attribute (For H5Aget_info/H5Aget_info_by_idx/H5Aget_info_by_name)
*
*/
public class H5A_info_t implements Serializable {
private static final long serialVersionUID = 2791443594041667613L;
/** Indicate if creation order is valid */
public boolean corder_valid;
/** Creation order of attribute */
public long corder;
/** Character set of attribute name */
public int cset;
/** Size of raw data */
public long data_size;
public H5A_info_t(boolean corder_valid, long corder, int cset, long data_size)
{
this.corder_valid = corder_valid;
this.corder = corder;
this.cset = cset;
this.data_size = data_size;
}
}
@@ -0,0 +1,147 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.io.Serializable;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.*;
/**
* Java representation of the ROS3 VFD file access property list (fapl)
* structure.
*
* Used for the access of files hosted remotely on S3 by Amazon.
*
* For simplicity, implemented assuming that all ROS3 fapls have components:
* - version
* - authenticate
* - aws_region
* - secret_id
* - secret_key
*
* Future implementations may be created to enable different fapl "shapes"
* depending on provided version.
*
* proposed:
*
* H5FD_ros3_fapl_t (super class, has only version field)
* H5FD_ros3_fapl_v1_t (extends super with Version 1 components)
* H5FD_ros3_fapl_v2_t (extends super with Version 2 components)
* and so on, for each version
*
* "super" is passed around, and is version-checked and re-cast as
* appropriate
*/
public class H5FD_ros3_fapl_t implements Serializable {
private static final long serialVersionUID = 8985533001471224030L;
/** Version number of the H5FD_ros3_fapl_t structure */
public int version;
/** Flag TRUE or FALSE whether or not requests are to be authenticated with the AWS4 algorithm. */
public boolean authenticate;
/** region "aws region" for authenticating request */
public String aws_region;
/** id "secret id" or "access id" for authenticating request */
public String secret_id;
/** key "secret key" or "access key" for authenticating request */
public String secret_key;
/**
* Create a "default" fapl_t structure, for anonymous access.
*/
public H5FD_ros3_fapl_t()
{
/* H5FD_ros3_fapl_t("", "", ""); */ /* defer */
this.version = 1;
this.authenticate = false;
this.aws_region = "";
this.secret_id = "";
this.secret_key = "";
}
/**
* Create a fapl_t structure with the specified components.
* If all are the empty string, is anonymous (non-authenticating).
* Region and ID must both be supplied for authentication.
*
* @param region "aws region" for authenticating request
* @param id "secret id" or "access id" for authenticating request
* @param key "secret key" or "access key" for authenticating request
*/
public H5FD_ros3_fapl_t(String region, String id, String key)
{
this.version = 1; /* must equal H5FD_CURR_ROS3_FAPL_T_VERSION */
/* as found in H5FDros3.h */
if (region == null)
region = "";
else
this.aws_region = region;
if (id == null)
id = "";
else
this.secret_id = id;
if (key == null)
key = "";
else
this.secret_key = key;
if (region == null && id == null && key == null)
this.authenticate = false;
else if (region != null && id != null)
this.authenticate = true;
}
@Override
public boolean equals(Object o)
{
if (o == null)
return false;
if (!(o instanceof H5FD_ros3_fapl_t))
return false;
H5FD_ros3_fapl_t other = (H5FD_ros3_fapl_t)o;
if (this.version != other.version)
return false;
if (!this.aws_region.equals(other.aws_region))
return false;
if (!this.secret_key.equals(other.secret_key))
return false;
if (!this.secret_id.equals(other.secret_id))
return false;
return true;
}
@Override
public int hashCode()
{
/* this is a _very bad_ hash algorithm for purposes of hashing! */
/* implemented to satisfy the "contract" regarding equality */
int k = (int)this.version;
k += this.aws_region.length();
k += this.secret_id.length();
k += this.secret_key.length();
return k;
}
@Override
public String toString()
{
return "H5FD_ros3_fapl_t (Version:" + this.version + ") {"
+ "\n aws_region : " + this.aws_region + "\n secret_id : " + this.secret_id +
"\n secret_key : " + this.secret_key + "\n}\n";
}
}
+101
View File
@@ -0,0 +1,101 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.io.Serializable;
import java.lang.foreign.Arena;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SequenceLayout;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.*;
/**
* Information struct for object (for H5Fget_info)
*
*/
public class H5F_info2_t implements Serializable {
private static final long serialVersionUID = 4691681162544054518L;
/** Superblock version number */
public int super_version;
/** Superblock size */
public long super_size;
/** Superblock extension size */
public long super_ext_size;
/** Version number of file free space management */
public int free_version;
/** Free space manager metadata size */
public long free_meta_size;
/** Amount of free space in the file */
public long free_tot_space;
/** Version number of shared object header info */
public int sohm_version;
/** Shared object header message header size */
public long sohm_hdr_size;
/** Shared object header message index and heap size */
public hdf.hdf5lib.structs.H5_ih_info_t sohm_msgs_info;
/**
* Constructor for current "global" information about file
* @param super_version: Superblock version number
* @param super_size: Superblock size
* @param super_ext_size: Superblock extension size
* @param free_version: Version number of file free space management
* @param free_meta_size: Free space manager metadata size
* @param free_tot_space: Amount of free space in the file
* @param sohm_version: Version number of shared object header info
* @param sohm_hdr_size: Shared object header message header size
* @param sohm_msgs_info: Shared object header message index and heap size
*/
public H5F_info2_t(int super_version, long super_size, long super_ext_size, int free_version,
long free_meta_size, long free_tot_space, int sohm_version, long sohm_hdr_size,
hdf.hdf5lib.structs.H5_ih_info_t sohm_msgs_info)
{
this.super_version = super_version;
this.super_size = super_size;
this.super_ext_size = super_ext_size;
this.free_version = free_version;
this.free_meta_size = free_meta_size;
this.free_tot_space = free_tot_space;
this.sohm_version = sohm_version;
this.sohm_hdr_size = sohm_hdr_size;
this.sohm_msgs_info = sohm_msgs_info;
}
/**
* Constructor for current "global" information about file
* @param info_segment: Memory segment for H5F_info2_t
*/
public H5F_info2_t(MemorySegment finfo_segment)
{
// Unpack the H5F_info2_t from the MemorySegment
MemorySegment super_segment = org.hdfgroup.javahdf5.H5F_info2_t.super_(finfo_segment);
MemorySegment free_segment = org.hdfgroup.javahdf5.H5F_info2_t.free(finfo_segment);
MemorySegment sohm_segment = org.hdfgroup.javahdf5.H5F_info2_t.sohm(finfo_segment);
MemorySegment sohm_ih_segment = org.hdfgroup.javahdf5.H5F_info2_t.sohm.msgs_info(sohm_segment);
this.sohm_msgs_info = new hdf.hdf5lib.structs.H5_ih_info_t(
org.hdfgroup.javahdf5.H5_ih_info_t.index_size(sohm_ih_segment),
org.hdfgroup.javahdf5.H5_ih_info_t.heap_size(sohm_ih_segment));
this.super_version = org.hdfgroup.javahdf5.H5F_info2_t.super_.version(super_segment);
this.super_size = org.hdfgroup.javahdf5.H5F_info2_t.super_.super_size(super_segment);
this.super_ext_size = org.hdfgroup.javahdf5.H5F_info2_t.super_.super_ext_size(super_segment);
this.free_version = org.hdfgroup.javahdf5.H5F_info2_t.free.version(free_segment);
this.free_meta_size = org.hdfgroup.javahdf5.H5F_info2_t.free.meta_size(free_segment);
this.free_tot_space = org.hdfgroup.javahdf5.H5F_info2_t.free.tot_space(free_segment);
this.sohm_version = org.hdfgroup.javahdf5.H5F_info2_t.sohm.version(sohm_segment);
this.sohm_hdr_size = org.hdfgroup.javahdf5.H5F_info2_t.sohm.hdr_size(sohm_segment);
}
}
+40
View File
@@ -0,0 +1,40 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
/**
* Information struct for group (for H5Gget_info/H5Gget_info_by_name/H5Gget_info_by_idx)
*
*/
public class H5G_info_t implements Serializable {
private static final long serialVersionUID = -3746463015312132912L;
/** Type of storage for links in group */
public int storage_type;
/** Number of links in group */
public long nlinks;
/** Current max. creation order value for group */
public long max_corder;
/** Whether group has a file mounted on it */
public boolean mounted;
/** Constructor for using val_size portion of C union */
public H5G_info_t(int storage_type, long nlinks, long max_corder, boolean mounted)
{
this.storage_type = storage_type;
this.nlinks = nlinks;
this.max_corder = max_corder;
this.mounted = mounted;
}
}
+86
View File
@@ -0,0 +1,86 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import hdf.hdf5lib.HDF5Constants;
import hdf.hdf5lib.structs.H5O_token_t;
/**
* Information struct for link (for H5Lget_info/H5Lget_info_by_idx)
*
*/
public class H5L_info_t implements Serializable {
private static final long serialVersionUID = -4754320605310155033L;
/** Type of link */
public int type;
/** Indicate if creation order is valid */
public boolean corder_valid;
/** Creation order */
public long corder;
/** Character set of link name */
public int cset;
/** Character set of link name */
public H5O_token_t token;
/** Size of a soft link or user-defined link value */
public long val_size;
/** Constructor for using object token portion of C union */
public H5L_info_t(int type, boolean corder_valid, long corder, int cset, H5O_token_t token)
{
this.type = type;
this.corder_valid = corder_valid;
this.corder = corder;
this.cset = cset;
this.token = token;
this.val_size = -1;
}
/** Constructor for using val_size portion of C union */
public H5L_info_t(int type, boolean corder_valid, long corder, int cset, long val_size)
{
this.type = type;
this.corder_valid = corder_valid;
this.corder = corder;
this.cset = cset;
this.token = HDF5Constants.H5O_TOKEN_UNDEF;
this.val_size = val_size;
}
/** Constructor for using val_size portion of C union */
public H5L_info_t(MemorySegment linfo_segment)
{
// Unpack the H5L_info2_t from the MemorySegment
MemorySegment u_segment = org.hdfgroup.javahdf5.H5L_info2_t.u(linfo_segment);
if (org.hdfgroup.javahdf5.H5L_info2_t.type(linfo_segment) == HDF5Constants.H5L_TYPE_HARD) {
this.token =
new hdf.hdf5lib.structs.H5O_token_t(org.hdfgroup.javahdf5.H5L_info2_t.u.token(u_segment));
this.type = org.hdfgroup.javahdf5.H5L_info2_t.type(linfo_segment);
this.corder_valid = org.hdfgroup.javahdf5.H5L_info2_t.corder_valid(linfo_segment);
this.corder = org.hdfgroup.javahdf5.H5L_info2_t.corder(linfo_segment);
this.cset = org.hdfgroup.javahdf5.H5L_info2_t.cset(linfo_segment);
this.val_size = -1;
}
else {
this.type = org.hdfgroup.javahdf5.H5L_info2_t.type(linfo_segment);
this.corder_valid = org.hdfgroup.javahdf5.H5L_info2_t.corder_valid(linfo_segment);
this.corder = org.hdfgroup.javahdf5.H5L_info2_t.corder(linfo_segment);
this.cset = org.hdfgroup.javahdf5.H5L_info2_t.cset(linfo_segment);
this.token = HDF5Constants.H5O_TOKEN_UNDEF;
this.val_size = org.hdfgroup.javahdf5.H5L_info2_t.u.val_size(u_segment);
}
}
}
@@ -0,0 +1,93 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
/**
* Information struct for object header metadata (for H5Oget_info/H5Oget_info_by_name/H5Oget_info_by_idx)
*
*/
public class H5O_hdr_info_t implements Serializable {
private static final long serialVersionUID = 7883826382952577189L;
/** Version number of header format in file */
public int version;
/** Number of object header messages */
public int nmesgs;
/** Number of object header chunks */
public int nchunks;
/** Object header status flags */
public int flags;
/** Total space for storing object header in file */
public long space_total;
/** Space within header for object header metadata information */
public long space_meta;
/** Space within header for actual message information */
public long space_mesg;
/** Free space within object header */
public long space_free;
/** Flags to indicate presence of message type in header */
public long mesg_present;
/** Flags to indicate message type is shared in header */
public long mesg_shared;
public H5O_hdr_info_t(int version, int nmesgs, int nchunks, int flags, long space_total, long space_meta,
long space_mesg, long space_free, long mesg_present, long mesg_shared)
{
this.version = version;
this.nmesgs = nmesgs;
this.nchunks = nchunks;
this.flags = flags;
this.space_total = space_total;
this.space_meta = space_meta;
this.space_mesg = space_mesg;
this.space_free = space_free;
this.mesg_present = mesg_present;
this.mesg_shared = mesg_shared;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof H5O_hdr_info_t))
return false;
H5O_hdr_info_t info = (H5O_hdr_info_t)o;
if (this.version != info.version)
return false;
if (this.nmesgs != info.nmesgs)
return false;
if (this.nchunks != info.nchunks)
return false;
if (this.flags != info.flags)
return false;
if (this.space_total != info.space_total)
return false;
if (this.space_meta != info.space_meta)
return false;
if (this.space_mesg != info.space_mesg)
return false;
if (this.space_free != info.space_free)
return false;
if (this.mesg_present != info.mesg_present)
return false;
if (this.mesg_shared != info.mesg_shared)
return false;
return true;
}
}
@@ -0,0 +1,57 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
/**
* Information struct for native HDF5 object info, such as object header metadata (for
* H5Oget_info/H5Oget_info_by_name/H5Oget_info_by_idx).
*
*/
public class H5O_native_info_t implements Serializable {
private static final long serialVersionUID = 7883826382952577189L;
/** Object header information */
public H5O_hdr_info_t hdr_info;
/* Extra metadata storage for obj & attributes */
/** v1/v2 B-tree and local/fractal heap for groups, B-tree for chunked datasets */
public H5_ih_info_t obj_info;
/** v2 B-tree and heap for attributes */
public H5_ih_info_t attr_info;
public H5O_native_info_t(H5O_hdr_info_t oheader_info, H5_ih_info_t obj_info, H5_ih_info_t attr_info)
{
this.hdr_info = oheader_info;
this.obj_info = obj_info;
this.attr_info = attr_info;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof H5O_native_info_t))
return false;
H5O_native_info_t info = (H5O_native_info_t)o;
if (!this.hdr_info.equals(info.hdr_info) || !this.obj_info.equals(info.obj_info) ||
!this.attr_info.equals(info.attr_info))
return false;
return true;
}
}
+63
View File
@@ -0,0 +1,63 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import static org.hdfgroup.javahdf5.hdf5_h.*;
import java.io.Serializable;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.util.Arrays;
import hdf.hdf5lib.HDF5Constants;
import org.hdfgroup.javahdf5.*;
/**
* Object token, which is a unique and permanent identifier, for an HDF5 object within a container.
*
*/
public class H5O_token_t implements Serializable {
private static final long serialVersionUID = -4754320605310155032L;
/**
* Tokens are unique and permanent identifiers that are
* used to reference HDF5 objects in a container.
* Use basic byte array to store the dat
*/
public byte[] data;
public H5O_token_t(byte[] data) { this.data = data; }
public H5O_token_t(MemorySegment data) { this.data = data.toArray(ValueLayout.JAVA_BYTE); }
/**
* Check if token data is undefined
*
* @return true if token data is undefined
*/
public boolean isUndefined() { return this.equals(HDF5Constants.H5O_TOKEN_UNDEF); }
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof H5O_token_t))
return false;
H5O_token_t token = (H5O_token_t)o;
return Arrays.equals(this.data, token.data);
}
}
@@ -0,0 +1,69 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package hdf.hdf5lib.structs;
import java.io.Serializable;
import java.lang.foreign.Arena;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SequenceLayout;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
/**
* Information struct for group (for H5Gget_info/H5Gget_info_by_name/H5Gget_info_by_idx)
*
*/
public class H5_ih_info_t implements Serializable {
private static final long serialVersionUID = -142238015615462707L;
/** btree and/or list size of index */
public long index_size;
/** btree and/or list size of hp */
public long heap_size;
public H5_ih_info_t(long index_size, long heap_size)
{
this.index_size = index_size;
this.heap_size = heap_size;
}
public H5_ih_info_t(MemorySegment info_segment)
{
MemoryLayout ilayout = MemoryLayout.structLayout(ValueLayout.JAVA_LONG.withName("index_size"),
ValueLayout.JAVA_LONG.withName("heap_size"));
this.index_size = info_segment.get(
ValueLayout.JAVA_LONG, ilayout.byteOffset(MemoryLayout.PathElement.groupElement("index_size")));
this.heap_size = info_segment.get(
ValueLayout.JAVA_LONG, ilayout.byteOffset(MemoryLayout.PathElement.groupElement("heap_size")));
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof H5_ih_info_t))
return false;
H5_ih_info_t info = (H5_ih_info_t)o;
if (this.index_size != info.index_size)
return false;
if (this.heap_size != info.heap_size)
return false;
return true;
}
}
+40
View File
@@ -0,0 +1,40 @@
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA_JSRC Java)
set (CMAKE_VERBOSE_MAKEFILE 1)
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${HDF5_JAVA_JSRC_BINARY_DIR}")
file (GLOB HDF5_JAVA_JSRC_SOURCES
LIST_DIRECTORIES false
${HDF5_JAVA_JSRC_BINARY_DIR}/org/hdfgroup/javahdf5/*.java
)
file (WRITE ${PROJECT_BINARY_DIR}/Manifest.txt
"Enable-Native-Access: ALL-UNNAMED
"
)
set (CMAKE_JAVA_INCLUDE_PATH "${HDF5_JAVA_LOGGING_JAR}")
# Set version suffix for snapshots vs releases
if (HDF5_ENABLE_MAVEN_DEPLOY AND HDF5_MAVEN_SNAPSHOT)
set (HDF5_JAVAHDF5_VERSION_SUFFIX "-SNAPSHOT")
else ()
set (HDF5_JAVAHDF5_VERSION_SUFFIX "")
endif ()
add_jar (${HDF5_JAVA_JSRC_LIB_TARGET} OUTPUT_NAME "${HDF5_JAVA_JSRC_LIB_TARGET}-${HDF5_PACKAGE_VERSION}${HDF5_JAVAHDF5_VERSION_SUFFIX}" MANIFEST ${PROJECT_BINARY_DIR}/Manifest.txt ${HDF5_JAVA_JSRC_SOURCES})
install_jar (${HDF5_JAVA_JSRC_LIB_TARGET} LIBRARY DESTINATION ${HDF5_INSTALL_JAR_DIR} COMPONENT libraries)
get_target_property (${HDF5_JAVA_JSRC_LIB_TARGET}_JAR_FILE ${HDF5_JAVA_JSRC_LIB_TARGET} JAR_FILE)
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS_TO_EXPORT "${HDF5_JAVA_JARS_TO_EXPORT};${${HDF5_JAVA_JSRC_LIB_TARGET}_JAR_FILE}")
SET_GLOBAL_VARIABLE (HDF5_JAVAHDF5_JARS ${${HDF5_JAVA_JSRC_LIB_TARGET}_JAR_FILE})
SET_GLOBAL_VARIABLE (HDF5_JAVA_JARS "${HDF5_JAVA_JARS};${${HDF5_JAVA_JSRC_LIB_TARGET}_JAR_FILE}")
set_target_properties (${HDF5_JAVA_JSRC_LIB_TARGET} PROPERTIES FOLDER libraries/java)
if (HDF5_ENABLE_FORMATTERS)
clang_format (HDF5_JAVA_SRC_FORMAT ${HDF5_JAVA_JSRC_SOURCES})
endif ()
set (CMAKE_JAVA_INCLUDE_PATH "")
+177
View File
@@ -0,0 +1,177 @@
#-----------------------------------------------------------------------------
# CMake configuration for HDF5 Java test suite
# This file sets up the build, and test execution rules for the HDF5 Java test suite.
# It handles Java test source grouping, JAR creation, test data management, test execution (including VOL tests),
# and integration with the HDF5 Java FFM and core libraries.
#-----------------------------------------------------------------------------
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA_JTEST Java)
set (CMAKE_VERBOSE_MAKEFILE 1)
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${HDF5_JAVA_JSRC_SOURCE_DIR};${HDF5_JAVA_JSRC_BINARY_DIR};${HDF5_JAVA_LIB_DIR}")
#-----------------------------------------------------------------------------
# Build FFM-only tests (no hdf.hdf5lib dependencies)
# Build FfmTestSupport first, then test files that depend on it
#-----------------------------------------------------------------------------
# Set classpath for FfmTestSupport compilation (needs FFM bindings)
set (CMAKE_JAVA_INCLUDE_PATH "${HDF5_JAVAHDF5_JARS}")
# Build FfmTestSupport utility class first
file (WRITE ${PROJECT_BINARY_DIR}/FfmTestSupportManifest.txt
"Main-Class: jtest.FfmTestSupport
Enable-Native-Access: ALL-UNNAMED
"
)
add_jar (${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport
MANIFEST ${PROJECT_BINARY_DIR}/FfmTestSupportManifest.txt
FfmTestSupport.java
)
get_target_property (${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport_JAR_FILE
${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport JAR_FILE)
add_dependencies (${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport ${HDF5_JAVA_JSRC_LIB_TARGET})
set_target_properties (${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport PROPERTIES FOLDER test/java/ffm)
if (HDF5_ENABLE_FORMATTERS)
clang_format (HDF5_JAVA_JTEST_FfmTestSupport_SRC_FORMAT FfmTestSupport.java)
endif ()
# Build FFM test files (they depend on FfmTestSupport)
set (HDF5_JAVA_JTEST_FFM_TEST_SOURCES
TestH5Fffm
TestH5Dffm
TestH5Sffm
TestH5Tffm
TestH5Affm
TestH5Pffm
TestH5Effm
TestH5Gffm
TestH5Iffm
TestH5Lffm
TestH5Rffm
TestH5Offm
TestH5VLffm
TestH5PLffm
TestH5Zffm
TestH5FDffm
)
# Update classpath to include FfmTestSupport JAR for test compilation
set (CMAKE_JAVA_INCLUDE_PATH "${HDF5_JAVAHDF5_JARS};${${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport_JAR_FILE};${HDF5_JAVA_LIB_DIR}/org.junit.jar;${HDF5_JAVA_LIB_DIR}/org.hamcrest.jar;${HDF5_JAVA_LOGGING_JAR};${HDF5_JAVA_LOGGING_SIMPLE_JAR}")
foreach (ffm_test_file ${HDF5_JAVA_JTEST_FFM_TEST_SOURCES})
file (WRITE ${PROJECT_BINARY_DIR}/${ffm_test_file}FfmManifest.txt
"Main-Class: jtest.${ffm_test_file}
Enable-Native-Access: ALL-UNNAMED
"
)
add_jar (${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file}
MANIFEST ${PROJECT_BINARY_DIR}/${ffm_test_file}FfmManifest.txt
${ffm_test_file}.java
)
get_target_property (${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file}_JAR_FILE
${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file} JAR_FILE)
# FFM tests depend on both javahdf5 JAR and FfmTestSupport JAR
add_dependencies (${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file} ${HDF5_JAVA_JSRC_LIB_TARGET} ${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport)
set_target_properties (${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file} PROPERTIES FOLDER test/java/ffm)
if (HDF5_ENABLE_FORMATTERS)
clang_format (HDF5_JAVA_JTEST_${ffm_test_file}_FFM_SRC_FORMAT ${ffm_test_file}.java)
endif ()
endforeach ()
# Restore classpath for other tests
set (CMAKE_JAVA_INCLUDE_PATH "${HDF5_JAVAHDF5_JARS};${HDF5_JAVA_LIB_DIR}/org.junit.jar;${HDF5_JAVA_LIB_DIR}/org.hamcrest.jar;${HDF5_JAVA_LOGGING_JAR};${HDF5_JAVA_LOGGING_SIMPLE_JAR}")
HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/h5ex_g_iterate.orig" "${PROJECT_BINARY_DIR}/h5ex_g_iterate.hdf" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/h5ex_g_iterate.orig" "${PROJECT_BINARY_DIR}/h5ex_g_iterateL1.hdf" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/h5ex_g_iterate.orig" "${PROJECT_BINARY_DIR}/h5ex_g_iterateL2.hdf" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/h5ex_g_iterate.orig" "${PROJECT_BINARY_DIR}/h5ex_g_iterateO1.hdf" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/h5ex_g_iterate.orig" "${PROJECT_BINARY_DIR}/h5ex_g_iterateO2.hdf" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/trefer_reg.h5" "${PROJECT_BINARY_DIR}/trefer_reg.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/trefer_attr.h5" "${PROJECT_BINARY_DIR}/trefer_attr.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/tdatareg.h5" "${PROJECT_BINARY_DIR}/tdatareg.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/tattrreg.h5" "${PROJECT_BINARY_DIR}/tattrreg.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/tintsattrs.h5" "${PROJECT_BINARY_DIR}/tintsattrs.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
HDFTEST_COPY_FILE("${HDF5_TOOLS_TST_DIR}/testfiles/tfloatsattrs.h5" "${PROJECT_BINARY_DIR}/tfloatsattrs.h5" "${HDF5_JAVA_JTEST_LIB_TARGET}_files")
add_custom_target(${HDF5_JAVA_JTEST_LIB_TARGET}_files ALL COMMENT "Copying files needed by ${HDF5_JAVA_JTEST_LIB_TARGET} tests" DEPENDS ${${HDF5_JAVA_JTEST_LIB_TARGET}_files_list})
if (WIN32)
set (CMAKE_JAVA_INCLUDE_FLAG_SEP ";")
else ()
set (CMAKE_JAVA_INCLUDE_FLAG_SEP ":")
endif ()
get_property (target_name TARGET ${HDF5_JAVA_JSRC_LIB_TARGET} PROPERTY OUTPUT_NAME)
set (CMAKE_JAVA_CLASSPATH ".")
foreach (CMAKE_INCLUDE_PATH ${CMAKE_JAVA_INCLUDE_PATH})
set (CMAKE_JAVA_CLASSPATH "${CMAKE_JAVA_CLASSPATH}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${CMAKE_INCLUDE_PATH}")
endforeach ()
if (HDF5_TEST_JAVA AND HDF5_TEST_SERIAL)
add_test (
NAME JUnitExt-clear-objects
COMMAND ${CMAKE_COMMAND} -E remove
test.h5
testF2.h5
testPf00000.h5
testPf00001.h5
WORKING_DIRECTORY ${HDF5_BINARY_DIR}/java/jtest
)
set_tests_properties (JUnitExt-clear-objects PROPERTIES FIXTURES_SETUP clear_JUnitExt)
add_test (
NAME JUnitExt-clean-objects
COMMAND ${CMAKE_COMMAND} -E remove
test.h5
testF2.h5
testPf00000.h5
testPf00001.h5
WORKING_DIRECTORY ${HDF5_BINARY_DIR}/java/jtest
)
set_tests_properties (JUnitExt-clean-objects PROPERTIES FIXTURES_CLEANUP clear_JUnitExt)
#-----------------------------------------------------------------------------
# Add FFM-only test execution (Test* files, skip FfmTestSupport utility)
#-----------------------------------------------------------------------------
foreach (ffm_test_file ${HDF5_JAVA_JTEST_FFM_TEST_SOURCES})
set (TEST_FFM_JAVA_CLASSPATH "${CMAKE_JAVA_CLASSPATH}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${${HDF5_JAVA_JTEST_LIB_TARGET}_${ffm_test_file}_JAR_FILE}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${${HDF5_JAVA_JTEST_LIB_TARGET}_FfmTestSupport_JAR_FILE}")
add_test (
NAME JUnitFFM-${ffm_test_file}
COMMAND "${CMAKE_COMMAND}"
-D "TEST_JAVA=${CMAKE_Java_RUNTIME};${CMAKE_Java_RUNTIME_FLAGS}"
-D "TEST_CLASSPATH:STRING=${TEST_FFM_JAVA_CLASSPATH}"
-D "TEST_ARGS:STRING=${CMD_ARGS}-ea;org.junit.runner.JUnitCore"
-D "TEST_PROGRAM=jtest.${ffm_test_file}"
-D "TEST_LIBRARY_DIRECTORY=${CMAKE_TEST_OUTPUT_DIRECTORY}"
-D "TEST_FOLDER=${HDF5_BINARY_DIR}/java/jtest"
-D "TEST_OUTPUT=JUnitFFM-${ffm_test_file}.out"
-D "TEST_EXPECT=0"
-D "TEST_MASK_ERROR=TRUE"
-D "TEST_SKIP_COMPARE=TRUE"
-P "${HDF_RESOURCES_DIR}/runTest.cmake"
)
set_tests_properties (JUnitFFM-${ffm_test_file} PROPERTIES
ENVIRONMENT "HDF5_PLUGIN_PATH=${CMAKE_BINARY_DIR}/testdir2"
FIXTURES_REQUIRED clear_JUnitExt
WORKING_DIRECTORY ${HDF5_BINARY_DIR}/java/jtest
)
if ("JUnitFFM-${ffm_test_file}" MATCHES "${HDF5_DISABLE_TESTS_REGEX}")
set_tests_properties (JUnitFFM-${ffm_test_file} PROPERTIES DISABLED true)
endif ()
endforeach ()
endif ()
set (CMAKE_JAVA_INCLUDE_PATH "")
+277
View File
@@ -0,0 +1,277 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
/**
* Support utilities for FFM-only HDF5 tests.
*
* This class provides common patterns for working with HDF5 through the FFM API,
* including error checking, memory management, and data conversion utilities.
*/
public class FfmTestSupport {
/**
* Check if an HDF5 return value indicates success.
*
* @param retVal The return value from an HDF5 function
* @return true if the operation succeeded (retVal >= 0), false otherwise
*/
public static boolean isSuccess(int retVal) { return retVal >= 0; }
/**
* Check if an HDF5 return value indicates success.
*
* @param retVal The return value from an HDF5 function (long version)
* @return true if the operation succeeded (retVal >= 0), false otherwise
*/
public static boolean isSuccess(long retVal) { return retVal >= 0; }
/**
* Check if an HDF5 identifier is valid.
*
* @param hid The HDF5 identifier to check
* @return true if the identifier is valid (>= 0), false otherwise
*/
public static boolean isValidId(long hid) { return hid >= 0; }
/**
* Create a MemorySegment from a Java String using the provided Arena.
* The string will be null-terminated.
*
* @param arena The Arena to use for allocation
* @param str The Java String to convert
* @return A MemorySegment containing the null-terminated string
*/
public static MemorySegment stringToSegment(Arena arena, String str)
{
if (str == null) {
return MemorySegment.NULL;
}
return arena.allocateFrom(str);
}
/**
* Convert a MemorySegment containing a null-terminated string to a Java String.
*
* @param segment The MemorySegment containing the string
* @return The Java string, or null if segment is NULL
*/
public static String segmentToString(MemorySegment segment)
{
if (segment == null || segment == MemorySegment.NULL) {
return null;
}
return segment.getString(0);
}
/**
* Create a MemorySegment for an integer output parameter.
*
* @param arena The Arena to use for allocation
* @return A MemorySegment that can hold one integer value
*/
public static MemorySegment allocateInt(Arena arena) { return arena.allocate(ValueLayout.JAVA_INT); }
/**
* Create a MemorySegment for a long output parameter.
*
* @param arena The Arena to use for allocation
* @return A MemorySegment that can hold one long value
*/
public static MemorySegment allocateLong(Arena arena) { return arena.allocate(ValueLayout.JAVA_LONG); }
/**
* Create a MemorySegment for an integer array.
*
* @param arena The Arena to use for allocation
* @param length The number of integers in the array
* @return A MemorySegment that can hold the integer array
*/
public static MemorySegment allocateIntArray(Arena arena, int length)
{
return arena.allocate(ValueLayout.JAVA_INT, length);
}
/**
* Create a MemorySegment for a long array.
*
* @param arena The Arena to use for allocation
* @param length The number of longs in the array
* @return A MemorySegment that can hold the long array
*/
public static MemorySegment allocateLongArray(Arena arena, int length)
{
return arena.allocate(ValueLayout.JAVA_LONG, length);
}
/**
* Create a MemorySegment for a double array.
*
* @param arena The Arena to use for allocation
* @param length The number of doubles in the array
* @return A MemorySegment that can hold the double array
*/
public static MemorySegment allocateDoubleArray(Arena arena, int length)
{
return arena.allocate(ValueLayout.JAVA_DOUBLE, length);
}
/**
* Copy data from a Java int array to a MemorySegment.
*
* @param segment The destination MemorySegment
* @param data The source int array
*/
public static void copyToSegment(MemorySegment segment, int[] data)
{
for (int i = 0; i < data.length; i++) {
segment.setAtIndex(ValueLayout.JAVA_INT, i, data[i]);
}
}
/**
* Copy data from a Java long array to a MemorySegment.
*
* @param segment The destination MemorySegment
* @param data The source long array
*/
public static void copyToSegment(MemorySegment segment, long[] data)
{
for (int i = 0; i < data.length; i++) {
segment.setAtIndex(ValueLayout.JAVA_LONG, i, data[i]);
}
}
/**
* Copy data from a MemorySegment to a Java int array.
*
* @param segment The source MemorySegment
* @param data The destination int array
*/
public static void copyFromSegment(MemorySegment segment, int[] data)
{
for (int i = 0; i < data.length; i++) {
data[i] = segment.getAtIndex(ValueLayout.JAVA_INT, i);
}
}
/**
* Copy data from a MemorySegment to a Java long array.
*
* @param segment The source MemorySegment
* @param data The destination long array
*/
public static void copyFromSegment(MemorySegment segment, long[] data)
{
for (int i = 0; i < data.length; i++) {
data[i] = segment.getAtIndex(ValueLayout.JAVA_LONG, i);
}
}
/**
* Get an integer value from a MemorySegment.
*
* @param segment The MemorySegment to read from
* @return The integer value at offset 0
*/
public static int getInt(MemorySegment segment) { return segment.get(ValueLayout.JAVA_INT, 0); }
/**
* Get a long value from a MemorySegment.
*
* @param segment The MemorySegment to read from
* @return The long value at offset 0
*/
public static long getLong(MemorySegment segment) { return segment.get(ValueLayout.JAVA_LONG, 0); }
/**
* Get a double value from a MemorySegment.
*
* @param segment The MemorySegment to read from
* @return The double value at offset 0
*/
public static double getDouble(MemorySegment segment) { return segment.get(ValueLayout.JAVA_DOUBLE, 0); }
/**
* Set an integer value in a MemorySegment.
*
* @param segment The MemorySegment to write to
* @param value The integer value to write
*/
public static void setInt(MemorySegment segment, int value)
{
segment.set(ValueLayout.JAVA_INT, 0, value);
}
/**
* Set a long value in a MemorySegment.
*
* @param segment The MemorySegment to write to
* @param value The long value to write
*/
public static void setLong(MemorySegment segment, long value)
{
segment.set(ValueLayout.JAVA_LONG, 0, value);
}
/**
* Format an error message for a failed HDF5 operation.
*
* @param operation The name of the operation that failed
* @param retVal The error return value
* @return A formatted error message
*/
public static String formatError(String operation, int retVal)
{
return String.format("%s failed with return value: %d", operation, retVal);
}
/**
* Format an error message for a failed HDF5 operation.
*
* @param operation The name of the operation that failed
* @param retVal The error return value (long version)
* @return A formatted error message
*/
public static String formatError(String operation, long retVal)
{
return String.format("%s failed with return value: %d", operation, retVal);
}
/**
* Close an HDF5 identifier if it's valid.
* Uses the appropriate close function based on the identifier type.
*
* @param hid The HDF5 identifier to close
* @param closeFunc A function that closes the identifier (returns int)
* @return true if close succeeded or id was invalid, false if close failed
*/
public static boolean closeQuietly(long hid, java.util.function.LongToIntFunction closeFunc)
{
if (hid >= 0) {
try {
return closeFunc.applyAsInt(hid) >= 0;
}
catch (Exception e) {
return false;
}
}
return true;
}
}
+1044
View File
@@ -0,0 +1,1044 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.H5A_info_t;
import org.hdfgroup.javahdf5.H5A_operator2_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* TestH5Affm - FFM-based tests for HDF5 Attribute operations.
* Tests the H5A* API using Foreign Function & Memory (FFM) bindings.
*/
public class TestH5Affm {
private static final String H5_FILE = "testA.h5";
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
private static final int RANK = 2;
@Rule
public TestName testname = new TestName();
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
long H5sid = hdf5_h.H5I_INVALID_HID();
long H5aid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file() throws Exception
{
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment fileName = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(fileName, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create dataset for attaching attributes
MemorySegment dsetName = stringToSegment(arena, "dset");
H5did = hdf5_h.H5Dcreate2(H5fid, dsetName, hdf5_h.H5T_NATIVE_INT_g(), H5sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
}
}
@After
public void deleteH5file() throws Exception
{
closeQuietly(H5aid, hdf5_h::H5Aclose);
closeQuietly(H5did, hdf5_h::H5Dclose);
closeQuietly(H5sid, hdf5_h::H5Sclose);
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5aid = hdf5_h.H5I_INVALID_HID();
H5did = hdf5_h.H5I_INVALID_HID();
H5sid = hdf5_h.H5I_INVALID_HID();
H5fid = hdf5_h.H5I_INVALID_HID();
}
static
{
try {
System.loadLibrary("hdf5");
hdf5_h.H5open();
}
catch (UnsatisfiedLinkError e) {
System.err.println("Failed to load HDF5 library: " + e.getMessage());
}
}
@Test
public void testH5Acreate()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create scalar attribute space
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
assertTrue("H5Screate scalar failed", isValidId(attr_sid));
// Create attribute
MemorySegment attrName = stringToSegment(arena, "attr1");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Awrite_read()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute with array dataspace
long[] attr_dims = {3};
MemorySegment attrDimsSegment = allocateLongArray(arena, 1);
attrDimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, attr_dims[0]);
long attr_sid = hdf5_h.H5Screate_simple(1, attrDimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(attr_sid));
MemorySegment attrName = stringToSegment(arena, "int_array_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Write data
int[] write_data = {10, 20, 30};
MemorySegment writeSegment = allocateIntArray(arena, 3);
copyToSegment(writeSegment, write_data);
int result = hdf5_h.H5Awrite(H5aid, hdf5_h.H5T_NATIVE_INT_g(), writeSegment);
assertTrue("H5Awrite failed", isSuccess(result));
// Read back
MemorySegment readSegment = allocateIntArray(arena, 3);
result = hdf5_h.H5Aread(H5aid, hdf5_h.H5T_NATIVE_INT_g(), readSegment);
assertTrue("H5Aread failed", isSuccess(result));
// Verify
int[] read_data = new int[3];
copyFromSegment(readSegment, read_data);
assertArrayEquals("Data mismatch", write_data, read_data);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aopen()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute first
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "test_attr");
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Open attribute
H5aid = hdf5_h.H5Aopen(H5did, attrName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aopen failed", isValidId(H5aid));
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aclose()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "temp_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
int result = hdf5_h.H5Aclose(H5aid);
assertTrue("H5Aclose failed", isSuccess(result));
H5aid = hdf5_h.H5I_INVALID_HID();
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
String expectedName = "my_attribute";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, expectedName);
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Get name size
long nameSize = hdf5_h.H5Aget_name(H5aid, 0, MemorySegment.NULL);
assertTrue("H5Aget_name size query failed", nameSize > 0);
// Get name
MemorySegment nameBuffer = arena.allocate(nameSize + 1);
hdf5_h.H5Aget_name(H5aid, nameSize + 1, nameBuffer);
String retrievedName = nameBuffer.getString(0);
assertEquals("Attribute name mismatch", expectedName, retrievedName);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_space()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute with specific dimensions
long[] dims = {5, 3};
MemorySegment dimsSegment = allocateLongArray(arena, 2);
copyToSegment(dimsSegment, dims);
long attr_sid = hdf5_h.H5Screate_simple(2, dimsSegment, MemorySegment.NULL);
MemorySegment attrName = stringToSegment(arena, "array_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Get dataspace
long retrieved_sid = hdf5_h.H5Aget_space(H5aid);
assertTrue("H5Aget_space failed", isValidId(retrieved_sid));
// Verify dimensions
MemorySegment retrievedDims = allocateLongArray(arena, 2);
hdf5_h.H5Sget_simple_extent_dims(retrieved_sid, retrievedDims, MemorySegment.NULL);
long[] readDims = new long[2];
copyFromSegment(retrievedDims, readDims);
assertArrayEquals("Dimensions mismatch", dims, readDims);
hdf5_h.H5Sclose(retrieved_sid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "type_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Get type
long retrieved_tid = hdf5_h.H5Aget_type(H5aid);
assertTrue("H5Aget_type failed", isValidId(retrieved_tid));
// Verify it's a double type
int equal = hdf5_h.H5Tequal(retrieved_tid, hdf5_h.H5T_NATIVE_DOUBLE_g());
assertTrue("Type should be H5T_NATIVE_DOUBLE", equal > 0);
hdf5_h.H5Tclose(retrieved_tid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aexists()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment existingName = stringToSegment(arena, "existing_attr");
MemorySegment missingName = stringToSegment(arena, "missing_attr");
// Create one attribute
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
long aid = hdf5_h.H5Acreate2(H5did, existingName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Check existing
int exists = hdf5_h.H5Aexists(H5did, existingName);
assertTrue("Attribute should exist", exists > 0);
// Check non-existing
exists = hdf5_h.H5Aexists(H5did, missingName);
assertEquals("Attribute should not exist", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Adelete()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment attrName = stringToSegment(arena, "deletable_attr");
// Create attribute
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Verify it exists
int exists = hdf5_h.H5Aexists(H5did, attrName);
assertTrue("Attribute should exist before delete", exists > 0);
// Delete
int result = hdf5_h.H5Adelete(H5did, attrName);
assertTrue("H5Adelete failed", isSuccess(result));
// Verify it's gone
exists = hdf5_h.H5Aexists(H5did, attrName);
assertEquals("Attribute should not exist after delete", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_storage_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute with 10 integers
long[] attr_dims = {10};
MemorySegment attrDimsSegment = allocateLongArray(arena, 1);
attrDimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, attr_dims[0]);
long attr_sid = hdf5_h.H5Screate_simple(1, attrDimsSegment, MemorySegment.NULL);
MemorySegment attrName = stringToSegment(arena, "storage_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Write data
int[] data = new int[10];
MemorySegment dataSegment = allocateIntArray(arena, 10);
copyToSegment(dataSegment, data);
hdf5_h.H5Awrite(H5aid, hdf5_h.H5T_NATIVE_INT_g(), dataSegment);
// Get storage size
long storage_size = hdf5_h.H5Aget_storage_size(H5aid);
assertEquals("Storage size should be 10 * sizeof(int)", 40L, storage_size);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Awrite_readStr()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
String testString = "Hello HDF5 Attributes!";
// Create string type
long str_tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(str_tid));
hdf5_h.H5Tset_size(str_tid, testString.length() + 1);
hdf5_h.H5Tset_strpad(str_tid, hdf5_h.H5T_STR_NULLTERM());
// Create attribute
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "str_attr");
H5aid = hdf5_h.H5Acreate2(H5did, attrName, str_tid, attr_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(H5aid));
// Write string
MemorySegment writeData = stringToSegment(arena, testString);
int writeResult = hdf5_h.H5Awrite(H5aid, str_tid, writeData);
assertTrue("H5Awrite failed", isSuccess(writeResult));
// Read string back
MemorySegment readData = arena.allocate(testString.length() + 1);
int readResult = hdf5_h.H5Aread(H5aid, str_tid, readData);
assertTrue("H5Aread failed", isSuccess(readResult));
String retrievedString = readData.getString(0);
assertEquals("String mismatch", testString, retrievedString);
hdf5_h.H5Tclose(str_tid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Arename()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment oldName = stringToSegment(arena, "old_name");
MemorySegment newName = stringToSegment(arena, "new_name");
// Create attribute
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
long aid = hdf5_h.H5Acreate2(H5did, oldName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Verify old name exists
int exists = hdf5_h.H5Aexists(H5did, oldName);
assertTrue("Old name should exist", exists > 0);
// Rename
int result = hdf5_h.H5Arename(H5did, oldName, newName);
assertTrue("H5Arename failed", isSuccess(result));
// Verify new name exists and old doesn't
exists = hdf5_h.H5Aexists(H5did, newName);
assertTrue("New name should exist", exists > 0);
exists = hdf5_h.H5Aexists(H5did, oldName);
assertEquals("Old name should not exist", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_num_attrs()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 3 attributes
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
for (int i = 0; i < 3; i++) {
MemorySegment attrName = stringToSegment(arena, "attr_" + i);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for attr_" + i, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Get number of attributes
int num_attrs = hdf5_h.H5Aget_num_attrs(H5did);
assertTrue("Should have at least 3 attributes", num_attrs >= 3);
hdf5_h.H5Sclose(attr_sid);
}
}
// =========================
// Phase 1: Essential Query Operations
// =========================
@Test
public void testH5Aget_info()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute with scalar dataspace
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "info_test_attr");
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
// Write some data
MemorySegment data = allocateInt(arena);
setInt(data, 42);
int writeResult = hdf5_h.H5Awrite(aid, hdf5_h.H5T_NATIVE_INT_g(), data);
assertTrue("H5Awrite failed", isSuccess(writeResult));
// Get attribute info
MemorySegment info = H5A_info_t.allocate(arena);
int result = hdf5_h.H5Aget_info(aid, info);
assertTrue("H5Aget_info failed", isSuccess(result));
// Verify info fields
long data_size = H5A_info_t.data_size(info);
assertEquals("Data size should be 4 bytes (sizeof int)", 4L, data_size);
// corder_valid may be false if creation order tracking is not enabled
boolean corder_valid = H5A_info_t.corder_valid(info);
// Just verify we can read it (no assertion on value)
assertNotNull("corder_valid should be readable", Boolean.valueOf(corder_valid));
// cset should be ASCII by default
int cset = H5A_info_t.cset(info);
assertEquals("Character set should be ASCII", hdf5_h.H5T_CSET_ASCII(), cset);
hdf5_h.H5Aclose(aid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_info_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create multiple attributes to test indexing
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"first_attr", "second_attr", "third_attr"};
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Get info for the second attribute (index 1) by name order
MemorySegment objName = stringToSegment(arena, ".");
MemorySegment info = H5A_info_t.allocate(arena);
int result = hdf5_h.H5Aget_info_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(),
hdf5_h.H5_ITER_INC(), 1, info, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aget_info_by_idx failed", isSuccess(result));
// Verify we got valid info
long data_size = H5A_info_t.data_size(info);
assertEquals("Data size should be 8 bytes (sizeof double)", 8L, data_size);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_info_by_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset
String attrNameStr = "named_info_attr";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, attrNameStr);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_FLOAT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Get info by name from the file (using dataset path)
MemorySegment objName = stringToSegment(arena, "dset");
MemorySegment info = H5A_info_t.allocate(arena);
int result = hdf5_h.H5Aget_info_by_name(H5fid, objName, attrName, info, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aget_info_by_name failed", isSuccess(result));
// Verify info
long data_size = H5A_info_t.data_size(info);
assertEquals("Data size should be 4 bytes (sizeof float)", 4L, data_size);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_name_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create multiple attributes with known names
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"alpha", "beta", "gamma"};
String[] sortedNames = {"alpha", "beta", "gamma"}; // Already sorted alphabetically
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Get name of each attribute by index (alphabetical order)
MemorySegment objName = stringToSegment(arena, ".");
for (int i = 0; i < sortedNames.length; i++) {
// Get name size first
long nameSize =
hdf5_h.H5Aget_name_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), i,
MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aget_name_by_idx size query failed for index " + i, nameSize > 0);
// Get actual name
MemorySegment nameBuffer = arena.allocate(nameSize + 1);
long result =
hdf5_h.H5Aget_name_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), i,
nameBuffer, nameSize + 1, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aget_name_by_idx failed for index " + i, result > 0);
String retrievedName = nameBuffer.getString(0);
assertEquals("Name at index " + i + " should match", sortedNames[i], retrievedName);
}
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aget_create_plist()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute creation property list with specific settings
long acpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_ATTRIBUTE_CREATE_ID_g());
assertTrue("H5Pcreate acpl failed", isValidId(acpl));
// Set character encoding to UTF-8
int setResult = hdf5_h.H5Pset_char_encoding(acpl, hdf5_h.H5T_CSET_UTF8());
assertTrue("H5Pset_char_encoding failed", isSuccess(setResult));
// Create attribute with this property list
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, "plist_attr");
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid, acpl,
hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
// Get the creation property list back
long retrieved_acpl = hdf5_h.H5Aget_create_plist(aid);
assertTrue("H5Aget_create_plist failed", isValidId(retrieved_acpl));
// Verify the encoding is UTF-8
MemorySegment encoding = allocateInt(arena);
int getResult = hdf5_h.H5Pget_char_encoding(retrieved_acpl, encoding);
assertTrue("H5Pget_char_encoding failed", isSuccess(getResult));
int retrievedEncoding = getInt(encoding);
assertEquals("Character encoding should be UTF-8", hdf5_h.H5T_CSET_UTF8(), retrievedEncoding);
hdf5_h.H5Pclose(retrieved_acpl);
hdf5_h.H5Pclose(acpl);
hdf5_h.H5Aclose(aid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aexists_by_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset
String existingAttrName = "existing_by_name";
String nonExistingAttrName = "nonexistent_by_name";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, existingAttrName);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Check existence from file using dataset path
MemorySegment objName = stringToSegment(arena, "dset");
MemorySegment existingAttrNameSeg = stringToSegment(arena, existingAttrName);
MemorySegment missingAttrNameSeg = stringToSegment(arena, nonExistingAttrName);
// Should exist
int exists = hdf5_h.H5Aexists_by_name(H5fid, objName, existingAttrNameSeg, hdf5_h.H5P_DEFAULT());
assertTrue("Attribute should exist", exists > 0);
// Should not exist
exists = hdf5_h.H5Aexists_by_name(H5fid, objName, missingAttrNameSeg, hdf5_h.H5P_DEFAULT());
assertEquals("Attribute should not exist", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
// =========================
// Phase 2: Advanced Operations
// =========================
@Test
public void testH5Aopen_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create multiple attributes with known names
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"apple", "banana", "cherry"};
String[] sortedNames = {"apple", "banana", "cherry"}; // Already sorted
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Open second attribute by index (index 1)
MemorySegment objName = stringToSegment(arena, ".");
long aid = hdf5_h.H5Aopen_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 1,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Aopen_by_idx failed", isValidId(aid));
// Verify we opened the correct attribute by checking its name
long nameSize = hdf5_h.H5Aget_name(aid, 0, MemorySegment.NULL);
MemorySegment nameBuf = arena.allocate(nameSize + 1);
hdf5_h.H5Aget_name(aid, nameSize + 1, nameBuf);
String retrievedName = nameBuf.getString(0);
assertEquals("Should have opened 'banana' (index 1)", sortedNames[1], retrievedName);
hdf5_h.H5Aclose(aid);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Adelete_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 3 attributes
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"first", "second", "third"};
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Delete middle attribute (index 1 = "second")
MemorySegment objName = stringToSegment(arena, ".");
int result = hdf5_h.H5Adelete_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(),
1, hdf5_h.H5P_DEFAULT());
assertTrue("H5Adelete_by_idx failed", isSuccess(result));
// Verify "second" is gone
MemorySegment secondName = stringToSegment(arena, "second");
int exists = hdf5_h.H5Aexists(H5did, secondName);
assertEquals("'second' should not exist after deletion", 0, exists);
// Verify others still exist
MemorySegment firstName = stringToSegment(arena, "first");
MemorySegment thirdName = stringToSegment(arena, "third");
exists = hdf5_h.H5Aexists(H5did, firstName);
assertTrue("'first' should still exist", exists > 0);
exists = hdf5_h.H5Aexists(H5did, thirdName);
assertTrue("'third' should still exist", exists > 0);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Adelete_by_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset
String attrNameStr = "deletable_by_name";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment attrName = stringToSegment(arena, attrNameStr);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Verify it exists
int exists = hdf5_h.H5Aexists(H5did, attrName);
assertTrue("Attribute should exist before delete", exists > 0);
// Delete by name from file using dataset path
MemorySegment objName = stringToSegment(arena, "dset");
int result = hdf5_h.H5Adelete_by_name(H5fid, objName, attrName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Adelete_by_name failed", isSuccess(result));
// Verify it's gone
exists = hdf5_h.H5Aexists(H5did, attrName);
assertEquals("Attribute should not exist after delete", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Arename_by_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset
String oldNameStr = "old_name_by_path";
String newNameStr = "new_name_by_path";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment oldName = stringToSegment(arena, oldNameStr);
MemorySegment newName = stringToSegment(arena, newNameStr);
long aid = hdf5_h.H5Acreate2(H5did, oldName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
// Verify old name exists
int exists = hdf5_h.H5Aexists(H5did, oldName);
assertTrue("Old name should exist", exists > 0);
// Rename by name from file using dataset path
MemorySegment objName = stringToSegment(arena, "dset");
int result = hdf5_h.H5Arename_by_name(H5fid, objName, oldName, newName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Arename_by_name failed", isSuccess(result));
// Verify new name exists and old doesn't
exists = hdf5_h.H5Aexists(H5did, newName);
assertTrue("New name should exist", exists > 0);
exists = hdf5_h.H5Aexists(H5did, oldName);
assertEquals("Old name should not exist", 0, exists);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aiterate2()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create multiple attributes
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"attr_A", "attr_B", "attr_C", "attr_D"};
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Create iteration callback
final int[] count = {0};
final String[] names = new String[10];
H5A_operator2_t.Function cb = (loc_id, attr_name, ainfo, op_data) ->
{
try {
String name = attr_name.getString(0);
names[count[0]] = name;
count[0]++;
return 0; // Continue iteration
}
catch (Exception e) {
return -1; // Stop on error
}
};
MemorySegment callback = H5A_operator2_t.allocate(cb, arena);
MemorySegment idx = allocateLong(arena);
setLong(idx, 0);
// Iterate
int result = hdf5_h.H5Aiterate2(H5did, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
callback, MemorySegment.NULL);
assertTrue("H5Aiterate2 failed", isSuccess(result));
// Verify we iterated all attributes (at least the 4 we created)
assertTrue("Should have iterated at least 4 attributes", count[0] >= 4);
// Verify all our attributes were seen
boolean foundA = false, foundB = false, foundC = false, foundD = false;
for (int i = 0; i < count[0]; i++) {
if ("attr_A".equals(names[i]))
foundA = true;
if ("attr_B".equals(names[i]))
foundB = true;
if ("attr_C".equals(names[i]))
foundC = true;
if ("attr_D".equals(names[i]))
foundD = true;
}
assertTrue("Should have found attr_A", foundA);
assertTrue("Should have found attr_B", foundB);
assertTrue("Should have found attr_C", foundC);
assertTrue("Should have found attr_D", foundD);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aiterate_by_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attributes on dataset
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
String[] attrNames = {"iter_1", "iter_2", "iter_3"};
for (String name : attrNames) {
MemorySegment attrName = stringToSegment(arena, name);
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
hdf5_h.H5Aclose(aid);
}
// Create iteration callback
final int[] count = {0};
H5A_operator2_t.Function cb = (loc_id, attr_name, ainfo, op_data) ->
{
count[0]++;
return 0; // Continue
};
MemorySegment callback = H5A_operator2_t.allocate(cb, arena);
MemorySegment idx = allocateLong(arena);
setLong(idx, 0);
// Iterate from file using dataset path
MemorySegment objName = stringToSegment(arena, "dset");
int result =
hdf5_h.H5Aiterate_by_name(H5fid, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
callback, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aiterate_by_name failed", isSuccess(result));
// Verify we iterated at least our 3 attributes
assertTrue("Should have iterated at least 3 attributes", count[0] >= 3);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Acreate_by_name_comprehensive()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset using path from file
String attrNameStr = "created_by_path_comprehensive";
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
MemorySegment objName = stringToSegment(arena, "dset");
MemorySegment attrName = stringToSegment(arena, attrNameStr);
long aid =
hdf5_h.H5Acreate_by_name(H5fid, objName, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate_by_name failed", isValidId(aid));
// Write data
MemorySegment data = allocateDoubleArray(arena, 1);
data.setAtIndex(ValueLayout.JAVA_DOUBLE, 0, 3.14159);
int writeResult = hdf5_h.H5Awrite(aid, hdf5_h.H5T_NATIVE_DOUBLE_g(), data);
assertTrue("H5Awrite failed", isSuccess(writeResult));
hdf5_h.H5Aclose(aid);
// Verify attribute is accessible from dataset
MemorySegment attrNameCheck = stringToSegment(arena, attrNameStr);
int exists = hdf5_h.H5Aexists(H5did, attrNameCheck);
assertTrue("Attribute should exist on dataset", exists > 0);
// Open and read back to verify data
long aid2 = hdf5_h.H5Aopen(H5did, attrNameCheck, hdf5_h.H5P_DEFAULT());
assertTrue("H5Aopen failed", isValidId(aid2));
MemorySegment readData = allocateDoubleArray(arena, 1);
int readResult = hdf5_h.H5Aread(aid2, hdf5_h.H5T_NATIVE_DOUBLE_g(), readData);
assertTrue("H5Aread failed", isSuccess(readResult));
double value = readData.getAtIndex(ValueLayout.JAVA_DOUBLE, 0);
assertEquals("Data should match", 3.14159, value, 0.00001);
hdf5_h.H5Aclose(aid2);
hdf5_h.H5Sclose(attr_sid);
}
}
@Test
public void testH5Aiterate()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment idx = allocateLongArray(arena, 1);
copyToSegment(idx, new long[] {0});
// Just verify the API works, iteration callback complex for FFM
long result = hdf5_h.H5Aiterate2(H5did, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
MemorySegment.NULL, MemorySegment.NULL);
assertTrue("H5Aiterate2 should complete", result >= 0);
}
}
}
+1157
View File
@@ -0,0 +1,1157 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.io.File;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Dataset (H5D) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Dffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "testDffm.h5";
private static final String DATASET_NAME = "dset";
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
private static final int RANK = 2;
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5dsid = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
private void deleteFile(String filename)
{
File file = new File(filename);
if (file.exists()) {
try {
file.delete();
}
catch (SecurityException e) {
// Ignore
}
}
}
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(fileNameSegment, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5dsid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5dsid));
// Create dataset
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
H5did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), H5dsid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
int flushResult = hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
assertTrue("H5Fflush failed", isSuccess(flushResult));
}
}
@After
public void deleteH5file()
{
closeQuietly(H5did, hdf5_h::H5Dclose);
closeQuietly(H5dsid, hdf5_h::H5Sclose);
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5did = hdf5_h.H5I_INVALID_HID();
H5dsid = hdf5_h.H5I_INVALID_HID();
H5fid = hdf5_h.H5I_INVALID_HID();
deleteFile(H5_FILE);
System.out.println();
}
@Test
public void testH5Dopen()
{
long did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
did = hdf5_h.H5Dopen2(H5fid, dsetNameSegment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
}
finally {
closeQuietly(did, hdf5_h::H5Dclose);
}
}
@Test
public void testH5Dget_space()
{
long sid = hdf5_h.H5I_INVALID_HID();
try {
sid = hdf5_h.H5Dget_space(H5did);
assertTrue("H5Dget_space failed", isValidId(sid));
// Verify dimensions
try (Arena arena = Arena.ofConfined()) {
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(sid, dimsSegment, MemorySegment.NULL);
assertEquals("Rank should match", RANK, ndims);
long[] dims = new long[RANK];
copyFromSegment(dimsSegment, dims);
assertEquals("Dimension 0 should match", DIM_X, dims[0]);
assertEquals("Dimension 1 should match", DIM_Y, dims[1]);
}
}
finally {
closeQuietly(sid, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Dget_type()
{
long tid = hdf5_h.H5I_INVALID_HID();
try {
tid = hdf5_h.H5Dget_type(H5did);
assertTrue("H5Dget_type failed", isValidId(tid));
}
finally {
closeQuietly(tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dget_create_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Dget_create_plist(H5did);
assertTrue("H5Dget_create_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_access_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Dget_access_plist(H5did);
assertTrue("H5Dget_access_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dwrite_read()
{
int[] writeData = new int[DIM_X * DIM_Y];
int[] readData = new int[DIM_X * DIM_Y];
// Initialize write data
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
// Allocate memory for write
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
// Write data
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Allocate memory for read
MemorySegment readSegment = allocateIntArray(arena, readData.length);
// Read data
int readResult = hdf5_h.H5Dread(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread failed", isSuccess(readResult));
// Copy back to Java array
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Data should match", writeData, readData);
}
}
@Test
public void testH5Dget_storage_size()
{
// Write some data first to allocate storage
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Flush to ensure storage is allocated
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Get storage size
long storageSize = hdf5_h.H5Dget_storage_size(H5did);
assertTrue("Storage size should be > 0", storageSize > 0);
}
}
@Test
public void testH5Dcreate_anon()
{
long anon_did = hdf5_h.H5I_INVALID_HID();
try {
// Create anonymous dataset
anon_did = hdf5_h.H5Dcreate_anon(H5fid, hdf5_h.H5T_NATIVE_INT_g(), H5dsid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate_anon failed", isValidId(anon_did));
// Write some data to verify it works
int[] writeData = {1, 2, 3, 4};
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(anon_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite to anonymous dataset failed", isSuccess(writeResult));
}
}
finally {
closeQuietly(anon_did, hdf5_h::H5Dclose);
}
}
@Test
public void testH5Dget_offset()
{
// Write some data first to ensure storage is allocated
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
try (Arena arena = Arena.ofConfined()) {
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(writeResult));
// Flush to ensure storage is allocated
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Get dataset offset
long offset = hdf5_h.H5Dget_offset(H5did);
// For contiguous datasets, offset should be > 0
// For other layouts, it might return HADDR_UNDEF
// We just verify the call succeeds
assertTrue("H5Dget_offset should return valid value", offset >= 0 || offset == -1);
}
}
@Test
public void testH5Dwrite_readCompound()
{
long compound_tid = hdf5_h.H5I_INVALID_HID();
long compound_did = hdf5_h.H5I_INVALID_HID();
long compound_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create compound type with int and double
// Note: double needs 8-byte alignment, so we pad the int to 8 bytes
int doubleOffset = 8; // Start double at 8-byte boundary
int compoundSize = 16; // 8 bytes for int (padded) + 8 bytes for double
compound_tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), compoundSize);
assertTrue("H5Tcreate compound failed", isValidId(compound_tid));
// Insert members with proper alignment
MemorySegment intNameSegment = stringToSegment(arena, "int_field");
int result = hdf5_h.H5Tinsert(compound_tid, intNameSegment, 0, hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tinsert int field failed", isSuccess(result));
MemorySegment doubleNameSegment = stringToSegment(arena, "double_field");
result =
hdf5_h.H5Tinsert(compound_tid, doubleNameSegment, doubleOffset, hdf5_h.H5T_NATIVE_DOUBLE_g());
assertTrue("H5Tinsert double field failed", isSuccess(result));
// Create dataspace for 4 compound elements
int nElements = 4;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
compound_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(compound_sid));
// Create dataset
MemorySegment compoundDsetSegment = stringToSegment(arena, "compound_dset");
compound_did =
hdf5_h.H5Dcreate2(H5fid, compoundDsetSegment, compound_tid, compound_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 compound dataset failed", isValidId(compound_did));
// Write compound data with proper 8-byte alignment
MemorySegment writeSegment = arena.allocate(compoundSize * nElements, 8); // 8-byte aligned
for (int i = 0; i < nElements; i++) {
long offset = i * compoundSize;
writeSegment.set(ValueLayout.JAVA_INT, offset, i);
writeSegment.set(ValueLayout.JAVA_DOUBLE, offset + doubleOffset, i * 1.5);
}
int writeResult = hdf5_h.H5Dwrite(compound_did, compound_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite compound failed", isSuccess(writeResult));
// Read compound data
MemorySegment readSegment = arena.allocate(compoundSize * nElements, 8); // 8-byte aligned
int readResult = hdf5_h.H5Dread(compound_did, compound_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread compound failed", isSuccess(readResult));
// Verify data
for (int i = 0; i < nElements; i++) {
long offset = i * compoundSize;
int intValue = readSegment.get(ValueLayout.JAVA_INT, offset);
double doubleValue = readSegment.get(ValueLayout.JAVA_DOUBLE, offset + doubleOffset);
assertEquals("Int field should match", i, intValue);
assertEquals("Double field should match", i * 1.5, doubleValue, 0.0001);
}
}
finally {
closeQuietly(compound_did, hdf5_h::H5Dclose);
closeQuietly(compound_sid, hdf5_h::H5Sclose);
closeQuietly(compound_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5DArraywr()
{
long array_tid = hdf5_h.H5I_INVALID_HID();
long array_did = hdf5_h.H5I_INVALID_HID();
long array_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create array datatype: int[3][2]
int arrayRank = 2;
long[] arrayDims = {3, 2};
MemorySegment arrayDimsSegment = allocateLongArray(arena, arrayRank);
copyToSegment(arrayDimsSegment, arrayDims);
array_tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_NATIVE_INT_g(), arrayRank, arrayDimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(array_tid));
// Create dataspace for 2 array elements
int nElements = 2;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
array_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(array_sid));
// Create dataset
MemorySegment arrayDsetSegment = stringToSegment(arena, "array_dset");
array_did = hdf5_h.H5Dcreate2(H5fid, arrayDsetSegment, array_tid, array_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 array dataset failed", isValidId(array_did));
// Write array data: 2 elements, each is int[3][2]
int arraySize = 3 * 2;
int totalSize = nElements * arraySize;
int[] writeData = new int[totalSize];
for (int i = 0; i < totalSize; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, totalSize);
copyToSegment(writeSegment, writeData);
int writeResult = hdf5_h.H5Dwrite(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite array failed", isSuccess(writeResult));
// Read array data
int[] readData = new int[totalSize];
MemorySegment readSegment = allocateIntArray(arena, totalSize);
int readResult = hdf5_h.H5Dread(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread array failed", isSuccess(readResult));
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Array data should match", writeData, readData);
}
finally {
closeQuietly(array_did, hdf5_h::H5Dclose);
closeQuietly(array_sid, hdf5_h::H5Sclose);
closeQuietly(array_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dvlen_write_read()
{
long vlen_tid = hdf5_h.H5I_INVALID_HID();
long vlen_did = hdf5_h.H5I_INVALID_HID();
long vlen_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create variable-length datatype
vlen_tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tvlen_create failed", isValidId(vlen_tid));
// Create dataspace for 2 VL elements
int nElements = 2;
long[] dims = {nElements};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
vlen_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(vlen_sid));
// Create dataset
MemorySegment vlenDsetSegment = stringToSegment(arena, "vlen_dset");
vlen_did = hdf5_h.H5Dcreate2(H5fid, vlenDsetSegment, vlen_tid, vlen_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 vlen dataset failed", isValidId(vlen_did));
// Note: Full VL write/read requires hvl_t struct manipulation which is complex in FFM
// This test verifies the dataset creation and basic API calls work
// Full VL data I/O would need hvl_t struct support from FfmTestSupport
// Verify we can get the datatype back
long retrieved_tid = hdf5_h.H5Dget_type(vlen_did);
assertTrue("H5Dget_type should succeed", isValidId(retrieved_tid));
// Verify it's a variable-length type
int tclass = hdf5_h.H5Tget_class(retrieved_tid);
assertEquals("Type class should be VLEN", hdf5_h.H5T_VLEN(), tclass);
closeQuietly(retrieved_tid, hdf5_h::H5Tclose);
}
finally {
closeQuietly(vlen_did, hdf5_h::H5Dclose);
closeQuietly(vlen_sid, hdf5_h::H5Sclose);
closeQuietly(vlen_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dclose()
{
long did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetNameSegment = stringToSegment(arena, DATASET_NAME);
did = hdf5_h.H5Dopen2(H5fid, dsetNameSegment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
int result = hdf5_h.H5Dclose(did);
assertTrue("H5Dclose failed", isSuccess(result));
did = hdf5_h.H5I_INVALID_HID();
}
}
@Test
public void testH5Dget_num_chunks_rw()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_dset");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get number of chunks (should be 4 chunks: (4/2) * (6/3) = 2 * 2 = 4)
MemorySegment nchunksSegment = allocateLong(arena);
result = hdf5_h.H5Dget_num_chunks(chunked_did, chunked_sid, nchunksSegment);
assertTrue("H5Dget_num_chunks failed", isSuccess(result));
long nchunks = getLong(nchunksSegment);
assertEquals("Should have 4 chunks", 4L, nchunks);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_chunk_storage_size()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_dset2");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to fill first chunk
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk storage size for first chunk (offset [0,0])
long[] offset = {0, 0};
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
copyToSegment(offsetSegment, offset);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_storage_size(chunked_did, offsetSegment, sizeSegment);
assertTrue("H5Dget_chunk_storage_size failed", isSuccess(result));
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dset_extent()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace with unlimited max dimensions
long[] dims = {4, 6};
long[] maxDims = {-1, -1}; // H5S_UNLIMITED for both dimensions
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
MemorySegment maxDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
copyToSegment(maxDimsSegment, maxDims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, maxDimsSegment);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create extensible chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "extensible_dset");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Extend dataset to 8x12
long[] newDims = {8, 12};
MemorySegment newDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(newDimsSegment, newDims);
result = hdf5_h.H5Dset_extent(chunked_did, newDimsSegment);
assertTrue("H5Dset_extent failed", isSuccess(result));
// Verify new dimensions
long space_id = hdf5_h.H5Dget_space(chunked_did);
assertTrue("H5Dget_space failed", isValidId(space_id));
MemorySegment verifyDimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(space_id, verifyDimsSegment, MemorySegment.NULL);
assertEquals("Rank should be 2", RANK, ndims);
long[] verifyDims = new long[RANK];
copyFromSegment(verifyDimsSegment, verifyDims);
assertEquals("First dimension should be 8", 8, verifyDims[0]);
assertEquals("Second dimension should be 12", 12, verifyDims[1]);
closeQuietly(space_id, hdf5_h::H5Sclose);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5DArrayenum_rw()
{
long enum_tid = hdf5_h.H5I_INVALID_HID();
long array_tid = hdf5_h.H5I_INVALID_HID();
long array_did = hdf5_h.H5I_INVALID_HID();
long array_sid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create enum type
enum_tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tenum_create failed", isValidId(enum_tid));
// Insert enum values
MemorySegment redSegment = stringToSegment(arena, "RED");
MemorySegment redValueSegment = allocateInt(arena);
setInt(redValueSegment, 0);
int result = hdf5_h.H5Tenum_insert(enum_tid, redSegment, redValueSegment);
assertTrue("H5Tenum_insert RED failed", isSuccess(result));
MemorySegment greenSegment = stringToSegment(arena, "GREEN");
MemorySegment greenValueSegment = allocateInt(arena);
setInt(greenValueSegment, 1);
result = hdf5_h.H5Tenum_insert(enum_tid, greenSegment, greenValueSegment);
assertTrue("H5Tenum_insert GREEN failed", isSuccess(result));
MemorySegment blueSegment = stringToSegment(arena, "BLUE");
MemorySegment blueValueSegment = allocateInt(arena);
setInt(blueValueSegment, 2);
result = hdf5_h.H5Tenum_insert(enum_tid, blueSegment, blueValueSegment);
assertTrue("H5Tenum_insert BLUE failed", isSuccess(result));
// Create array of enum: [3]
long[] arrayDims = {3};
MemorySegment arrayDimsSegment = allocateLongArray(arena, 1);
copyToSegment(arrayDimsSegment, arrayDims);
array_tid = hdf5_h.H5Tarray_create2(enum_tid, 1, arrayDimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(array_tid));
// Create dataspace for 2 array elements
long[] dims = {2};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
array_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(array_sid));
// Create dataset
MemorySegment arrayEnumDsetSegment = stringToSegment(arena, "array_enum_dset");
array_did = hdf5_h.H5Dcreate2(H5fid, arrayEnumDsetSegment, array_tid, array_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 array enum failed", isValidId(array_did));
// Write array of enum data: [[0,1,2], [2,1,0]]
int[] writeData = {0, 1, 2, 2, 1, 0};
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite array enum failed", isSuccess(result));
// Read array of enum data
int[] readData = new int[writeData.length];
MemorySegment readSegment = allocateIntArray(arena, readData.length);
result = hdf5_h.H5Dread(array_did, array_tid, hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), readSegment);
assertTrue("H5Dread array enum failed", isSuccess(result));
copyFromSegment(readSegment, readData);
// Verify data
assertArrayEquals("Array enum data should match", writeData, readData);
}
finally {
closeQuietly(array_did, hdf5_h::H5Dclose);
closeQuietly(array_sid, hdf5_h::H5Sclose);
closeQuietly(array_tid, hdf5_h::H5Tclose);
closeQuietly(enum_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dfill()
{
try (Arena arena = Arena.ofConfined()) {
// Create a buffer and fill it with a value
int fillValue = 42;
MemorySegment fillSegment = allocateInt(arena);
setInt(fillSegment, fillValue);
MemorySegment bufferSegment = allocateIntArray(arena, DIM_X * DIM_Y);
int result = hdf5_h.H5Dfill(fillSegment, hdf5_h.H5T_NATIVE_INT_g(), bufferSegment,
hdf5_h.H5T_NATIVE_INT_g(), H5dsid);
assertTrue("H5Dfill failed", isSuccess(result));
// Verify buffer is filled
int[] buffer = new int[DIM_X * DIM_Y];
copyFromSegment(bufferSegment, buffer);
for (int value : buffer) {
assertEquals("All values should be fill value", fillValue, value);
}
}
}
@Test
public void testH5Dget_chunk_info()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_info");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk info for first chunk (index 0)
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
MemorySegment filterMaskSegment = allocateInt(arena);
MemorySegment addrSegment = allocateLong(arena);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_info(chunked_did, chunked_sid, 0, offsetSegment, filterMaskSegment,
addrSegment, sizeSegment);
assertTrue("H5Dget_chunk_info failed", isSuccess(result));
// Verify we got valid chunk information
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
long[] offset = new long[RANK];
copyFromSegment(offsetSegment, offset);
// First chunk should start at [0, 0]
assertEquals("First chunk offset[0] should be 0", 0L, offset[0]);
assertEquals("First chunk offset[1] should be 0", 0L, offset[1]);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Dget_chunk_info_by_coord()
{
System.out.print(testname.getMethodName());
long chunked_dcpl = hdf5_h.H5I_INVALID_HID();
long chunked_sid = hdf5_h.H5I_INVALID_HID();
long chunked_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset creation property list
chunked_dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate failed", isValidId(chunked_dcpl));
// Set chunk dimensions: 2x3 chunks
long[] chunkDims = {2, 3};
MemorySegment chunkDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(chunked_dcpl, RANK, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Create dataspace for chunked dataset: 4x6
long[] dims = {4, 6};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
chunked_sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(chunked_sid));
// Create chunked dataset
MemorySegment dsetNameSegment = stringToSegment(arena, "chunked_by_coord");
chunked_did = hdf5_h.H5Dcreate2(H5fid, dsetNameSegment, hdf5_h.H5T_NATIVE_INT_g(), chunked_sid,
hdf5_h.H5P_DEFAULT(), chunked_dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(chunked_did));
// Write data to create chunks
int[] writeData = new int[DIM_X * DIM_Y];
for (int i = 0; i < writeData.length; i++) {
writeData[i] = i;
}
MemorySegment writeSegment = allocateIntArray(arena, writeData.length);
copyToSegment(writeSegment, writeData);
result = hdf5_h.H5Dwrite(chunked_did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(),
hdf5_h.H5S_ALL(), hdf5_h.H5P_DEFAULT(), writeSegment);
assertTrue("H5Dwrite failed", isSuccess(result));
// Get chunk info for chunk at coordinates [2, 3]
long[] offset = {2, 3};
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
copyToSegment(offsetSegment, offset);
MemorySegment filterMaskSegment = allocateInt(arena);
MemorySegment addrSegment = allocateLong(arena);
MemorySegment sizeSegment = allocateLong(arena);
result = hdf5_h.H5Dget_chunk_info_by_coord(chunked_did, offsetSegment, filterMaskSegment,
addrSegment, sizeSegment);
assertTrue("H5Dget_chunk_info_by_coord failed", isSuccess(result));
// Verify we got valid chunk information
long chunkSize = getLong(sizeSegment);
assertTrue("Chunk size should be > 0", chunkSize > 0);
}
finally {
closeQuietly(chunked_did, hdf5_h::H5Dclose);
closeQuietly(chunked_sid, hdf5_h::H5Sclose);
closeQuietly(chunked_dcpl, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Drefresh()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Refresh the dataset metadata
int result = hdf5_h.H5Drefresh(H5did);
assertTrue("H5Drefresh failed", isSuccess(result));
// Verify dataset is still valid after refresh
long type_id = hdf5_h.H5Dget_type(H5did);
assertTrue("H5Dget_type should succeed after refresh", isValidId(type_id));
hdf5_h.H5Tclose(type_id);
}
}
@Test
public void testH5Dvlen_get_buf_size()
{
System.out.print(testname.getMethodName());
long vlen_tid = hdf5_h.H5I_INVALID_HID();
long vlen_sid = hdf5_h.H5I_INVALID_HID();
long vlen_did = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create variable-length integer datatype
vlen_tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_NATIVE_INT_g());
assertTrue("H5Tvlen_create failed", isValidId(vlen_tid));
// Create simple 1D dataspace
long[] dims = {3};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
dimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, dims[0]);
vlen_sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(vlen_sid));
// Create dataset
MemorySegment dsetName = stringToSegment(arena, "vlen_bufsize");
vlen_did = hdf5_h.H5Dcreate2(H5fid, dsetName, vlen_tid, vlen_sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(vlen_did));
// Note: In FFM, we can test that the function exists and returns successfully
// Full VL data writing/reading is complex in FFM and tested separately
MemorySegment sizeSegment = allocateLong(arena);
int result = hdf5_h.H5Dvlen_get_buf_size(vlen_did, vlen_tid, vlen_sid, sizeSegment);
assertTrue("H5Dvlen_get_buf_size should succeed", isSuccess(result));
long bufSize = getLong(sizeSegment);
assertEquals("Buffer size should be 0 for empty VL dataset", 0L, bufSize);
}
finally {
closeQuietly(vlen_did, hdf5_h::H5Dclose);
closeQuietly(vlen_sid, hdf5_h::H5Sclose);
closeQuietly(vlen_tid, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Dget_space_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
// Get dataspace
long sid = hdf5_h.H5Dget_space(did);
assertTrue("H5Dget_space failed", isValidId(sid));
// Get datatype
long tid = hdf5_h.H5Dget_type(did);
assertTrue("H5Dget_type failed", isValidId(tid));
hdf5_h.H5Tclose(tid);
hdf5_h.H5Sclose(sid);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dget_space_status()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
MemorySegment status = allocateIntArray(arena, 1);
int result = hdf5_h.H5Dget_space_status(did, status);
assertTrue("H5Dget_space_status failed", isSuccess(result));
int statusValue = getInt(status);
assertTrue("Status should be valid", statusValue >= 0);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dget_chunk_index_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create chunked dataset
long[] dims = {10, 10};
long[] chunk_dims = {5, 5};
MemorySegment dimsSegment = allocateLongArray(arena, 2);
MemorySegment chunkSegment = allocateLongArray(arena, 2);
copyToSegment(dimsSegment, dims);
copyToSegment(chunkSegment, chunk_dims);
long sid = hdf5_h.H5Screate_simple(2, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(sid));
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
hdf5_h.H5Pset_chunk(dcpl, 2, chunkSegment);
MemorySegment dsetname = stringToSegment(arena, "/chunked_ds");
long did = hdf5_h.H5Dcreate2(H5fid, dsetname, hdf5_h.H5T_NATIVE_INT_g(), sid,
hdf5_h.H5P_DEFAULT(), dcpl, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(did));
// Get chunk index type
MemorySegment indexType = allocateIntArray(arena, 1);
int result = hdf5_h.H5Dget_chunk_index_type(did, indexType);
assertTrue("H5Dget_chunk_index_type failed", isSuccess(result));
hdf5_h.H5Dclose(did);
hdf5_h.H5Pclose(dcpl);
hdf5_h.H5Sclose(sid);
}
}
@Test
public void testH5Dget_num_chunks()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Open existing dataset
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
long sid = hdf5_h.H5Dget_space(did);
MemorySegment numChunks = allocateLongArray(arena, 1);
int result = hdf5_h.H5Dget_num_chunks(did, sid, numChunks);
// This may fail if dataset is not chunked, which is okay
if (isSuccess(result)) {
long count = getLong(numChunks);
assertTrue("Chunk count should be >= 0", count >= 0);
}
hdf5_h.H5Sclose(sid);
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Dflush_refresh()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
long did = hdf5_h.H5Dopen2(H5fid, dsetname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 failed", isValidId(did));
// Flush dataset
int result = hdf5_h.H5Dflush(did);
assertTrue("H5Dflush failed", isSuccess(result));
// Refresh dataset
result = hdf5_h.H5Drefresh(did);
assertTrue("H5Drefresh failed", isSuccess(result));
hdf5_h.H5Dclose(did);
}
}
}
+487
View File
@@ -0,0 +1,487 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Error (H5E) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Effm {
@Rule
public TestName testname = new TestName();
long hdf_java_classid = hdf5_h.H5I_INVALID_HID();
long current_stackid = hdf5_h.H5I_INVALID_HID();
@Before
public void setupErrorClass()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Register custom error class
MemorySegment cls_name = stringToSegment(arena, "HDF-Java-FFM-Error");
MemorySegment lib_name = stringToSegment(arena, "hdf-java-ffm");
MemorySegment version = stringToSegment(arena, "2.0");
hdf_java_classid = hdf5_h.H5Eregister_class(cls_name, lib_name, version);
assertTrue("H5Eregister_class failed", isValidId(hdf_java_classid));
// Get current error stack
current_stackid = hdf5_h.H5Eget_current_stack();
assertTrue("H5Eget_current_stack failed", isValidId(current_stackid));
}
}
@After
public void cleanup()
{
if (isValidId(hdf_java_classid)) {
int result = hdf5_h.H5Eunregister_class(hdf_java_classid);
assertTrue("H5Eunregister_class failed", isSuccess(result));
hdf_java_classid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(current_stackid)) {
closeQuietly(current_stackid, hdf5_h::H5Eclose_stack);
current_stackid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
// ============================================================================
// Phase 1: Error Class and Message Operations
// ============================================================================
@Test
public void testH5Eregister_unregister_class()
{
try (Arena arena = Arena.ofConfined()) {
// Register a new error class
MemorySegment cls_name = stringToSegment(arena, "Test-Error-Class");
MemorySegment lib_name = stringToSegment(arena, "test-lib");
MemorySegment version = stringToSegment(arena, "1.0");
long class_id = hdf5_h.H5Eregister_class(cls_name, lib_name, version);
assertTrue("H5Eregister_class failed", isValidId(class_id));
// Get class name back
long name_size = hdf5_h.H5Eget_class_name(class_id, MemorySegment.NULL, 0);
assertTrue("H5Eget_class_name size query failed", name_size > 0);
MemorySegment nameBuffer = arena.allocate(name_size + 1);
long actual_size = hdf5_h.H5Eget_class_name(class_id, nameBuffer, name_size + 1);
assertTrue("H5Eget_class_name failed", actual_size > 0);
String retrieved_name = nameBuffer.getString(0);
assertEquals("Class name should match", "Test-Error-Class", retrieved_name);
// Unregister class
int result = hdf5_h.H5Eunregister_class(class_id);
assertTrue("H5Eunregister_class failed", isSuccess(result));
}
}
@Test
public void testH5Ecreate_close_msg()
{
try (Arena arena = Arena.ofConfined()) {
// Create major error message
MemorySegment major_msg = stringToSegment(arena, "Test major error");
long maj_err_id = hdf5_h.H5Ecreate_msg(hdf_java_classid, hdf5_h.H5E_MAJOR(), major_msg);
assertTrue("H5Ecreate_msg major failed", isValidId(maj_err_id));
// Get message back
MemorySegment typePtr = allocateInt(arena);
long msg_size = hdf5_h.H5Eget_msg(maj_err_id, typePtr, MemorySegment.NULL, 0);
assertTrue("H5Eget_msg size query failed", msg_size > 0);
MemorySegment msgBuffer = arena.allocate(msg_size + 1);
long actual_size = hdf5_h.H5Eget_msg(maj_err_id, typePtr, msgBuffer, msg_size + 1);
assertTrue("H5Eget_msg failed", actual_size > 0);
String retrieved_msg = msgBuffer.getString(0);
assertEquals("Message should match", "Test major error", retrieved_msg);
int msg_type = getInt(typePtr);
assertEquals("Message type should be MAJOR", hdf5_h.H5E_MAJOR(), msg_type);
// Close message
int result = hdf5_h.H5Eclose_msg(maj_err_id);
assertTrue("H5Eclose_msg failed", isSuccess(result));
// Create minor error message
MemorySegment minor_msg = stringToSegment(arena, "Test minor error");
long min_err_id = hdf5_h.H5Ecreate_msg(hdf_java_classid, hdf5_h.H5E_MINOR(), minor_msg);
assertTrue("H5Ecreate_msg minor failed", isValidId(min_err_id));
// Close minor message
result = hdf5_h.H5Eclose_msg(min_err_id);
assertTrue("H5Eclose_msg minor failed", isSuccess(result));
}
}
@Test
public void testH5Eget_major_minor()
{
try (Arena arena = Arena.ofConfined()) {
// Trigger an error to get real error numbers
MemorySegment filename = stringToSegment(arena, "nonexistent_for_error_test.h5");
long file_id = hdf5_h.H5Fopen(filename, hdf5_h.H5F_ACC_RDONLY(), hdf5_h.H5P_DEFAULT());
if (isValidId(file_id)) {
hdf5_h.H5Fclose(file_id);
}
// Get error stack with actual errors
long stack_id = hdf5_h.H5Eget_current_stack();
if (isValidId(stack_id)) {
long num_errors = hdf5_h.H5Eget_num(stack_id);
if (num_errors > 0) {
// We have errors, test H5Eget_major/minor with error numbers from stack
// For now, just verify the functions can be called with value 0
// (H5Eget_major/minor require actual error numbers which are internal)
// Test that functions return non-null for valid inputs
// Note: We can't easily get actual major/minor error numbers without
// walking the stack, which requires H5Ewalk callback (not yet implemented)
}
hdf5_h.H5Eclose_stack(stack_id);
}
}
}
// ============================================================================
// Phase 2: Error Stack Operations
// ============================================================================
@Test
public void testH5Ecreate_close_stack()
{
// Create new error stack
long stack_id = hdf5_h.H5Ecreate_stack();
assertTrue("H5Ecreate_stack failed", isValidId(stack_id));
// Verify it's empty (new stack has no errors)
long num_errors = hdf5_h.H5Eget_num(stack_id);
assertEquals("New stack should have 0 errors", 0L, num_errors);
// Close stack
int result = hdf5_h.H5Eclose_stack(stack_id);
assertTrue("H5Eclose_stack failed", isSuccess(result));
}
@Test
public void testH5Eget_current_set_stack()
{
// Get current stack
long stack1 = hdf5_h.H5Eget_current_stack();
assertTrue("H5Eget_current_stack failed", isValidId(stack1));
// Create a new empty stack
long stack2 = hdf5_h.H5Ecreate_stack();
assertTrue("H5Ecreate_stack failed", isValidId(stack2));
// Set new stack as current
int result = hdf5_h.H5Eset_current_stack(stack2);
assertTrue("H5Eset_current_stack failed", isSuccess(result));
// Note: Setting current stack transfers ownership, so we don't close stack2
// Restore original stack
result = hdf5_h.H5Eset_current_stack(stack1);
assertTrue("H5Eset_current_stack restore failed", isSuccess(result));
}
@Test
public void testH5Eget_num_pop()
{
// Trigger an error by trying to open non-existent file
try (Arena arena = Arena.ofConfined()) {
MemorySegment filename = stringToSegment(arena, "nonexistent_file_for_test.h5");
long file_id = hdf5_h.H5Fopen(filename, hdf5_h.H5F_ACC_RDONLY(), hdf5_h.H5P_DEFAULT());
// File open will fail, but that's expected
if (isValidId(file_id)) {
hdf5_h.H5Fclose(file_id);
}
}
// Get current error stack (should have errors from failed open)
long stack_id = hdf5_h.H5Eget_current_stack();
assertTrue("H5Eget_current_stack failed", isValidId(stack_id));
// Get number of errors
long num_errors = hdf5_h.H5Eget_num(stack_id);
assertTrue("Stack should have errors after failed open", num_errors > 0);
long saved_num = num_errors;
// Pop one error
int result = hdf5_h.H5Epop(stack_id, 1);
assertTrue("H5Epop failed", isSuccess(result));
// Verify count decreased
num_errors = hdf5_h.H5Eget_num(stack_id);
assertEquals("Error count should decrease by 1", saved_num - 1, num_errors);
// Clean up
hdf5_h.H5Eclose_stack(stack_id);
}
@Test
public void testH5Eappend_stack()
{
try (Arena arena = Arena.ofConfined()) {
// Create two stacks with errors
// Stack 1: trigger error
MemorySegment filename1 = stringToSegment(arena, "nonexistent1.h5");
long file_id1 = hdf5_h.H5Fopen(filename1, hdf5_h.H5F_ACC_RDONLY(), hdf5_h.H5P_DEFAULT());
if (isValidId(file_id1))
hdf5_h.H5Fclose(file_id1);
long stack1 = hdf5_h.H5Eget_current_stack();
assertTrue("H5Eget_current_stack stack1 failed", isValidId(stack1));
long num1 = hdf5_h.H5Eget_num(stack1);
// Stack 2: trigger another error
MemorySegment filename2 = stringToSegment(arena, "nonexistent2.h5");
long file_id2 = hdf5_h.H5Fopen(filename2, hdf5_h.H5F_ACC_RDONLY(), hdf5_h.H5P_DEFAULT());
if (isValidId(file_id2))
hdf5_h.H5Fclose(file_id2);
long stack2 = hdf5_h.H5Eget_current_stack();
assertTrue("H5Eget_current_stack stack2 failed", isValidId(stack2));
long num2 = hdf5_h.H5Eget_num(stack2);
// Append stack2 to stack1 (close_source = false)
int result = hdf5_h.H5Eappend_stack(stack1, stack2, false);
assertTrue("H5Eappend_stack failed", isSuccess(result));
// Verify stack1 now has combined errors
long combined_num = hdf5_h.H5Eget_num(stack1);
assertTrue("Combined stack should have more errors", combined_num >= num1);
// Clean up (both stacks need closing since close_source was false)
hdf5_h.H5Eclose_stack(stack1);
hdf5_h.H5Eclose_stack(stack2);
}
}
// ============================================================================
// Phase 3: Stack Pause/Resume Operations
// ============================================================================
@Test
public void testH5Epause_resume_stack()
{
try (Arena arena = Arena.ofConfined()) {
// Create a stack
long stack_id = hdf5_h.H5Ecreate_stack();
assertTrue("H5Ecreate_stack failed", isValidId(stack_id));
// Check if paused (should not be paused initially)
MemorySegment isPausedPtr = allocateInt(arena); // Using int for boolean
int result = hdf5_h.H5Eis_paused(stack_id, isPausedPtr);
assertTrue("H5Eis_paused failed", isSuccess(result));
boolean is_paused = (getInt(isPausedPtr) != 0);
assertFalse("New stack should not be paused", is_paused);
// Pause the stack
result = hdf5_h.H5Epause_stack(stack_id);
assertTrue("H5Epause_stack failed", isSuccess(result));
// Verify it's paused
result = hdf5_h.H5Eis_paused(stack_id, isPausedPtr);
assertTrue("H5Eis_paused after pause failed", isSuccess(result));
is_paused = (getInt(isPausedPtr) != 0);
assertTrue("Stack should be paused", is_paused);
// Resume the stack
result = hdf5_h.H5Eresume_stack(stack_id);
assertTrue("H5Eresume_stack failed", isSuccess(result));
// Verify it's resumed (not paused)
result = hdf5_h.H5Eis_paused(stack_id, isPausedPtr);
assertTrue("H5Eis_paused after resume failed", isSuccess(result));
is_paused = (getInt(isPausedPtr) != 0);
assertFalse("Stack should not be paused after resume", is_paused);
// Clean up
hdf5_h.H5Eclose_stack(stack_id);
}
}
// ============================================================================
// Phase 4: Comprehensive Workflow Tests
// ============================================================================
@Test
public void testH5E_complete_workflow()
{
try (Arena arena = Arena.ofConfined()) {
// 1. Register error class
MemorySegment cls_name = stringToSegment(arena, "Workflow-Test-Class");
MemorySegment lib_name = stringToSegment(arena, "workflow-lib");
MemorySegment version = stringToSegment(arena, "1.0");
long class_id = hdf5_h.H5Eregister_class(cls_name, lib_name, version);
assertTrue("Register class failed", isValidId(class_id));
// 2. Create error messages
MemorySegment major_msg = stringToSegment(arena, "Workflow major error");
long maj_id = hdf5_h.H5Ecreate_msg(class_id, hdf5_h.H5E_MAJOR(), major_msg);
assertTrue("Create major message failed", isValidId(maj_id));
MemorySegment minor_msg = stringToSegment(arena, "Workflow minor error");
long min_id = hdf5_h.H5Ecreate_msg(class_id, hdf5_h.H5E_MINOR(), minor_msg);
assertTrue("Create minor message failed", isValidId(min_id));
// 3. Create and manipulate error stack
long stack_id = hdf5_h.H5Ecreate_stack();
assertTrue("Create stack failed", isValidId(stack_id));
// Verify stack starts empty
long num = hdf5_h.H5Eget_num(stack_id);
assertEquals("New stack should be empty", 0L, num);
// 4. Get class name
long name_size = hdf5_h.H5Eget_class_name(class_id, MemorySegment.NULL, 0);
assertTrue("Get class name size failed", name_size > 0);
// 5. Clean up in reverse order
hdf5_h.H5Eclose_stack(stack_id);
hdf5_h.H5Eclose_msg(min_id);
hdf5_h.H5Eclose_msg(maj_id);
int result = hdf5_h.H5Eunregister_class(class_id);
assertTrue("Unregister class failed", isSuccess(result));
}
}
@Test
public void testH5Eget_num()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Get number of errors on default stack
long num_errors = hdf5_h.H5Eget_num(hdf5_h.H5E_DEFAULT());
assertTrue("Number of errors should be >= 0", num_errors >= 0);
}
}
@Test
public void testH5Eclear()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Clear error stack
int result = hdf5_h.H5Eclear2(hdf5_h.H5E_DEFAULT());
assertTrue("H5Eclear2 failed", isSuccess(result));
// Verify stack is empty
long num_errors = hdf5_h.H5Eget_num(hdf5_h.H5E_DEFAULT());
assertEquals("Stack should be empty", 0L, num_errors);
}
}
@Test
public void testH5Eget_current_stack()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Get current error stack
long stack_id = hdf5_h.H5Eget_current_stack();
assertTrue("Stack ID should be valid", isValidId(stack_id));
// Close stack
int result = hdf5_h.H5Eclose_stack(stack_id);
assertTrue("H5Eclose_stack failed", isSuccess(result));
}
}
@Test
public void testH5Epop()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Clear stack first
hdf5_h.H5Eclear2(hdf5_h.H5E_DEFAULT());
// Pop errors (should succeed even if empty)
int result = hdf5_h.H5Epop(hdf5_h.H5E_DEFAULT(), 1);
assertTrue("H5Epop should succeed", isSuccess(result));
}
}
@Test
public void testH5Eget_msg()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create error class
MemorySegment cls_name = stringToSegment(arena, "TestClass");
MemorySegment lib_name = stringToSegment(arena, "TestLib");
MemorySegment version = stringToSegment(arena, "1.0");
long class_id = hdf5_h.H5Eregister_class(cls_name, lib_name, version);
assertTrue("Register class failed", isValidId(class_id));
// Create error message
MemorySegment msg_text = stringToSegment(arena, "Test error message");
long msg_id = hdf5_h.H5Ecreate_msg(class_id, hdf5_h.H5E_MAJOR(), msg_text);
assertTrue("Create message failed", isValidId(msg_id));
// Get message
MemorySegment type = allocateIntArray(arena, 1);
long msg_size = hdf5_h.H5Eget_msg(msg_id, type, MemorySegment.NULL, 0);
assertTrue("Message size should be > 0", msg_size > 0);
MemorySegment msg_buf = arena.allocate(msg_size + 1);
long actual_size = hdf5_h.H5Eget_msg(msg_id, type, msg_buf, msg_size + 1);
assertTrue("Actual size should match", actual_size > 0);
String retrieved_msg = segmentToString(msg_buf);
assertEquals("Message should match", "Test error message", retrieved_msg);
// Cleanup
hdf5_h.H5Eclose_msg(msg_id);
hdf5_h.H5Eunregister_class(class_id);
}
}
}
+223
View File
@@ -0,0 +1,223 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Virtual File Driver (H5FD) operations.
*
* NOTE: These tests focus on built-in VFD registration checking and driver queries.
* Low-level VFD operations require file handles and are tested through H5F/H5P APIs.
*/
public class TestH5FDffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5FDffm.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5fapl_id = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
// Ensure HDF5 library is initialized (prevents FFM constant initialization issues)
hdf5_h.H5open();
H5fapl_id = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate failed", isValidId(H5fapl_id));
try (Arena arena = Arena.ofConfined()) {
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(), H5fapl_id);
assertTrue("H5Fcreate failed", isValidId(H5fid));
}
}
@After
public void deleteH5file()
{
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5fapl_id)) {
closeQuietly(H5fapl_id, hdf5_h::H5Pclose);
H5fapl_id = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
/**
* Test H5FDis_driver_registered_by_name for sec2 driver
*/
@Test
public void testH5FDis_driver_registered_by_name_sec2()
{
try (Arena arena = Arena.ofConfined()) {
// SEC2 driver should always be registered
MemorySegment name = stringToSegment(arena, "sec2");
int result = hdf5_h.H5FDis_driver_registered_by_name(name);
assertTrue("SEC2 driver should be registered", result > 0);
}
}
/**
* Test H5FDis_driver_registered_by_name for core driver
*/
@Test
public void testH5FDis_driver_registered_by_name_core()
{
try (Arena arena = Arena.ofConfined()) {
// CORE (memory) driver should always be registered
MemorySegment name = stringToSegment(arena, "core");
int result = hdf5_h.H5FDis_driver_registered_by_name(name);
assertTrue("CORE driver should be registered", result > 0);
}
}
/**
* Test H5FDis_driver_registered_by_name for family driver
*/
@Test
public void testH5FDis_driver_registered_by_name_family()
{
try (Arena arena = Arena.ofConfined()) {
// FAMILY driver should always be registered
MemorySegment name = stringToSegment(arena, "family");
int result = hdf5_h.H5FDis_driver_registered_by_name(name);
assertTrue("FAMILY driver should be registered", result > 0);
}
}
/**
* Test H5FDis_driver_registered_by_name for non-existent driver
*/
@Test
public void testH5FDis_driver_registered_by_name_invalid()
{
try (Arena arena = Arena.ofConfined()) {
// Non-existent driver should not be registered
MemorySegment name = stringToSegment(arena, "nonexistent_driver");
int result = hdf5_h.H5FDis_driver_registered_by_name(name);
assertEquals("Non-existent driver should not be registered", 0, result);
}
}
/**
* Test H5FDis_driver_registered_by_value for sec2 driver
*/
@Test
public void testH5FDis_driver_registered_by_value_sec2()
{
// SEC2 driver (H5_VFD_SEC2 = 0) should be registered
int result = hdf5_h.H5FDis_driver_registered_by_value(hdf5_h.H5_VFD_SEC2());
assertTrue("SEC2 driver should be registered", result > 0);
}
/**
* Test H5FDis_driver_registered_by_value for core driver
*/
@Test
public void testH5FDis_driver_registered_by_value_core()
{
// CORE driver (H5_VFD_CORE = 1) should be registered
int result = hdf5_h.H5FDis_driver_registered_by_value(hdf5_h.H5_VFD_CORE());
assertTrue("CORE driver should be registered", result > 0);
}
/**
* Test H5FDis_driver_registered_by_value for invalid driver
*/
@Test
public void testH5FDis_driver_registered_by_value_invalid()
{
// Invalid driver value should not be registered
int result = hdf5_h.H5FDis_driver_registered_by_value(9999);
assertEquals("Invalid driver value should not be registered", 0, result);
}
/**
* Test H5FDdriver_query for file driver
*/
@Test
public void testH5FDdriver_query()
{
try (Arena arena = Arena.ofConfined()) {
// Get driver ID from FAPL
long driver_id = hdf5_h.H5Pget_driver(H5fapl_id);
assertTrue("Should get valid driver ID", isValidId(driver_id));
// Query driver flags
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_LONG);
int result = hdf5_h.H5FDdriver_query(driver_id, flagsSeg);
assertEquals("H5FDdriver_query should succeed", 0, result);
long flags = flagsSeg.get(ValueLayout.JAVA_LONG, 0);
// Flags should be non-zero for most drivers
assertTrue("Driver should report some features", flags >= 0);
}
}
/**
* Test VFD value constants
*/
@Test
public void testH5_VFD_constants()
{
// Verify VFD value constants
assertEquals("H5_VFD_SEC2 should be 0", 0, hdf5_h.H5_VFD_SEC2());
assertEquals("H5_VFD_CORE should be 1", 1, hdf5_h.H5_VFD_CORE());
assertEquals("H5_VFD_LOG should be 2", 2, hdf5_h.H5_VFD_LOG());
assertEquals("H5_VFD_FAMILY should be 3", 3, hdf5_h.H5_VFD_FAMILY());
assertEquals("H5_VFD_MULTI should be 4", 4, hdf5_h.H5_VFD_MULTI());
// Verify reserved values
assertEquals("H5_VFD_RESERVED should be 256", 256, hdf5_h.H5_VFD_RESERVED());
}
/**
* Test multiple built-in VFDs are registered
*/
@Test
public void testH5FD_builtin_drivers()
{
// Test that common built-in drivers are registered
String[] builtinDrivers = {"sec2", "core", "family", "multi", "log"};
try (Arena arena = Arena.ofConfined()) {
for (String driverName : builtinDrivers) {
MemorySegment name = stringToSegment(arena, driverName);
int result = hdf5_h.H5FDis_driver_registered_by_name(name);
assertTrue(driverName + " driver should be registered", result >= 0);
}
}
}
}
+561
View File
@@ -0,0 +1,561 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.io.File;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.H5AC_cache_config_t;
import org.hdfgroup.javahdf5.H5F_info2_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 File (H5F) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Fffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "testFffm.h5";
private static final String H5_FILE2 = "testFffm2.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
private void deleteFile(String filename)
{
File file = new File(filename);
if (file.exists()) {
try {
file.delete();
}
catch (SecurityException e) {
// Ignore
}
}
}
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(fileNameSegment, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
int flushResult = hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
assertTrue("H5Fflush failed", isSuccess(flushResult));
}
}
@After
public void deleteH5file()
{
if (H5fid >= 0) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
deleteFile(H5_FILE);
deleteFile(H5_FILE2);
System.out.println();
}
@Test
public void testH5Fopen()
{
long fid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE);
fid = hdf5_h.H5Fopen(fileNameSegment, hdf5_h.H5F_ACC_RDONLY(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Fopen failed", isValidId(fid));
}
finally {
closeQuietly(fid, hdf5_h::H5Fclose);
}
}
@Test
public void testH5Freopen()
{
long fid2 = hdf5_h.H5I_INVALID_HID();
try {
fid2 = hdf5_h.H5Freopen(H5fid);
assertTrue("H5Freopen failed", isValidId(fid2));
assertNotEquals("H5Freopen should return different id", H5fid, fid2);
}
finally {
closeQuietly(fid2, hdf5_h::H5Fclose);
}
}
@Test
public void testH5Fget_create_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Fget_create_plist(H5fid);
assertTrue("H5Fget_create_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Fget_access_plist()
{
long plist = hdf5_h.H5I_INVALID_HID();
try {
plist = hdf5_h.H5Fget_access_plist(H5fid);
assertTrue("H5Fget_access_plist failed", isValidId(plist));
}
finally {
closeQuietly(plist, hdf5_h::H5Pclose);
}
}
@Test
public void testH5Fget_intent()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment intentSegment = allocateInt(arena);
int result = hdf5_h.H5Fget_intent(H5fid, intentSegment);
assertTrue("H5Fget_intent failed", isSuccess(result));
int intent = getInt(intentSegment);
assertTrue("File should be opened with write access",
(intent & hdf5_h.H5F_ACC_RDWR()) == hdf5_h.H5F_ACC_RDWR());
}
}
@Test
public void testH5Fget_name()
{
try (Arena arena = Arena.ofConfined()) {
// First call to get the name length
long nameLength = hdf5_h.H5Fget_name(H5fid, MemorySegment.NULL, 0);
assertTrue("H5Fget_name (get length) failed", nameLength > 0);
// Second call to get the actual name
MemorySegment nameSegment = arena.allocate(nameLength + 1);
long result = hdf5_h.H5Fget_name(H5fid, nameSegment, nameLength + 1);
assertTrue("H5Fget_name failed", result > 0);
String fileName = nameSegment.getString(0);
assertTrue("File name should contain test file name", fileName.contains(H5_FILE));
}
}
@Test
public void testH5Fget_filesize()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment sizeSegment = allocateLong(arena);
int result = hdf5_h.H5Fget_filesize(H5fid, sizeSegment);
assertTrue("H5Fget_filesize failed", isSuccess(result));
long fileSize = getLong(sizeSegment);
assertTrue("File size should be > 0", fileSize > 0);
}
}
@Test
public void testH5Fget_obj_count()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSegment = allocateLong(arena);
// Count all objects
long result = hdf5_h.H5Fget_obj_count(H5fid, hdf5_h.H5F_OBJ_ALL());
assertTrue("H5Fget_obj_count failed", result >= 0);
assertTrue("Should have at least one object (the file)", result >= 1);
}
}
@Test
public void testH5Fget_info()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileInfoSegment = H5F_info2_t.allocate(arena);
int result = hdf5_h.H5Fget_info2(H5fid, fileInfoSegment);
assertTrue("H5Fget_info2 failed", isSuccess(result));
// Struct verified (complex struct accessor testing skipped in FFM)
}
}
@Test
public void testH5Fis_accessible()
{
try (Arena arena = Arena.ofConfined()) {
// Close the file first
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
// Check if file is accessible
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE);
int result = hdf5_h.H5Fis_accessible(fileNameSegment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Fis_accessible should return true", result > 0);
// Check non-existent file
MemorySegment badFileSegment = stringToSegment(arena, "nonexistent.h5");
result = hdf5_h.H5Fis_accessible(badFileSegment, hdf5_h.H5P_DEFAULT());
assertFalse("H5Fis_accessible should return false for non-existent file", result > 0);
}
}
@Test
public void testH5Fclear_elink_file_cache()
{
int result = hdf5_h.H5Fclear_elink_file_cache(H5fid);
assertTrue("H5Fclear_elink_file_cache failed", isSuccess(result));
}
@Test
public void testH5Fclose()
{
long fid = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileNameSegment = stringToSegment(arena, H5_FILE2);
fid = hdf5_h.H5Fcreate(fileNameSegment, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(fid));
int result = hdf5_h.H5Fclose(fid);
assertTrue("H5Fclose failed", isSuccess(result));
fid = hdf5_h.H5I_INVALID_HID();
}
}
// =========================
// File Metadata and Cache Tests
// =========================
@Test
public void testH5Fget_freespace()
{
try (Arena arena = Arena.ofConfined()) {
long freespace = hdf5_h.H5Fget_freespace(H5fid);
assertTrue("H5Fget_freespace should return non-negative value", freespace >= 0);
}
}
@Test
public void testH5Fget_mdc_config()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate and initialize H5AC_cache_config_t structure
MemorySegment config = H5AC_cache_config_t.allocate(arena);
// Set version field (required)
H5AC_cache_config_t.version(config, hdf5_h.H5AC__CURR_CACHE_CONFIG_VERSION());
int result = hdf5_h.H5Fget_mdc_config(H5fid, config);
assertTrue("H5Fget_mdc_config failed", isSuccess(result));
// Verify we got valid data back
int version = H5AC_cache_config_t.version(config);
assertEquals("Version should match", hdf5_h.H5AC__CURR_CACHE_CONFIG_VERSION(), version);
}
}
@Test
public void testH5Fget_mdc_hit_rate()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment hitRate = allocateDoubleArray(arena, 1);
int result = hdf5_h.H5Fget_mdc_hit_rate(H5fid, hitRate);
assertTrue("H5Fget_mdc_hit_rate failed", isSuccess(result));
double rate = getDouble(hitRate);
assertTrue("Hit rate should be between 0.0 and 1.0", rate >= 0.0 && rate <= 1.0);
}
}
@Test
public void testH5Fget_fileno()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileno = allocateLongArray(arena, 1);
int result = hdf5_h.H5Fget_fileno(H5fid, fileno);
assertTrue("H5Fget_fileno failed", isSuccess(result));
// File number should be valid (non-negative on most systems)
long fileNum = getLong(fileno);
// Just verify we got some value - actual value is system-dependent
assertNotEquals("File number should be set", 0L, fileNum | 1);
}
}
@Test
public void testH5Fget_file_image()
{
try (Arena arena = Arena.ofConfined()) {
// First get size
long imageSize = hdf5_h.H5Fget_file_image(H5fid, MemorySegment.NULL, 0);
assertTrue("H5Fget_file_image should return positive size", imageSize > 0);
// Allocate buffer and get image (limit to 64KB for test)
long bufSize = Math.min(imageSize, 65536);
MemorySegment imageBuffer = arena.allocate(bufSize);
long actualSize = hdf5_h.H5Fget_file_image(H5fid, imageBuffer, bufSize);
assertTrue("H5Fget_file_image should return size", actualSize > 0);
}
}
@Test
public void testH5Fget_mdc_logging_status()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment isEnabled = allocateIntArray(arena, 1);
MemorySegment isCurrentlyLogging = allocateIntArray(arena, 1);
int result = hdf5_h.H5Fget_mdc_logging_status(H5fid, isEnabled, isCurrentlyLogging);
assertTrue("H5Fget_mdc_logging_status failed", isSuccess(result));
// Values should be boolean (0 or 1)
int enabled = getInt(isEnabled);
int logging = getInt(isCurrentlyLogging);
assertTrue("Enabled should be 0 or 1", enabled == 0 || enabled == 1);
assertTrue("Currently logging should be 0 or 1", logging == 0 || logging == 1);
}
}
@Test
public void testH5Freset_mdc_hit_rate_stats()
{
int result = hdf5_h.H5Freset_mdc_hit_rate_stats(H5fid);
assertTrue("H5Freset_mdc_hit_rate_stats failed", isSuccess(result));
}
@Test
public void testH5Fget_mdc_size()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment maxSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment minCleanSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment curSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment curNumEntries = allocateInt(arena);
int result = hdf5_h.H5Fget_mdc_size(H5fid, maxSize, minCleanSize, curSize, curNumEntries);
assertTrue("H5Fget_mdc_size failed", isSuccess(result));
long max = maxSize.get(ValueLayout.JAVA_LONG, 0);
long minClean = minCleanSize.get(ValueLayout.JAVA_LONG, 0);
long cur = curSize.get(ValueLayout.JAVA_LONG, 0);
int entries = getInt(curNumEntries);
assertTrue("Max size should be positive", max > 0);
assertTrue("Current size should be non-negative", cur >= 0);
assertTrue("Entries should be non-negative", entries >= 0);
}
}
@Test
public void testH5Fget_free_sections()
{
try (Arena arena = Arena.ofConfined()) {
// Query number of free sections
int type = hdf5_h.H5FD_MEM_DEFAULT();
long nsects = hdf5_h.H5Fget_free_sections(H5fid, type, 0, MemorySegment.NULL);
assertTrue("H5Fget_free_sections count query should succeed", nsects >= 0);
}
}
@Test
public void testH5Fget_info2()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment finfo = H5F_info2_t.allocate(arena);
int result = hdf5_h.H5Fget_info2(H5fid, finfo);
assertTrue("H5Fget_info2 failed", isSuccess(result));
// Access super block info
MemorySegment superInfo = H5F_info2_t.super_(finfo);
int version = H5F_info2_t.super_.version(superInfo);
assertTrue("Super block version should be valid", version >= 0);
long superSize = H5F_info2_t.super_.super_size(superInfo);
assertTrue("Super block size should be positive", superSize > 0);
}
}
@Test
public void testH5Fstart_swmr_write()
{
try (Arena arena = Arena.ofConfined()) {
// Create a new file for SWMR testing
String swmrFile = "swmr_test.h5";
MemorySegment fileName = stringToSegment(arena, swmrFile);
// Create file with SWMR-compatible settings
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
hdf5_h.H5Pset_libver_bounds(fapl, hdf5_h.H5F_LIBVER_LATEST(), hdf5_h.H5F_LIBVER_LATEST());
long fid = hdf5_h.H5Fcreate(fileName, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(), fapl);
if (isValidId(fid)) {
// Try to start SWMR write mode
int result = hdf5_h.H5Fstart_swmr_write(fid);
// Note: May fail if file has open objects, which is expected behavior
// We're just testing that the API is callable
hdf5_h.H5Fclose(fid);
}
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Fget_vfd_handle()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment fileHandle = arena.allocate(ValueLayout.ADDRESS);
// Get VFD handle (may not be supported by all VFDs)
int result = hdf5_h.H5Fget_vfd_handle(H5fid, hdf5_h.H5P_DEFAULT(), fileHandle);
// Result may fail for some VFDs, which is acceptable
// We're testing that the API is callable
}
}
@Test
public void testH5Fget_page_buffering_stats()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment accesses = allocateIntArray(arena, 2);
MemorySegment hits = allocateIntArray(arena, 2);
MemorySegment misses = allocateIntArray(arena, 2);
MemorySegment evictions = allocateIntArray(arena, 2);
MemorySegment bypasses = allocateIntArray(arena, 2);
int result =
hdf5_h.H5Fget_page_buffering_stats(H5fid, accesses, hits, misses, evictions, bypasses);
// May fail if page buffering is not enabled, which is expected
// Testing API availability
}
}
@Test
public void testH5Freset_page_buffering_stats()
{
int result = hdf5_h.H5Freset_page_buffering_stats(H5fid);
// May fail if page buffering not enabled
// Testing API availability
}
@Test
public void testH5Fincrement_filesize()
{
try (Arena arena = Arena.ofConfined()) {
// Get current file size
MemorySegment sizeBefore = arena.allocate(ValueLayout.JAVA_LONG);
hdf5_h.H5Fget_filesize(H5fid, sizeBefore);
long before = sizeBefore.get(ValueLayout.JAVA_LONG, 0);
// Increment file size by 1KB
long increment = 1024;
int result = hdf5_h.H5Fincrement_filesize(H5fid, increment);
assertTrue("H5Fincrement_filesize failed", isSuccess(result));
// Get new file size
MemorySegment sizeAfter = arena.allocate(ValueLayout.JAVA_LONG);
hdf5_h.H5Fget_filesize(H5fid, sizeAfter);
long after = sizeAfter.get(ValueLayout.JAVA_LONG, 0);
assertTrue("File size should have increased", after >= before + increment);
}
}
@Test
public void testH5Fformat_convert()
{
// Format convert - converts older format files to latest format
// May fail on already-latest format files, which is acceptable
int result = hdf5_h.H5Fformat_convert(H5fid);
// Just testing API availability
}
@Test
public void testH5Fget_dset_no_attrs_hint()
{
try (Arena arena = Arena.ofConfined()) {
// Create a test dataset to check hint
String dsetName = "test_dset_hint";
MemorySegment dsetNameSeg = stringToSegment(arena, dsetName);
long[] dims = {10};
MemorySegment dimsSeg = arena.allocateFrom(ValueLayout.JAVA_LONG, dims);
long space = hdf5_h.H5Screate_simple(1, dimsSeg, MemorySegment.NULL);
long dset = hdf5_h.H5Dcreate2(H5fid, dsetNameSeg, hdf5_h.H5T_NATIVE_INT_g(), space,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
if (isValidId(dset)) {
MemorySegment minimize = arena.allocate(ValueLayout.JAVA_BOOLEAN);
int result = hdf5_h.H5Fget_dset_no_attrs_hint(H5fid, minimize);
assertTrue("H5Fget_dset_no_attrs_hint failed", isSuccess(result));
// Close dataset
hdf5_h.H5Dclose(dset);
}
hdf5_h.H5Sclose(space);
}
}
@Test
public void testH5Fset_dset_no_attrs_hint()
{
try (Arena arena = Arena.ofConfined()) {
// Set the hint to minimize dataset object headers
boolean minimize = true;
int result = hdf5_h.H5Fset_dset_no_attrs_hint(H5fid, minimize);
assertTrue("H5Fset_dset_no_attrs_hint failed", isSuccess(result));
// Verify it was set
MemorySegment minimizeSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
result = hdf5_h.H5Fget_dset_no_attrs_hint(H5fid, minimizeSeg);
assertTrue("H5Fget_dset_no_attrs_hint failed", isSuccess(result));
boolean retrieved = minimizeSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
assertEquals("Minimize hint should match", minimize, retrieved);
}
}
}
+512
View File
@@ -0,0 +1,512 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.H5G_info_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Group (H5G) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Gffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5Gffm.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5gid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create root group for testing
MemorySegment groupname = stringToSegment(arena, "TestGroup");
H5gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(H5gid));
}
}
@After
public void deleteH5file()
{
if (isValidId(H5gid)) {
closeQuietly(H5gid, hdf5_h::H5Gclose);
H5gid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
// ============================================================================
// Phase 1: Group Creation and Closing
// ============================================================================
@Test
public void testH5Gcreate2_close()
{
try (Arena arena = Arena.ofConfined()) {
// Create a group
MemorySegment groupname = stringToSegment(arena, "Group1");
long gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Verify it's a group
int obj_type = hdf5_h.H5Iget_type(gid);
assertEquals("Should be group type", hdf5_h.H5I_GROUP(), obj_type);
// Close group
int result = hdf5_h.H5Gclose(gid);
assertTrue("H5Gclose failed", isSuccess(result));
}
}
@Test
public void testH5Gopen2()
{
try (Arena arena = Arena.ofConfined()) {
// Create a group
MemorySegment groupname = stringToSegment(arena, "GroupToOpen");
long gid1 = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid1));
hdf5_h.H5Gclose(gid1);
// Open the group
long gid2 = hdf5_h.H5Gopen2(H5fid, groupname, hdf5_h.H5P_DEFAULT());
assertTrue("H5Gopen2 failed", isValidId(gid2));
// Verify it's a group
int obj_type = hdf5_h.H5Iget_type(gid2);
assertEquals("Should be group type", hdf5_h.H5I_GROUP(), obj_type);
hdf5_h.H5Gclose(gid2);
}
}
@Test
public void testH5Gcreate_anon()
{
try (Arena arena = Arena.ofConfined()) {
// Create anonymous group
long gid = hdf5_h.H5Gcreate_anon(H5fid, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate_anon failed", isValidId(gid));
// Verify it's a group
int obj_type = hdf5_h.H5Iget_type(gid);
assertEquals("Should be group type", hdf5_h.H5I_GROUP(), obj_type);
// Link it to a name
MemorySegment linkname = stringToSegment(arena, "AnonGroup");
int result = hdf5_h.H5Olink(gid, H5fid, linkname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Olink failed", isSuccess(result));
hdf5_h.H5Gclose(gid);
}
}
// ============================================================================
// Phase 2: Group Information
// ============================================================================
@Test
public void testH5Gget_info()
{
try (Arena arena = Arena.ofConfined()) {
// Create subgroups
for (int i = 0; i < 3; i++) {
MemorySegment subname = stringToSegment(arena, "SubGroup" + i);
long sub_gid = hdf5_h.H5Gcreate2(H5gid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 subgroup failed", isValidId(sub_gid));
hdf5_h.H5Gclose(sub_gid);
}
// Get group info
MemorySegment ginfo = H5G_info_t.allocate(arena);
int result = hdf5_h.H5Gget_info(H5gid, ginfo);
assertTrue("H5Gget_info failed", isSuccess(result));
// Verify storage type
int storage_type = H5G_info_t.storage_type(ginfo);
assertTrue("Storage type should be valid", storage_type >= 0);
// Verify link count
long nlinks = H5G_info_t.nlinks(ginfo);
assertEquals("Should have 3 links", 3L, nlinks);
}
}
@Test
public void testH5Gget_info_by_name()
{
try (Arena arena = Arena.ofConfined()) {
// Create a subgroup
MemorySegment subname = stringToSegment(arena, "InfoTestGroup");
long sub_gid = hdf5_h.H5Gcreate2(H5fid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(sub_gid));
hdf5_h.H5Gclose(sub_gid);
// Get info by name from file
MemorySegment ginfo = H5G_info_t.allocate(arena);
int result = hdf5_h.H5Gget_info_by_name(H5fid, subname, ginfo, hdf5_h.H5P_DEFAULT());
assertTrue("H5Gget_info_by_name failed", isSuccess(result));
// Verify storage type
int storage_type = H5G_info_t.storage_type(ginfo);
assertTrue("Storage type should be valid", storage_type >= 0);
}
}
@Test
public void testH5Gget_info_by_idx()
{
try (Arena arena = Arena.ofConfined()) {
// Create multiple groups
for (int i = 0; i < 3; i++) {
MemorySegment subname = stringToSegment(arena, "IdxGroup" + i);
long sub_gid = hdf5_h.H5Gcreate2(H5fid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(sub_gid));
hdf5_h.H5Gclose(sub_gid);
}
// Get info for group at index 1
MemorySegment ginfo = H5G_info_t.allocate(arena);
MemorySegment dotname = stringToSegment(arena, ".");
int result = hdf5_h.H5Gget_info_by_idx(H5fid, dotname, hdf5_h.H5_INDEX_NAME(),
hdf5_h.H5_ITER_INC(), 1, ginfo, hdf5_h.H5P_DEFAULT());
assertTrue("H5Gget_info_by_idx failed", isSuccess(result));
// Verify storage type is valid
int storage_type = H5G_info_t.storage_type(ginfo);
assertTrue("Storage type should be valid", storage_type >= 0);
}
}
// ============================================================================
// Phase 3: Group Property List
// ============================================================================
@Test
public void testH5Gget_create_plist()
{
try (Arena arena = Arena.ofConfined()) {
// Create group with default GCPL
MemorySegment groupname = stringToSegment(arena, "GroupWithGCPL");
long gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Get GCPL back
long retrieved_gcpl = hdf5_h.H5Gget_create_plist(gid);
assertTrue("H5Gget_create_plist failed", isValidId(retrieved_gcpl));
// Verify it's a valid property list
int plist_class = hdf5_h.H5Iget_type(retrieved_gcpl);
assertEquals("Should be property list type", hdf5_h.H5I_GENPROP_LST(), plist_class);
// Clean up
closeQuietly(retrieved_gcpl, hdf5_h::H5Dclose); // Use Dclose as generic close
hdf5_h.H5Gclose(gid);
}
}
// ============================================================================
// Phase 4: Group Flush and Refresh
// ============================================================================
@Test
public void testH5Gflush()
{
try (Arena arena = Arena.ofConfined()) {
// Create a subgroup
MemorySegment subname = stringToSegment(arena, "FlushGroup");
long gid = hdf5_h.H5Gcreate2(H5gid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Flush group
int result = hdf5_h.H5Gflush(gid);
assertTrue("H5Gflush failed", isSuccess(result));
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Grefresh()
{
try (Arena arena = Arena.ofConfined()) {
// Create a subgroup
MemorySegment subname = stringToSegment(arena, "RefreshGroup");
long gid = hdf5_h.H5Gcreate2(H5gid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Flush first
int result = hdf5_h.H5Gflush(gid);
assertTrue("H5Gflush failed", isSuccess(result));
// Refresh group
result = hdf5_h.H5Grefresh(gid);
assertTrue("H5Grefresh failed", isSuccess(result));
hdf5_h.H5Gclose(gid);
}
}
// ============================================================================
// Phase 5: Comprehensive Workflow
// ============================================================================
@Test
public void testH5G_complete_workflow()
{
try (Arena arena = Arena.ofConfined()) {
// 1. Create group
MemorySegment groupname = stringToSegment(arena, "WorkflowGroup");
long gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create group failed", isValidId(gid));
// 2. Create subgroups
for (int i = 0; i < 3; i++) {
MemorySegment subname = stringToSegment(arena, "Sub" + i);
long sub_gid = hdf5_h.H5Gcreate2(gid, subname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create subgroup failed", isValidId(sub_gid));
hdf5_h.H5Gclose(sub_gid);
}
// 3. Get group info
MemorySegment ginfo = H5G_info_t.allocate(arena);
int result = hdf5_h.H5Gget_info(gid, ginfo);
assertTrue("Get group info failed", isSuccess(result));
long nlinks = H5G_info_t.nlinks(ginfo);
assertEquals("Should have 3 links", 3L, nlinks);
// 4. Get GCPL
long retrieved_gcpl = hdf5_h.H5Gget_create_plist(gid);
assertTrue("Get GCPL failed", isValidId(retrieved_gcpl));
closeQuietly(retrieved_gcpl, hdf5_h::H5Dclose);
// 5. Flush
result = hdf5_h.H5Gflush(gid);
assertTrue("Flush failed", isSuccess(result));
// 6. Close and reopen
hdf5_h.H5Gclose(gid);
gid = hdf5_h.H5Gopen2(H5fid, groupname, hdf5_h.H5P_DEFAULT());
assertTrue("Reopen group failed", isValidId(gid));
// 7. Verify info still correct
result = hdf5_h.H5Gget_info(gid, ginfo);
assertTrue("Get info after reopen failed", isSuccess(result));
nlinks = H5G_info_t.nlinks(ginfo);
assertEquals("Should still have 3 links", 3L, nlinks);
// Clean up
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Gget_num_objs()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group with subgroups
MemorySegment groupName = stringToSegment(arena, "/test_obj_info");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create subgroups
for (int i = 0; i < 3; i++) {
MemorySegment subName = stringToSegment(arena, "sub" + i);
long subGid = hdf5_h.H5Gcreate2(gid, subName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create sub" + i + " failed", isValidId(subGid));
hdf5_h.H5Gclose(subGid);
}
// Get number of objects
MemorySegment numObjs = allocateLongArray(arena, 1);
int result = hdf5_h.H5Gget_num_objs(gid, numObjs);
assertTrue("H5Gget_num_objs failed", isSuccess(result));
assertEquals("Should have 3 objects", 3L, getLong(numObjs));
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Gget_objname_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group with named subgroups
MemorySegment groupName = stringToSegment(arena, "/test_objname_idx");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create subgroup
MemorySegment subName = stringToSegment(arena, "mysubgroup");
long subGid = hdf5_h.H5Gcreate2(gid, subName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create subgroup failed", isValidId(subGid));
hdf5_h.H5Gclose(subGid);
// Get object name by index
long nameSize = hdf5_h.H5Gget_objname_by_idx(gid, 0, MemorySegment.NULL, 0);
assertTrue("Name size should be > 0", nameSize > 0);
MemorySegment nameBuf = arena.allocate(nameSize + 1);
long actualSize = hdf5_h.H5Gget_objname_by_idx(gid, 0, nameBuf, nameSize + 1);
assertTrue("Actual size should match", actualSize > 0);
String retrievedName = segmentToString(nameBuf);
assertEquals("Name should match", "mysubgroup", retrievedName);
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Gget_objtype_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group
MemorySegment groupName = stringToSegment(arena, "/test_objtype_idx");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create subgroup
MemorySegment subName = stringToSegment(arena, "subgroup");
long subGid = hdf5_h.H5Gcreate2(gid, subName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create subgroup failed", isValidId(subGid));
hdf5_h.H5Gclose(subGid);
// Get object type by index
int objType = hdf5_h.H5Gget_objtype_by_idx(gid, 0);
assertTrue("Object type should be valid", objType >= 0);
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Gget_comment()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group
MemorySegment groupName = stringToSegment(arena, "/test_comment");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Set comment
String comment = "This is a test comment";
MemorySegment commentSeg = stringToSegment(arena, comment);
int result = hdf5_h.H5Gset_comment(gid, stringToSegment(arena, "."), commentSeg);
assertTrue("H5Gset_comment failed", isSuccess(result));
// Get comment size
long commentSize = hdf5_h.H5Gget_comment(gid, stringToSegment(arena, "."), 0, MemorySegment.NULL);
assertTrue("Comment size should be > 0", commentSize > 0);
// Get comment
MemorySegment commentBuf = arena.allocate(commentSize + 1);
long actualSize =
hdf5_h.H5Gget_comment(gid, stringToSegment(arena, "."), commentSize + 1, commentBuf);
assertTrue("Actual size should match", actualSize > 0);
String retrievedComment = segmentToString(commentBuf);
assertEquals("Comment should match", comment, retrievedComment);
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Gget_linkval()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group
MemorySegment groupName = stringToSegment(arena, "/test_linkval");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create soft link
String targetPath = "/some/target";
MemorySegment targetSeg = stringToSegment(arena, targetPath);
MemorySegment linkName = stringToSegment(arena, "softlink");
int result = hdf5_h.H5Glink(gid, hdf5_h.H5G_LINK_SOFT(), targetSeg, linkName);
assertTrue("H5Glink failed", isSuccess(result));
// Get link value
MemorySegment valueBuf = arena.allocate(100);
result = hdf5_h.H5Gget_linkval(gid, linkName, 100, valueBuf);
assertTrue("H5Gget_linkval failed", isSuccess(result));
String linkValue = segmentToString(valueBuf);
assertEquals("Link value should match", targetPath, linkValue);
hdf5_h.H5Gclose(gid);
}
}
}
+486
View File
@@ -0,0 +1,486 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.H5I_free_t;
import org.hdfgroup.javahdf5.H5I_iterate_func_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Identifier (H5I) operations.
*/
public class TestH5Iffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5Iffm.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5gid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
MemorySegment groupname = stringToSegment(arena, "Group1");
H5gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(H5gid));
}
}
@After
public void deleteH5file()
{
if (isValidId(H5gid)) {
closeQuietly(H5gid, hdf5_h::H5Gclose);
H5gid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
@Test
public void testH5Iget_type()
{
int file_type = hdf5_h.H5Iget_type(H5fid);
assertEquals("File type should be H5I_FILE", hdf5_h.H5I_FILE(), file_type);
int group_type = hdf5_h.H5Iget_type(H5gid);
assertEquals("Group type should be H5I_GROUP", hdf5_h.H5I_GROUP(), group_type);
}
@Test
public void testH5Iis_valid()
{
int result = hdf5_h.H5Iis_valid(H5fid);
assertTrue("File ID should be valid", result > 0);
result = hdf5_h.H5Iis_valid(H5gid);
assertTrue("Group ID should be valid", result > 0);
result = hdf5_h.H5Iis_valid(hdf5_h.H5I_INVALID_HID());
assertEquals("Invalid ID should not be valid", 0, result);
}
@Test
public void testH5Iget_name()
{
try (Arena arena = Arena.ofConfined()) {
// Get group name size
long name_size = hdf5_h.H5Iget_name(H5gid, MemorySegment.NULL, 0);
assertTrue("H5Iget_name size query failed", name_size > 0);
// Get group name
MemorySegment nameBuffer = arena.allocate(name_size + 1);
long actual_size = hdf5_h.H5Iget_name(H5gid, nameBuffer, name_size + 1);
assertTrue("H5Iget_name failed", actual_size > 0);
String name = nameBuffer.getString(0);
assertEquals("Group name should be /Group1", "/Group1", name);
}
}
@Test
public void testH5Iget_file_id()
{
long file_id = hdf5_h.H5Iget_file_id(H5gid);
assertTrue("H5Iget_file_id failed", isValidId(file_id));
int type = hdf5_h.H5Iget_type(file_id);
assertEquals("Should be file type", hdf5_h.H5I_FILE(), type);
hdf5_h.H5Fclose(file_id);
}
@Test
public void testH5Iinc_dec_ref()
{
// Get initial ref count
int ref_count = hdf5_h.H5Iget_ref(H5gid);
assertTrue("Initial ref count should be positive", ref_count > 0);
// Increment ref count
int new_count = hdf5_h.H5Iinc_ref(H5gid);
assertEquals("Ref count should increase by 1", ref_count + 1, new_count);
// Decrement ref count
new_count = hdf5_h.H5Idec_ref(H5gid);
assertEquals("Ref count should decrease by 1", ref_count, new_count);
}
@Test
public void testH5I_complete_workflow()
{
try (Arena arena = Arena.ofConfined()) {
// 1. Verify ID is valid
int result = hdf5_h.H5Iis_valid(H5gid);
assertTrue("ID should be valid", result > 0);
// 2. Get type
int type = hdf5_h.H5Iget_type(H5gid);
assertEquals("Type should be GROUP", hdf5_h.H5I_GROUP(), type);
// 3. Get name
long name_size = hdf5_h.H5Iget_name(H5gid, MemorySegment.NULL, 0);
assertTrue("Name size should be positive", name_size > 0);
// 4. Get file ID
long file_id = hdf5_h.H5Iget_file_id(H5gid);
assertTrue("File ID should be valid", isValidId(file_id));
// 5. Get ref count
int ref_count = hdf5_h.H5Iget_ref(H5gid);
assertTrue("Ref count should be positive", ref_count > 0);
hdf5_h.H5Fclose(file_id);
}
}
// ============================================================================
// User-Defined ID Type Tests (H5Iregister_type2)
// ============================================================================
@Test
public void testH5Iregister_type2()
{
try (Arena arena = Arena.ofConfined()) {
// Define free function callback (no-op for this test)
H5I_free_t.Function freeFunc = (MemorySegment obj, MemorySegment request) ->
{
// Simple free function that does nothing
// In real usage, this would free memory associated with the object
return 0; // Success
};
// Allocate callback function pointer
MemorySegment freeFuncPtr = H5I_free_t.allocate(freeFunc, arena);
// Register a new user-defined type
int myType = hdf5_h.H5Iregister_type2(0, freeFuncPtr);
assertTrue("H5Iregister_type2 should succeed", myType >= hdf5_h.H5I_NTYPES());
// Verify type exists
int exists = hdf5_h.H5Itype_exists(myType);
assertTrue("User type should exist", exists > 0);
// Get initial member count (should be 0)
MemorySegment numMembers = allocateLongArray(arena, 1);
int result = hdf5_h.H5Inmembers(myType, numMembers);
assertTrue("H5Inmembers should succeed", isSuccess(result));
assertEquals("Should have 0 members initially", 0L, getLong(numMembers));
// Destroy the type
result = hdf5_h.H5Idestroy_type(myType);
assertTrue("H5Idestroy_type should succeed", isSuccess(result));
// Verify type no longer exists
exists = hdf5_h.H5Itype_exists(myType);
assertEquals("User type should not exist after destroy", 0, exists);
}
}
@Test
public void testH5Iregister_and_operations()
{
try (Arena arena = Arena.ofConfined()) {
// Track whether free function was called
MemorySegment freeCalled = allocateIntArray(arena, 1);
freeCalled.set(ValueLayout.JAVA_INT, 0, 0);
// Define free function callback that tracks calls
H5I_free_t.Function freeFunc = (MemorySegment obj, MemorySegment request) ->
{
freeCalled.set(ValueLayout.JAVA_INT, 0, 1);
return 0; // Success
};
MemorySegment freeFuncPtr = H5I_free_t.allocate(freeFunc, arena);
// Register user-defined type
int myType = hdf5_h.H5Iregister_type2(0, freeFuncPtr);
assertTrue("H5Iregister_type2 should succeed", myType >= hdf5_h.H5I_NTYPES());
// Create a test object (just a simple integer in memory)
MemorySegment testObj = allocateIntArray(arena, 1);
testObj.set(ValueLayout.JAVA_INT, 0, 42);
// Register the object with the user type
long objId = hdf5_h.H5Iregister(myType, testObj);
assertTrue("H5Iregister should succeed", isValidId(objId));
// Verify ID is valid
int valid = hdf5_h.H5Iis_valid(objId);
assertTrue("Object ID should be valid", valid > 0);
// Verify ID type matches
int idType = hdf5_h.H5Iget_type(objId);
assertEquals("ID type should match registered type", myType, idType);
// Check member count (should be 1 now)
MemorySegment numMembers = allocateLongArray(arena, 1);
int result = hdf5_h.H5Inmembers(myType, numMembers);
assertTrue("H5Inmembers should succeed", isSuccess(result));
assertEquals("Should have 1 member", 1L, getLong(numMembers));
// Increment reference count
int refCount = hdf5_h.H5Iinc_ref(objId);
assertEquals("Ref count should be 2", 2, refCount);
// Decrement reference count
refCount = hdf5_h.H5Idec_ref(objId);
assertEquals("Ref count should be 1", 1, refCount);
// Clear type (should call free function)
result = hdf5_h.H5Iclear_type(myType, false);
assertTrue("H5Iclear_type should succeed", isSuccess(result));
// Verify free function was called
assertEquals("Free function should have been called", 1, getInt(freeCalled));
// Verify member count is now 0
result = hdf5_h.H5Inmembers(myType, numMembers);
assertTrue("H5Inmembers should succeed", isSuccess(result));
assertEquals("Should have 0 members after clear", 0L, getLong(numMembers));
// Destroy type
result = hdf5_h.H5Idestroy_type(myType);
assertTrue("H5Idestroy_type should succeed", isSuccess(result));
}
}
@Test
public void testH5Iiterate_user_type()
{
try (Arena arena = Arena.ofConfined()) {
// Free function
H5I_free_t.Function freeFunc = (MemorySegment obj, MemorySegment request) -> 0;
MemorySegment freeFuncPtr = H5I_free_t.allocate(freeFunc, arena);
// Register user type
int myType = hdf5_h.H5Iregister_type2(0, freeFuncPtr);
assertTrue("H5Iregister_type2 should succeed", myType >= hdf5_h.H5I_NTYPES());
// Register 3 objects
MemorySegment obj1 = allocateIntArray(arena, 1);
MemorySegment obj2 = allocateIntArray(arena, 1);
MemorySegment obj3 = allocateIntArray(arena, 1);
obj1.set(ValueLayout.JAVA_INT, 0, 10);
obj2.set(ValueLayout.JAVA_INT, 0, 20);
obj3.set(ValueLayout.JAVA_INT, 0, 30);
long id1 = hdf5_h.H5Iregister(myType, obj1);
long id2 = hdf5_h.H5Iregister(myType, obj2);
long id3 = hdf5_h.H5Iregister(myType, obj3);
assertTrue("All IDs should be valid", isValidId(id1) && isValidId(id2) && isValidId(id3));
// Iterate and count IDs
MemorySegment counter = allocateIntArray(arena, 1);
counter.set(ValueLayout.JAVA_INT, 0, 0);
H5I_iterate_func_t.Function callback = (long id, MemorySegment udata) ->
{
int current = udata.get(ValueLayout.JAVA_INT, 0);
udata.set(ValueLayout.JAVA_INT, 0, current + 1);
return 0; // Continue
};
MemorySegment callbackPtr = H5I_iterate_func_t.allocate(callback, arena);
int result = hdf5_h.H5Iiterate(myType, callbackPtr, counter);
assertTrue("H5Iiterate should succeed", isSuccess(result));
// Should have iterated over all 3 objects
assertEquals("Should iterate over 3 IDs", 3, getInt(counter));
// Cleanup - clear type first to free all IDs
result = hdf5_h.H5Iclear_type(myType, false);
assertTrue("H5Iclear_type should succeed", isSuccess(result));
result = hdf5_h.H5Idestroy_type(myType);
assertTrue("H5Idestroy_type should succeed", isSuccess(result));
}
}
@Test
public void testH5Itype_ref_counting()
{
try (Arena arena = Arena.ofConfined()) {
// Free function
H5I_free_t.Function freeFunc = (MemorySegment obj, MemorySegment request) -> 0;
MemorySegment freeFuncPtr = H5I_free_t.allocate(freeFunc, arena);
// Register user type
int myType = hdf5_h.H5Iregister_type2(0, freeFuncPtr);
assertTrue("H5Iregister_type2 should succeed", myType >= hdf5_h.H5I_NTYPES());
// Get initial type ref count
int initialRef = hdf5_h.H5Iget_type_ref(myType);
assertTrue("Initial ref count should be positive", initialRef > 0);
// Increment type ref count
int newRef = hdf5_h.H5Iinc_type_ref(myType);
assertEquals("Ref count should increase by 1", initialRef + 1, newRef);
// Verify with get
int currentRef = hdf5_h.H5Iget_type_ref(myType);
assertEquals("Ref count should match", newRef, currentRef);
// Decrement type ref count
newRef = hdf5_h.H5Idec_type_ref(myType);
assertEquals("Ref count should decrease by 1", initialRef, newRef);
// Verify type still exists
int exists = hdf5_h.H5Itype_exists(myType);
assertTrue("Type should still exist", exists > 0);
// Final cleanup
int result = hdf5_h.H5Idestroy_type(myType);
assertTrue("H5Idestroy_type should succeed", isSuccess(result));
}
}
@Test
public void testH5Iget_type_ref()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a user type (library types like H5I_FILE cannot be used with this API)
int user_type = hdf5_h.H5Iregister_type2(0, MemorySegment.NULL);
assertTrue("Register type failed", isValidId(user_type));
// Get reference count for the user type
int ref_count = hdf5_h.H5Iget_type_ref(user_type);
assertTrue("Type ref count should be >= 0", ref_count >= 0);
// Cleanup
hdf5_h.H5Idestroy_type(user_type);
}
}
@Test
public void testH5Iinc_type_ref()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a user type (library types like H5I_DATATYPE cannot be used with this API)
int user_type = hdf5_h.H5Iregister_type2(0, MemorySegment.NULL);
assertTrue("Register type failed", isValidId(user_type));
// Get initial ref count
int initial_ref = hdf5_h.H5Iget_type_ref(user_type);
assertTrue("Initial ref should be >= 0", initial_ref >= 0);
// Increment type ref count
int new_ref = hdf5_h.H5Iinc_type_ref(user_type);
assertEquals("Ref should increment", initial_ref + 1, new_ref);
// Decrement back
int dec_ref = hdf5_h.H5Idec_type_ref(user_type);
assertEquals("Ref should decrement", initial_ref, dec_ref);
// Cleanup
hdf5_h.H5Idestroy_type(user_type);
}
}
@Test
public void testH5Inmembers()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a user type (library types like H5I_FILE cannot be used with this API)
int user_type = hdf5_h.H5Iregister_type2(0, MemorySegment.NULL);
assertTrue("Register type failed", isValidId(user_type));
// Get number of members of the user type
MemorySegment num_members = allocateLongArray(arena, 1);
int result = hdf5_h.H5Inmembers(user_type, num_members);
assertTrue("H5Inmembers should succeed", isSuccess(result));
long count = getLong(num_members);
assertTrue("Member count should be >= 0", count >= 0);
// Cleanup
hdf5_h.H5Idestroy_type(user_type);
}
}
@Test
public void testH5Iclear_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Register a user-defined type
int user_type = hdf5_h.H5Iregister_type2(0, MemorySegment.NULL);
assertTrue("Register type failed", isValidId(user_type));
// Clear type (remove all objects of this type)
int result = hdf5_h.H5Iclear_type(user_type, false);
assertTrue("H5Iclear_type should succeed", isSuccess(result));
// Destroy type
result = hdf5_h.H5Idestroy_type(user_type);
assertTrue("Destroy type should succeed", isSuccess(result));
}
}
@Test
public void testH5Itype_exists()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a user type to test existence
int user_type = hdf5_h.H5Iregister_type2(0, MemorySegment.NULL);
assertTrue("Register type failed", isValidId(user_type));
// Check if the user type exists
int exists = hdf5_h.H5Itype_exists(user_type);
assertTrue("User type should exist", exists > 0);
// Destroy the type
int result = hdf5_h.H5Idestroy_type(user_type);
assertTrue("Destroy type should succeed", isSuccess(result));
// After destruction, type should not exist
exists = hdf5_h.H5Itype_exists(user_type);
assertTrue("Destroyed type should not exist", exists == 0);
}
}
}
+596
View File
@@ -0,0 +1,596 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.H5L_info2_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Link (H5L) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Lffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5Lffm.h5";
private static final String H5_FILE_EXT = "test_H5Lffm_ext.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5gid = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create group
MemorySegment groupname = stringToSegment(arena, "Group1");
H5gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(H5gid));
// Create dataset
long[] dims = {10};
MemorySegment dimsSegment = allocateLongArray(arena, 1);
copyToSegment(dimsSegment, dims);
long sid = hdf5_h.H5Screate_simple(1, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(sid));
MemorySegment dsetname = stringToSegment(arena, "Dataset1");
H5did = hdf5_h.H5Dcreate2(H5fid, dsetname, hdf5_h.H5T_NATIVE_INT_g(), sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
hdf5_h.H5Sclose(sid);
}
}
@After
public void deleteH5file()
{
if (isValidId(H5did)) {
closeQuietly(H5did, hdf5_h::H5Dclose);
H5did = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5gid)) {
closeQuietly(H5gid, hdf5_h::H5Gclose);
H5gid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
// ============================================================================
// Phase 1: Hard Link Operations
// ============================================================================
@Test
public void testH5Lcreate_hard()
{
try (Arena arena = Arena.ofConfined()) {
// Create hard link to existing dataset
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment link_name = stringToSegment(arena, "HardLink1");
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5fid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
// Verify link exists
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("Link should exist", result > 0);
// Open via hard link
long did = hdf5_h.H5Dopen2(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("H5Dopen2 via hard link failed", isValidId(did));
hdf5_h.H5Dclose(did);
}
}
@Test
public void testH5Lcopy()
{
try (Arena arena = Arena.ofConfined()) {
// Copy existing dataset link
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment dest_name = stringToSegment(arena, "CopiedLink");
int result =
hdf5_h.H5Lcopy(H5fid, src_name, H5fid, dest_name, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcopy failed", isSuccess(result));
// Verify copied link exists
result = hdf5_h.H5Lexists(H5fid, dest_name, hdf5_h.H5P_DEFAULT());
assertTrue("Copied link should exist", result > 0);
}
}
@Test
public void testH5Lmove()
{
try (Arena arena = Arena.ofConfined()) {
// Create a link to move
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment link_name = stringToSegment(arena, "TempLink");
MemorySegment moved_name = stringToSegment(arena, "MovedLink");
// Create initial link
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5fid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
// Move link
result = hdf5_h.H5Lmove(H5fid, link_name, H5fid, moved_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lmove failed", isSuccess(result));
// Verify old link doesn't exist
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertEquals("Old link should not exist", 0, result);
// Verify new link exists
result = hdf5_h.H5Lexists(H5fid, moved_name, hdf5_h.H5P_DEFAULT());
assertTrue("Moved link should exist", result > 0);
}
}
// ============================================================================
// Phase 2: Soft Link Operations
// ============================================================================
@Test
public void testH5Lcreate_soft()
{
try (Arena arena = Arena.ofConfined()) {
// Create soft link to dataset
MemorySegment target_path = stringToSegment(arena, "/Dataset1");
MemorySegment link_name = stringToSegment(arena, "SoftLink1");
int result = hdf5_h.H5Lcreate_soft(target_path, H5fid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_soft failed", isSuccess(result));
// Verify link exists
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("Soft link should exist", result > 0);
// Get link value (use reasonable buffer size for soft link)
long buf_size = 256;
MemorySegment val_buffer = arena.allocate(buf_size);
result = hdf5_h.H5Lget_val(H5fid, link_name, val_buffer, buf_size, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_val failed", isSuccess(result));
String link_target = val_buffer.getString(0);
assertEquals("Link target should match", "/Dataset1", link_target);
}
}
// ============================================================================
// Phase 3: External Link Operations
// ============================================================================
@Test
public void testH5Lcreate_external()
{
try (Arena arena = Arena.ofConfined()) {
// Create external file
MemorySegment ext_filename = stringToSegment(arena, H5_FILE_EXT);
long ext_fid = hdf5_h.H5Fcreate(ext_filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate external failed", isValidId(ext_fid));
// Create group in external file
MemorySegment ext_groupname = stringToSegment(arena, "ExtGroup");
long ext_gid = hdf5_h.H5Gcreate2(ext_fid, ext_groupname, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 external failed", isValidId(ext_gid));
hdf5_h.H5Gclose(ext_gid);
hdf5_h.H5Fclose(ext_fid);
// Create external link in main file
MemorySegment obj_path = stringToSegment(arena, "/ExtGroup");
MemorySegment link_name = stringToSegment(arena, "ExternalLink");
int result = hdf5_h.H5Lcreate_external(ext_filename, obj_path, H5fid, link_name,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_external failed", isSuccess(result));
// Verify link exists
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("External link should exist", result > 0);
}
}
@Test
public void testH5Lunpack_elink_val()
{
try (Arena arena = Arena.ofConfined()) {
// Create external link
MemorySegment ext_filename = stringToSegment(arena, H5_FILE_EXT);
MemorySegment obj_path = stringToSegment(arena, "/SomeObject");
MemorySegment link_name = stringToSegment(arena, "ExternalLinkToUnpack");
int result = hdf5_h.H5Lcreate_external(ext_filename, obj_path, H5fid, link_name,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_external failed", isSuccess(result));
// Get link value (use reasonable buffer size)
long buf_size = 512;
MemorySegment val_buffer = arena.allocate(buf_size);
result = hdf5_h.H5Lget_val(H5fid, link_name, val_buffer, buf_size, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_val failed", isSuccess(result));
// Unpack external link value
MemorySegment file_ptr = allocateLong(arena); // Pointer to filename string
MemorySegment obj_ptr = allocateLong(arena); // Pointer to object path string
result = hdf5_h.H5Lunpack_elink_val(val_buffer, buf_size, MemorySegment.NULL, file_ptr, obj_ptr);
assertTrue("H5Lunpack_elink_val failed", isSuccess(result));
}
}
// ============================================================================
// Phase 4: Link Deletion
// ============================================================================
@Test
public void testH5Ldelete()
{
try (Arena arena = Arena.ofConfined()) {
// Create a link to delete
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment link_name = stringToSegment(arena, "LinkToDelete");
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5fid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
// Verify link exists
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("Link should exist before deletion", result > 0);
// Delete link
result = hdf5_h.H5Ldelete(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertTrue("H5Ldelete failed", isSuccess(result));
// Verify link no longer exists
result = hdf5_h.H5Lexists(H5fid, link_name, hdf5_h.H5P_DEFAULT());
assertEquals("Link should not exist after deletion", 0, result);
}
}
@Test
public void testH5Ldelete_by_idx()
{
try (Arena arena = Arena.ofConfined()) {
// Create multiple links in a group
for (int i = 0; i < 3; i++) {
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment link_name = stringToSegment(arena, "Link" + i);
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5gid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
}
// Delete link at index 1 by name order
MemorySegment dotname = stringToSegment(arena, ".");
int result = hdf5_h.H5Ldelete_by_idx(H5gid, dotname, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(),
1, hdf5_h.H5P_DEFAULT());
assertTrue("H5Ldelete_by_idx failed", isSuccess(result));
// Verify link at index 1 is deleted (Link1)
MemorySegment deleted_name = stringToSegment(arena, "Link1");
result = hdf5_h.H5Lexists(H5gid, deleted_name, hdf5_h.H5P_DEFAULT());
assertEquals("Link1 should not exist after deletion", 0, result);
// Verify other links still exist
MemorySegment link0_name = stringToSegment(arena, "Link0");
result = hdf5_h.H5Lexists(H5gid, link0_name, hdf5_h.H5P_DEFAULT());
assertTrue("Link0 should still exist", result > 0);
}
}
// ============================================================================
// Phase 5: Link Query Operations
// ============================================================================
@Test
public void testH5Lexists()
{
try (Arena arena = Arena.ofConfined()) {
// Check existing object
MemorySegment existing_name = stringToSegment(arena, "Dataset1");
int result = hdf5_h.H5Lexists(H5fid, existing_name, hdf5_h.H5P_DEFAULT());
assertTrue("Dataset1 should exist", result > 0);
// Check non-existing object
MemorySegment non_existing_name = stringToSegment(arena, "DoesNotExist");
result = hdf5_h.H5Lexists(H5fid, non_existing_name, hdf5_h.H5P_DEFAULT());
assertEquals("DoesNotExist should not exist", 0, result);
}
}
@Test
public void testH5Lget_name_by_idx()
{
try (Arena arena = Arena.ofConfined()) {
// Create multiple objects
for (int i = 0; i < 3; i++) {
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment link_name = stringToSegment(arena, "IndexLink" + i);
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5fid, link_name, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
}
// Get name at index 1 by name order
MemorySegment dotname = stringToSegment(arena, ".");
long name_size =
hdf5_h.H5Lget_name_by_idx(H5fid, dotname, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 1,
MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_name_by_idx size query failed", name_size > 0);
MemorySegment name_buffer = arena.allocate(name_size + 1);
long actual_size =
hdf5_h.H5Lget_name_by_idx(H5fid, dotname, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 1,
name_buffer, name_size + 1, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_name_by_idx failed", actual_size > 0);
String retrieved_name = name_buffer.getString(0);
assertTrue("Retrieved name should be a link name", retrieved_name.length() > 0);
}
}
// ============================================================================
// Phase 6: Comprehensive Workflow
// ============================================================================
@Test
public void testH5L_complete_workflow()
{
try (Arena arena = Arena.ofConfined()) {
// 1. Create hard link
MemorySegment src_name = stringToSegment(arena, "Dataset1");
MemorySegment hard_link = stringToSegment(arena, "HardLinkWorkflow");
int result = hdf5_h.H5Lcreate_hard(H5fid, src_name, H5fid, hard_link, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create hard link failed", isSuccess(result));
// 2. Create soft link
MemorySegment soft_target = stringToSegment(arena, "/Dataset1");
MemorySegment soft_link = stringToSegment(arena, "SoftLinkWorkflow");
result = hdf5_h.H5Lcreate_soft(soft_target, H5fid, soft_link, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Create soft link failed", isSuccess(result));
// 3. Verify both exist
result = hdf5_h.H5Lexists(H5fid, hard_link, hdf5_h.H5P_DEFAULT());
assertTrue("Hard link should exist", result > 0);
result = hdf5_h.H5Lexists(H5fid, soft_link, hdf5_h.H5P_DEFAULT());
assertTrue("Soft link should exist", result > 0);
// 4. Copy hard link
MemorySegment copied_link = stringToSegment(arena, "CopiedLinkWorkflow");
result = hdf5_h.H5Lcopy(H5fid, hard_link, H5fid, copied_link, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Copy link failed", isSuccess(result));
// 5. Move soft link
MemorySegment moved_link = stringToSegment(arena, "MovedSoftLinkWorkflow");
result = hdf5_h.H5Lmove(H5fid, soft_link, H5fid, moved_link, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("Move link failed", isSuccess(result));
// 6. Verify soft link moved
result = hdf5_h.H5Lexists(H5fid, soft_link, hdf5_h.H5P_DEFAULT());
assertEquals("Old soft link should not exist", 0, result);
result = hdf5_h.H5Lexists(H5fid, moved_link, hdf5_h.H5P_DEFAULT());
assertTrue("Moved soft link should exist", result > 0);
// 7. Delete copied link
result = hdf5_h.H5Ldelete(H5fid, copied_link, hdf5_h.H5P_DEFAULT());
assertTrue("Delete link failed", isSuccess(result));
// 8. Verify deletion
result = hdf5_h.H5Lexists(H5fid, copied_link, hdf5_h.H5P_DEFAULT());
assertEquals("Copied link should not exist after deletion", 0, result);
}
}
@Test
public void testH5Lget_info()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a group for testing
MemorySegment groupName = stringToSegment(arena, "/test_group_info");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create a link
MemorySegment linkName = stringToSegment(arena, "/test_link_info");
int result = hdf5_h.H5Lcreate_hard(H5fid, groupName, H5fid, linkName, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_hard failed", isSuccess(result));
// Get link info
MemorySegment linfo = arena.allocate(56); // H5L_info_t size
result = hdf5_h.H5Lget_info2(H5fid, linkName, linfo, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_info2 failed", isSuccess(result));
// Cleanup
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Lget_info_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a group with some links
MemorySegment groupName = stringToSegment(arena, "/test_group_idx");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create subgroups to have links
MemorySegment subgroup1 = stringToSegment(arena, "subgroup1");
long gid1 = hdf5_h.H5Gcreate2(gid, subgroup1, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 subgroup1 failed", isValidId(gid1));
// Get link info by index
MemorySegment linfo = arena.allocate(56); // H5L_info_t size
int result = hdf5_h.H5Lget_info_by_idx2(gid, stringToSegment(arena, "."), hdf5_h.H5_INDEX_NAME(),
hdf5_h.H5_ITER_INC(), 0, linfo, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_info_by_idx2 failed", isSuccess(result));
// Cleanup
hdf5_h.H5Gclose(gid1);
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Lget_val()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a soft link
MemorySegment targetPath = stringToSegment(arena, "/target");
MemorySegment linkName = stringToSegment(arena, "/soft_link_val");
int result = hdf5_h.H5Lcreate_soft(targetPath, H5fid, linkName, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_soft failed", isSuccess(result));
// Get link value size first
MemorySegment size = allocateLongArray(arena, 1);
result = hdf5_h.H5Lget_val(H5fid, linkName, MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_val (size query) should succeed", isSuccess(result));
// Note: H5Lget_val returns size via return value in some versions
// For FFM testing, we verify the call succeeds
}
}
@Test
public void testH5Lget_val_by_idx()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a group
MemorySegment groupName = stringToSegment(arena, "/test_group_val_idx");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create a soft link inside the group
MemorySegment targetPath = stringToSegment(arena, "/target");
MemorySegment linkName = stringToSegment(arena, "soft_link");
int result =
hdf5_h.H5Lcreate_soft(targetPath, gid, linkName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Lcreate_soft failed", isSuccess(result));
// Get link value by index
result = hdf5_h.H5Lget_val_by_idx(gid, stringToSegment(arena, "."), hdf5_h.H5_INDEX_NAME(),
hdf5_h.H5_ITER_INC(), 0, MemorySegment.NULL, 0,
hdf5_h.H5P_DEFAULT());
assertTrue("H5Lget_val_by_idx should succeed", isSuccess(result));
// Cleanup
hdf5_h.H5Gclose(gid);
}
}
@Test
public void testH5Lget_name_by_idx_multiple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a group with multiple links
MemorySegment groupName = stringToSegment(arena, "/test_multiple_links");
long gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(gid));
// Create multiple subgroups
for (int i = 0; i < 3; i++) {
MemorySegment subName = stringToSegment(arena, "sub" + i);
long subGid = hdf5_h.H5Gcreate2(gid, subName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 sub" + i + " failed", isValidId(subGid));
hdf5_h.H5Gclose(subGid);
}
// Get name of first link by index
long nameSize = hdf5_h.H5Lget_name_by_idx(gid, stringToSegment(arena, "."),
hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 0,
MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
assertTrue("Name size should be > 0", nameSize > 0);
// Get the actual name
MemorySegment nameBuf = arena.allocate(nameSize + 1);
long actualSize = hdf5_h.H5Lget_name_by_idx(gid, stringToSegment(arena, "."),
hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 0,
nameBuf, nameSize + 1, hdf5_h.H5P_DEFAULT());
assertTrue("Actual size should match", actualSize == nameSize);
String linkName = segmentToString(nameBuf);
assertFalse("Link name should not be empty", linkName.isEmpty());
// Cleanup
hdf5_h.H5Gclose(gid);
}
}
}
+515
View File
@@ -0,0 +1,515 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.H5O_info2_t;
import org.hdfgroup.javahdf5.H5O_native_info_t;
import org.hdfgroup.javahdf5.H5O_token_t;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* TestH5Offm - FFM-based tests for HDF5 Object operations.
* Tests the H5O* API using Foreign Function & Memory (FFM) bindings.
*/
public class TestH5Offm {
private static final String H5_FILE = "testO.h5";
private static final String H5_FILE2 = "testO2.h5";
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
private static final int RANK = 2;
@Rule
public TestName testname = new TestName();
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5fid2 = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
long H5gid = hdf5_h.H5I_INVALID_HID();
long H5sid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file() throws Exception
{
try (Arena arena = Arena.ofConfined()) {
// Create primary file
MemorySegment fileName = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(fileName, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create dataset
MemorySegment dsetName = stringToSegment(arena, "dset");
H5did = hdf5_h.H5Dcreate2(H5fid, dsetName, hdf5_h.H5T_NATIVE_INT_g(), H5sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
// Create group
MemorySegment groupName = stringToSegment(arena, "group");
H5gid = hdf5_h.H5Gcreate2(H5fid, groupName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(H5gid));
}
}
@After
public void deleteH5file() throws Exception
{
closeQuietly(H5gid, hdf5_h::H5Gclose);
closeQuietly(H5did, hdf5_h::H5Dclose);
closeQuietly(H5sid, hdf5_h::H5Sclose);
closeQuietly(H5fid, hdf5_h::H5Fclose);
closeQuietly(H5fid2, hdf5_h::H5Fclose);
H5gid = hdf5_h.H5I_INVALID_HID();
H5did = hdf5_h.H5I_INVALID_HID();
H5sid = hdf5_h.H5I_INVALID_HID();
H5fid = hdf5_h.H5I_INVALID_HID();
H5fid2 = hdf5_h.H5I_INVALID_HID();
}
static
{
try {
System.loadLibrary("hdf5");
hdf5_h.H5open();
}
catch (UnsatisfiedLinkError e) {
System.err.println("Failed to load HDF5 library: " + e.getMessage());
}
}
/**
* Test H5Oopen and H5Oclose - Basic object open/close operations
*/
@Test
public void testH5Oopen_close()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetName = stringToSegment(arena, "dset");
// Open dataset as object
long oid = hdf5_h.H5Oopen(H5fid, dsetName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Oopen should return valid ID", isValidId(oid));
// Close object
int ret = hdf5_h.H5Oclose(oid);
assertTrue("H5Oclose should succeed", isSuccess(ret));
}
}
/**
* Test H5Oopen with group object
*/
@Test
public void testH5Oopen_group()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment groupName = stringToSegment(arena, "group");
// Open group as object
long oid = hdf5_h.H5Oopen(H5fid, groupName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Oopen should return valid ID for group", isValidId(oid));
int ret = hdf5_h.H5Oclose(oid);
assertTrue("H5Oclose should succeed", isSuccess(ret));
}
}
/**
* Test H5Oget_info3 - Get object information
*/
@Test
public void testH5Oget_info()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate H5O_info2_t structure
MemorySegment oinfo = H5O_info2_t.allocate(arena);
// Get info for dataset
int ret = hdf5_h.H5Oget_info3(H5did, oinfo, hdf5_h.H5O_INFO_ALL());
assertTrue("H5Oget_info3 should succeed", isSuccess(ret));
// Verify we got valid information
int type = H5O_info2_t.type(oinfo);
assertTrue("Object type should be valid", type >= 0);
assertEquals("Should be dataset type", hdf5_h.H5O_TYPE_DATASET(), type);
}
}
/**
* Test H5Oget_info3 on group object
*/
@Test
public void testH5Oget_info_group()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment oinfo = H5O_info2_t.allocate(arena);
int ret = hdf5_h.H5Oget_info3(H5gid, oinfo, hdf5_h.H5O_INFO_ALL());
assertTrue("H5Oget_info3 should succeed for group", isSuccess(ret));
int type = H5O_info2_t.type(oinfo);
assertEquals("Should be group type", hdf5_h.H5O_TYPE_GROUP(), type);
}
}
/**
* Test H5Oget_info_by_name3 - Get object info by name
*/
@Test
public void testH5Oget_info_by_name()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetName = stringToSegment(arena, "dset");
MemorySegment oinfo = H5O_info2_t.allocate(arena);
int ret = hdf5_h.H5Oget_info_by_name3(H5fid, dsetName, oinfo, hdf5_h.H5O_INFO_ALL(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Oget_info_by_name3 should succeed", isSuccess(ret));
int type = H5O_info2_t.type(oinfo);
assertEquals("Should be dataset type", hdf5_h.H5O_TYPE_DATASET(), type);
}
}
/**
* Test H5Oget_info_by_idx3 - Get object info by index
*/
@Test
public void testH5Oget_info_by_idx()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment rootName = stringToSegment(arena, ".");
MemorySegment oinfo = H5O_info2_t.allocate(arena);
// Get info for first object in root group (by creation order)
int ret =
hdf5_h.H5Oget_info_by_idx3(H5fid, rootName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 0,
oinfo, hdf5_h.H5O_INFO_ALL(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Oget_info_by_idx3 should succeed", isSuccess(ret));
int type = H5O_info2_t.type(oinfo);
assertTrue("Object type should be valid", type >= 0);
}
}
/**
* Test H5Oexists_by_name - Check if object exists
*/
@Test
public void testH5Oexists_by_name()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetName = stringToSegment(arena, "dset");
// Check if dataset exists
int ret = hdf5_h.H5Oexists_by_name(H5fid, dsetName, hdf5_h.H5P_DEFAULT());
assertTrue("H5Oexists_by_name should return true for existing object", ret > 0);
// Check non-existent object
MemorySegment noName = stringToSegment(arena, "nonexistent");
ret = hdf5_h.H5Oexists_by_name(H5fid, noName, hdf5_h.H5P_DEFAULT());
assertFalse("H5Oexists_by_name should return false for non-existent object", ret > 0);
}
}
/**
* Test H5Olink - Create hard link to object
*/
@Test
public void testH5Olink()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment linkName = stringToSegment(arena, "dset_link");
// Create hard link to dataset
int ret = hdf5_h.H5Olink(H5did, H5fid, linkName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Olink should succeed", isSuccess(ret));
// Verify link exists
long oid = hdf5_h.H5Oopen(H5fid, linkName, hdf5_h.H5P_DEFAULT());
assertTrue("Should be able to open linked object", isValidId(oid));
hdf5_h.H5Oclose(oid);
}
}
/**
* Test H5Ocopy - Copy object to new location
*/
@Test
public void testH5Ocopy()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment srcName = stringToSegment(arena, "dset");
MemorySegment dstName = stringToSegment(arena, "dset_copy");
// Copy dataset within same file
int ret =
hdf5_h.H5Ocopy(H5fid, srcName, H5fid, dstName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Ocopy should succeed", isSuccess(ret));
// Verify copy exists
long oid = hdf5_h.H5Oopen(H5fid, dstName, hdf5_h.H5P_DEFAULT());
assertTrue("Should be able to open copied object", isValidId(oid));
hdf5_h.H5Oclose(oid);
}
}
/**
* Test H5Ocopy across files
*/
@Test
public void testH5Ocopy_across_files()
{
try (Arena arena = Arena.ofConfined()) {
// Create second file
MemorySegment fileName2 = stringToSegment(arena, H5_FILE2);
H5fid2 = hdf5_h.H5Fcreate(fileName2, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate for second file should succeed", isValidId(H5fid2));
MemorySegment srcName = stringToSegment(arena, "dset");
MemorySegment dstName = stringToSegment(arena, "dset_from_file1");
// Copy dataset to different file
int ret =
hdf5_h.H5Ocopy(H5fid, srcName, H5fid2, dstName, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Ocopy across files should succeed", isSuccess(ret));
// Verify copy exists in destination file
long oid = hdf5_h.H5Oopen(H5fid2, dstName, hdf5_h.H5P_DEFAULT());
assertTrue("Should be able to open copied object in destination file", isValidId(oid));
hdf5_h.H5Oclose(oid);
}
}
/**
* Test H5Oget_comment and H5Oset_comment - Object comments
*/
@Test
public void testH5O_comment()
{
try (Arena arena = Arena.ofConfined()) {
String comment = "This is a test dataset";
MemorySegment commentSeg = stringToSegment(arena, comment);
// Set comment on dataset
int ret = hdf5_h.H5Oset_comment(H5did, commentSeg);
assertTrue("H5Oset_comment should succeed", isSuccess(ret));
// Get comment size
long commentSize = hdf5_h.H5Oget_comment(H5did, MemorySegment.NULL, 0);
assertTrue("H5Oget_comment should return positive size", commentSize > 0);
// Allocate buffer and get comment
MemorySegment buffer = arena.allocate(commentSize + 1);
long actualSize = hdf5_h.H5Oget_comment(H5did, buffer, commentSize + 1);
assertTrue("H5Oget_comment should return actual size", actualSize > 0);
String retrievedComment = segmentToString(buffer);
assertEquals("Retrieved comment should match", comment, retrievedComment);
}
}
/**
* Test H5Oget_comment_by_name and H5Oset_comment_by_name
*/
@Test
public void testH5O_comment_by_name()
{
try (Arena arena = Arena.ofConfined()) {
String comment = "Dataset comment by name";
MemorySegment commentSeg = stringToSegment(arena, comment);
MemorySegment dsetName = stringToSegment(arena, "dset");
// Set comment by name
int ret = hdf5_h.H5Oset_comment_by_name(H5fid, dsetName, commentSeg, hdf5_h.H5P_DEFAULT());
assertTrue("H5Oset_comment_by_name should succeed", isSuccess(ret));
// Get comment size by name
long commentSize =
hdf5_h.H5Oget_comment_by_name(H5fid, dsetName, MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
assertTrue("H5Oget_comment_by_name should return positive size", commentSize > 0);
// Get comment by name
MemorySegment buffer = arena.allocate(commentSize + 1);
long actualSize =
hdf5_h.H5Oget_comment_by_name(H5fid, dsetName, buffer, commentSize + 1, hdf5_h.H5P_DEFAULT());
assertTrue("Should get actual comment size", actualSize > 0);
String retrievedComment = segmentToString(buffer);
assertEquals("Retrieved comment should match", comment, retrievedComment);
}
}
/**
* Test H5Oincr_refcount and H5Odecr_refcount - Reference counting
*/
@Test
public void testH5O_refcount()
{
try (Arena arena = Arena.ofConfined()) {
// Increment reference count
int ret = hdf5_h.H5Oincr_refcount(H5did);
assertTrue("H5Oincr_refcount should succeed", isSuccess(ret));
// Decrement reference count
ret = hdf5_h.H5Odecr_refcount(H5did);
assertTrue("H5Odecr_refcount should succeed", isSuccess(ret));
}
}
/**
* Test H5Oflush - Flush object metadata
*/
@Test
public void testH5Oflush()
{
int ret = hdf5_h.H5Oflush(H5did);
assertTrue("H5Oflush should succeed", isSuccess(ret));
}
/**
* Test H5Oget_native_info - Get native object information
*/
@Test
public void testH5Oget_native_info()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment ninfo = H5O_native_info_t.allocate(arena);
int ret = hdf5_h.H5Oget_native_info(H5did, ninfo, hdf5_h.H5O_NATIVE_INFO_ALL());
assertTrue("H5Oget_native_info should succeed", isSuccess(ret));
// Verify we got valid information
// Header info should have valid values
MemorySegment hdr = H5O_native_info_t.hdr(ninfo);
assertNotNull("Header info should not be null", hdr);
}
}
/**
* Test H5Oget_native_info_by_name
*/
@Test
public void testH5Oget_native_info_by_name()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetName = stringToSegment(arena, "dset");
MemorySegment ninfo = H5O_native_info_t.allocate(arena);
int ret = hdf5_h.H5Oget_native_info_by_name(H5fid, dsetName, ninfo, hdf5_h.H5O_NATIVE_INFO_ALL(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Oget_native_info_by_name should succeed", isSuccess(ret));
MemorySegment hdr = H5O_native_info_t.hdr(ninfo);
assertNotNull("Header info should not be null", hdr);
}
}
/**
* Test H5Oopen_by_idx - Open object by index
*/
@Test
public void testH5Oopen_by_idx()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment rootName = stringToSegment(arena, ".");
// Open first object by name index
long oid = hdf5_h.H5Oopen_by_idx(H5fid, rootName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 0,
hdf5_h.H5P_DEFAULT());
assertTrue("H5Oopen_by_idx should return valid ID", isValidId(oid));
int ret = hdf5_h.H5Oclose(oid);
assertTrue("H5Oclose should succeed", isSuccess(ret));
}
}
/**
* Test H5Oopen_by_token - Open object by token
*/
@Test
public void testH5Oopen_by_token()
{
try (Arena arena = Arena.ofConfined()) {
// Get token for dataset
MemorySegment oinfo = H5O_info2_t.allocate(arena);
int ret = hdf5_h.H5Oget_info3(H5did, oinfo, hdf5_h.H5O_INFO_BASIC());
assertTrue("H5Oget_info3 should succeed", isSuccess(ret));
// Get the token
MemorySegment token = H5O_info2_t.token(oinfo);
assertNotNull("Token should not be null", token);
// Open object by token
long oid = hdf5_h.H5Oopen_by_token(H5fid, token);
assertTrue("H5Oopen_by_token should return valid ID", isValidId(oid));
ret = hdf5_h.H5Oclose(oid);
assertTrue("H5Oclose should succeed", isSuccess(ret));
}
}
/**
* Test H5Oare_mdc_flushes_disabled, H5Odisable_mdc_flushes, H5Oenable_mdc_flushes
*/
@Test
public void testH5O_mdc_flushes()
{
try (Arena arena = Arena.ofConfined()) {
// Check initial state
MemorySegment areDisabled = arena.allocate(ValueLayout.JAVA_BYTE);
int ret = hdf5_h.H5Oare_mdc_flushes_disabled(H5did, areDisabled);
assertTrue("H5Oare_mdc_flushes_disabled should succeed", isSuccess(ret));
// Disable flushes
ret = hdf5_h.H5Odisable_mdc_flushes(H5did);
assertTrue("H5Odisable_mdc_flushes should succeed", isSuccess(ret));
// Check they are disabled
ret = hdf5_h.H5Oare_mdc_flushes_disabled(H5did, areDisabled);
assertTrue("Should be able to check flush state", isSuccess(ret));
assertTrue("Flushes should be disabled", areDisabled.get(ValueLayout.JAVA_BYTE, 0) > 0);
// Re-enable flushes
ret = hdf5_h.H5Oenable_mdc_flushes(H5did);
assertTrue("H5Oenable_mdc_flushes should succeed", isSuccess(ret));
// Check they are enabled
ret = hdf5_h.H5Oare_mdc_flushes_disabled(H5did, areDisabled);
assertTrue("Should be able to check flush state", isSuccess(ret));
assertFalse("Flushes should be enabled", areDisabled.get(ValueLayout.JAVA_BYTE, 0) > 0);
}
}
}
+422
View File
@@ -0,0 +1,422 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Plugin (H5PL) operations.
*
* NOTE: These tests focus on plugin path management and loading state control.
* Actual plugin loading requires external plugin libraries and specialized setup.
*/
public class TestH5PLffm {
@Rule
public TestName testname = new TestName();
// Store initial state to restore after tests
private int initialPluginState;
private int initialPathCount;
@Before
public void setUp()
{
System.out.print(testname.getMethodName());
// Save initial plugin loading state
try (Arena arena = Arena.ofConfined()) {
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
int result = hdf5_h.H5PLget_loading_state(stateSeg);
if (result >= 0) {
initialPluginState = stateSeg.get(ValueLayout.JAVA_INT, 0);
}
}
// Save initial path count
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
int result = hdf5_h.H5PLsize(countSeg);
if (result >= 0) {
initialPathCount = countSeg.get(ValueLayout.JAVA_INT, 0);
}
}
}
@After
public void tearDown()
{
// Restore initial plugin loading state
hdf5_h.H5PLset_loading_state(initialPluginState);
// Remove any paths added during testing (in reverse order)
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
hdf5_h.H5PLsize(countSeg);
int currentCount = countSeg.get(ValueLayout.JAVA_INT, 0);
// Remove paths added by tests
while (currentCount > initialPathCount) {
hdf5_h.H5PLremove(currentCount - 1);
currentCount--;
}
}
System.out.println();
}
/**
* Test H5PLset_loading_state and H5PLget_loading_state
*/
@Test
public void testH5PLset_and_get_loading_state()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get initial state
int result = hdf5_h.H5PLget_loading_state(stateSeg);
assertEquals("H5PLget_loading_state should succeed", 0, result);
int originalState = stateSeg.get(ValueLayout.JAVA_INT, 0);
// Enable all plugins
result = hdf5_h.H5PLset_loading_state(hdf5_h.H5PL_ALL_PLUGIN());
assertEquals("H5PLset_loading_state should succeed", 0, result);
result = hdf5_h.H5PLget_loading_state(stateSeg);
assertEquals("H5PLget_loading_state should succeed", 0, result);
int allState = stateSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("All plugins should be enabled", hdf5_h.H5PL_ALL_PLUGIN(), allState);
// Enable only filter plugins
result = hdf5_h.H5PLset_loading_state(hdf5_h.H5PL_FILTER_PLUGIN());
assertEquals("H5PLset_loading_state should succeed", 0, result);
result = hdf5_h.H5PLget_loading_state(stateSeg);
assertEquals("H5PLget_loading_state should succeed", 0, result);
int filterState = stateSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Only filter plugins should be enabled", hdf5_h.H5PL_FILTER_PLUGIN(), filterState);
// Disable all plugins
result = hdf5_h.H5PLset_loading_state(0);
assertEquals("H5PLset_loading_state should succeed", 0, result);
result = hdf5_h.H5PLget_loading_state(stateSeg);
assertEquals("H5PLget_loading_state should succeed", 0, result);
int disabledState = stateSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("All plugins should be disabled", 0, disabledState);
// Restore original state
hdf5_h.H5PLset_loading_state(originalState);
}
}
/**
* Test H5PLsize - get number of plugin search paths
*/
@Test
public void testH5PLsize()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
int result = hdf5_h.H5PLsize(countSeg);
assertEquals("H5PLsize should succeed", 0, result);
int pathCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertTrue("Path count should be non-negative", pathCount >= 0);
}
}
/**
* Test H5PLappend - add path to end of search list
*/
@Test
public void testH5PLappend()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get initial count
hdf5_h.H5PLsize(countSeg);
int initialCount = countSeg.get(ValueLayout.JAVA_INT, 0);
// Append a test path
MemorySegment testPath = stringToSegment(arena, "/tmp/test_plugin_path");
int result = hdf5_h.H5PLappend(testPath);
assertEquals("H5PLappend should succeed", 0, result);
// Verify count increased
hdf5_h.H5PLsize(countSeg);
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Path count should increase by 1", initialCount + 1, newCount);
// Verify the path was added at the end
long size = hdf5_h.H5PLget(newCount - 1, MemorySegment.NULL, 0);
assertTrue("Should get path size", size > 0);
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
size = hdf5_h.H5PLget(newCount - 1, pathBuf, size + 1);
String retrievedPath = segmentToString(pathBuf);
assertEquals("Retrieved path should match", "/tmp/test_plugin_path", retrievedPath);
}
}
/**
* Test H5PLprepend - add path to beginning of search list
*/
@Test
public void testH5PLprepend()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get initial count
hdf5_h.H5PLsize(countSeg);
int initialCount = countSeg.get(ValueLayout.JAVA_INT, 0);
// Prepend a test path
MemorySegment testPath = stringToSegment(arena, "/tmp/test_prepend_path");
int result = hdf5_h.H5PLprepend(testPath);
assertEquals("H5PLprepend should succeed", 0, result);
// Verify count increased
hdf5_h.H5PLsize(countSeg);
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Path count should increase by 1", initialCount + 1, newCount);
// Verify the path was added at the beginning (index 0)
long size = hdf5_h.H5PLget(0, MemorySegment.NULL, 0);
assertTrue("Should get path size", size > 0);
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
size = hdf5_h.H5PLget(0, pathBuf, size + 1);
String retrievedPath = segmentToString(pathBuf);
assertEquals("Retrieved path should match", "/tmp/test_prepend_path", retrievedPath);
}
}
/**
* Test H5PLinsert - insert path at specific index
*/
@Test
public void testH5PLinsert()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Add two paths first
MemorySegment path1 = stringToSegment(arena, "/tmp/path1");
MemorySegment path2 = stringToSegment(arena, "/tmp/path2");
hdf5_h.H5PLappend(path1);
hdf5_h.H5PLappend(path2);
// Get count before insert
hdf5_h.H5PLsize(countSeg);
int beforeCount = countSeg.get(ValueLayout.JAVA_INT, 0);
// Insert path at index 1 (between path1 and path2)
MemorySegment insertPath = stringToSegment(arena, "/tmp/path_inserted");
int result = hdf5_h.H5PLinsert(insertPath, beforeCount - 1);
assertEquals("H5PLinsert should succeed", 0, result);
// Verify count increased
hdf5_h.H5PLsize(countSeg);
int afterCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Path count should increase by 1", beforeCount + 1, afterCount);
// Verify the path was inserted at correct position
long size = hdf5_h.H5PLget(beforeCount - 1, MemorySegment.NULL, 0);
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
hdf5_h.H5PLget(beforeCount - 1, pathBuf, size + 1);
String retrievedPath = segmentToString(pathBuf);
assertEquals("Retrieved path should match", "/tmp/path_inserted", retrievedPath);
}
}
/**
* Test H5PLreplace - replace path at specific index
*/
@Test
public void testH5PLreplace()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Add a test path
MemorySegment originalPath = stringToSegment(arena, "/tmp/original_path");
hdf5_h.H5PLappend(originalPath);
// Get count and index of last path
hdf5_h.H5PLsize(countSeg);
int count = countSeg.get(ValueLayout.JAVA_INT, 0);
int lastIdx = count - 1;
// Replace the last path
MemorySegment replacePath = stringToSegment(arena, "/tmp/replacement_path");
int result = hdf5_h.H5PLreplace(replacePath, lastIdx);
assertEquals("H5PLreplace should succeed", 0, result);
// Verify count unchanged
hdf5_h.H5PLsize(countSeg);
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Path count should remain the same", count, newCount);
// Verify the path was replaced
long size = hdf5_h.H5PLget(lastIdx, MemorySegment.NULL, 0);
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
hdf5_h.H5PLget(lastIdx, pathBuf, size + 1);
String retrievedPath = segmentToString(pathBuf);
assertEquals("Retrieved path should be replacement", "/tmp/replacement_path", retrievedPath);
}
}
/**
* Test H5PLremove - remove path at specific index
*/
@Test
public void testH5PLremove()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Add a test path
MemorySegment testPath = stringToSegment(arena, "/tmp/path_to_remove");
hdf5_h.H5PLappend(testPath);
// Get count before removal
hdf5_h.H5PLsize(countSeg);
int beforeCount = countSeg.get(ValueLayout.JAVA_INT, 0);
// Remove the last path
int result = hdf5_h.H5PLremove(beforeCount - 1);
assertEquals("H5PLremove should succeed", 0, result);
// Verify count decreased
hdf5_h.H5PLsize(countSeg);
int afterCount = countSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Path count should decrease by 1", beforeCount - 1, afterCount);
}
}
/**
* Test H5PLget - retrieve path at specific index
*/
@Test
public void testH5PLget()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
// Add a known test path
String knownPath = "/tmp/test_get_path";
MemorySegment testPath = stringToSegment(arena, knownPath);
hdf5_h.H5PLappend(testPath);
// Get the index of the path we just added
hdf5_h.H5PLsize(countSeg);
int count = countSeg.get(ValueLayout.JAVA_INT, 0);
int lastIdx = count - 1;
// First call to get size (with NULL buffer)
long size = hdf5_h.H5PLget(lastIdx, MemorySegment.NULL, 0);
assertTrue("Should return path length", size > 0);
// Second call to get actual path
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
long actualSize = hdf5_h.H5PLget(lastIdx, pathBuf, size + 1);
assertEquals("Sizes should match", size, actualSize);
String retrievedPath = segmentToString(pathBuf);
assertEquals("Retrieved path should match", knownPath, retrievedPath);
}
}
/**
* Test H5PLget with invalid index
*/
@Test
public void testH5PLget_invalid_index()
{
try (Arena arena = Arena.ofConfined()) {
// Try to get path at very large invalid index
long size = hdf5_h.H5PLget(99999, MemorySegment.NULL, 0);
// Should return negative value or zero for invalid index
assertTrue("Should return error for invalid index", size <= 0);
}
}
/**
* Test plugin type constants
*/
@Test
public void testH5PL_plugin_type_constants()
{
// Verify plugin type flag constants exist and have expected values
int filterPlugin = hdf5_h.H5PL_FILTER_PLUGIN();
int volPlugin = hdf5_h.H5PL_VOL_PLUGIN();
int vfdPlugin = hdf5_h.H5PL_VFD_PLUGIN();
int allPlugin = hdf5_h.H5PL_ALL_PLUGIN();
// Filter plugin should be bit 0
assertEquals("H5PL_FILTER_PLUGIN should be 0x0001", 0x0001, filterPlugin);
// VOL plugin should be bit 1
assertEquals("H5PL_VOL_PLUGIN should be 0x0002", 0x0002, volPlugin);
// VFD plugin should be bit 2
assertEquals("H5PL_VFD_PLUGIN should be 0x0004", 0x0004, vfdPlugin);
// All plugins should be 0xFFFF
assertEquals("H5PL_ALL_PLUGIN should be 0xFFFF", 0xFFFF, allPlugin);
}
/**
* Test multiple plugin types enabled simultaneously
*/
@Test
public void testH5PL_multiple_plugin_types()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
// Enable filter and VOL plugins
int combinedMask = hdf5_h.H5PL_FILTER_PLUGIN() | hdf5_h.H5PL_VOL_PLUGIN();
int result = hdf5_h.H5PLset_loading_state(combinedMask);
assertEquals("H5PLset_loading_state should succeed", 0, result);
// Verify state
hdf5_h.H5PLget_loading_state(stateSeg);
int state = stateSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("State should match combined mask", combinedMask, state);
// Verify individual bits are set
assertTrue("Filter plugin should be enabled", (state & hdf5_h.H5PL_FILTER_PLUGIN()) != 0);
assertTrue("VOL plugin should be enabled", (state & hdf5_h.H5PL_VOL_PLUGIN()) != 0);
assertFalse("VFD plugin should not be enabled", (state & hdf5_h.H5PL_VFD_PLUGIN()) != 0);
}
}
}
+2693
View File
@@ -0,0 +1,2693 @@
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class TestH5Pffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "testPffm.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5fcpl = hdf5_h.H5I_INVALID_HID();
long H5fapl = hdf5_h.H5I_INVALID_HID();
long H5dcpl = hdf5_h.H5I_INVALID_HID();
long H5dxpl = hdf5_h.H5I_INVALID_HID();
private static void _deleteFile(String filename)
{
java.io.File file = new java.io.File(filename);
if (file.exists()) {
try {
file.delete();
}
catch (SecurityException e) {
// Ignore
}
}
}
@Before
public void createH5file()
{
// Ensure HDF5 library is initialized (prevents FFM constant initialization issues)
hdf5_h.H5open();
H5fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl", isValidId(H5fcpl));
H5fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl", isValidId(H5fapl));
try (Arena arena = Arena.ofConfined()) {
H5fid = hdf5_h.H5Fcreate(stringToSegment(arena, H5_FILE), hdf5_h.H5F_ACC_TRUNC(), H5fcpl, H5fapl);
}
assertTrue("H5Fcreate", isValidId(H5fid));
}
@After
public void deleteH5file()
{
if (H5dxpl > 0)
try {
hdf5_h.H5Pclose(H5dxpl);
}
catch (Exception ex) {
}
if (H5dcpl > 0)
try {
hdf5_h.H5Pclose(H5dcpl);
}
catch (Exception ex) {
}
if (H5fid > 0)
try {
hdf5_h.H5Fclose(H5fid);
}
catch (Exception ex) {
}
if (H5fapl > 0)
try {
hdf5_h.H5Pclose(H5fapl);
}
catch (Exception ex) {
}
if (H5fcpl > 0)
try {
hdf5_h.H5Pclose(H5fcpl);
}
catch (Exception ex) {
}
_deleteFile(H5_FILE);
}
// =========================
// Generic Property List Tests
// =========================
@Test
public void testH5Pcreate()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create dataset creation property list
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Verify it's the right class
long cls = hdf5_h.H5Pget_class(dcpl);
assertTrue("H5Pget_class failed", isValidId(cls));
int equal = hdf5_h.H5Pequal(cls, hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("Class should match H5P_DATASET_CREATE", equal > 0);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pclose()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create property list
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Close it
int result = hdf5_h.H5Pclose(dcpl);
assertTrue("H5Pclose failed", isSuccess(result));
// Verify it's closed (H5Iis_valid should return false)
int valid = hdf5_h.H5Iis_valid(dcpl);
assertEquals("Property list should be invalid after close", 0, valid);
}
}
@Test
public void testH5Pcopy()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create dataset creation property list with chunk settings
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set chunk dimensions
long[] chunkDims = {10, 20};
MemorySegment chunkSeg = allocateLongArray(arena, 2);
copyToSegment(chunkSeg, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkSeg);
// Copy property list
long dcpl_copy = hdf5_h.H5Pcopy(dcpl);
assertTrue("H5Pcopy failed", isValidId(dcpl_copy));
// Verify copy has same settings
MemorySegment outChunk = allocateLongArray(arena, 2);
int ndims = hdf5_h.H5Pget_chunk(dcpl_copy, 2, outChunk);
assertEquals("Should have 2 dimensions", 2, ndims);
long[] retrieved = new long[2];
copyFromSegment(outChunk, retrieved);
assertArrayEquals("Chunk dimensions should match in copy", chunkDims, retrieved);
hdf5_h.H5Pclose(dcpl_copy);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pequal()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create two identical property lists
long dcpl1 = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
long dcpl2 = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
// They should be equal (both are default dataset create plists)
int equal = hdf5_h.H5Pequal(dcpl1, dcpl2);
assertTrue("Default property lists should be equal", equal > 0);
// Modify one
long[] chunkDims = {10, 20};
MemorySegment chunkSeg = allocateLongArray(arena, 2);
copyToSegment(chunkSeg, chunkDims);
hdf5_h.H5Pset_chunk(dcpl1, 2, chunkSeg);
// Now they should be different
equal = hdf5_h.H5Pequal(dcpl1, dcpl2);
assertEquals("Modified property lists should not be equal", 0, equal);
hdf5_h.H5Pclose(dcpl2);
hdf5_h.H5Pclose(dcpl1);
}
}
@Test
public void testH5Pget_class()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create different types of property lists
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
// Get their classes
long fcpl_class = hdf5_h.H5Pget_class(fcpl);
long dcpl_class = hdf5_h.H5Pget_class(dcpl);
// Verify correct classes
int fcpl_equal = hdf5_h.H5Pequal(fcpl_class, hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("FCPL class should match FILE_CREATE", fcpl_equal > 0);
int dcpl_equal = hdf5_h.H5Pequal(dcpl_class, hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("DCPL class should match DATASET_CREATE", dcpl_equal > 0);
// Verify they're different classes
int different = hdf5_h.H5Pequal(fcpl_class, dcpl_class);
assertEquals("FILE_CREATE and DATASET_CREATE should be different classes", 0, different);
hdf5_h.H5Pclose(dcpl);
hdf5_h.H5Pclose(fcpl);
}
}
// =========================
// File Creation Property Tests
// =========================
@Test
public void testH5Pset_userblock()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set user block size (must be power of 2 >= 512)
long userblock_size = 1024;
int result = hdf5_h.H5Pset_userblock(fcpl, userblock_size);
assertTrue("H5Pset_userblock failed", isSuccess(result));
// Get user block size back
MemorySegment sizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_userblock(fcpl, sizeSeg);
assertTrue("H5Pget_userblock failed", isSuccess(result));
long retrieved = getLong(sizeSeg);
assertEquals("User block size should match", userblock_size, retrieved);
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_sizes()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set sizes (sizeof_addr=8, sizeof_size=8 for 64-bit addressing)
long sizeof_addr = 8;
long sizeof_size = 8;
int result = hdf5_h.H5Pset_sizes(fcpl, sizeof_addr, sizeof_size);
assertTrue("H5Pset_sizes failed", isSuccess(result));
// Get sizes back
MemorySegment addrSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment sizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_sizes(fcpl, addrSeg, sizeSeg);
assertTrue("H5Pget_sizes failed", isSuccess(result));
long addr_retrieved = getLong(addrSeg);
long size_retrieved = getLong(sizeSeg);
assertEquals("Address size should match", sizeof_addr, addr_retrieved);
assertEquals("Size size should match", sizeof_size, size_retrieved);
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_sym_k()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set symbol table parameters (ik=tree rank, lk=node size)
int ik = 32;
int lk = 16;
int result = hdf5_h.H5Pset_sym_k(fcpl, ik, lk);
assertTrue("H5Pset_sym_k failed", isSuccess(result));
// Get parameters back
MemorySegment ikSeg = arena.allocate(ValueLayout.JAVA_INT);
MemorySegment lkSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_sym_k(fcpl, ikSeg, lkSeg);
assertTrue("H5Pget_sym_k failed", isSuccess(result));
int ik_retrieved = getInt(ikSeg);
int lk_retrieved = getInt(lkSeg);
assertEquals("ik parameter should match", ik, ik_retrieved);
assertEquals("lk parameter should match", lk, lk_retrieved);
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_istore_k()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set indexed storage B-tree parameter
int ik = 64;
int result = hdf5_h.H5Pset_istore_k(fcpl, ik);
assertTrue("H5Pset_istore_k failed", isSuccess(result));
// Get parameter back
MemorySegment ikSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_istore_k(fcpl, ikSeg);
assertTrue("H5Pget_istore_k failed", isSuccess(result));
int ik_retrieved = getInt(ikSeg);
assertEquals("istore_k parameter should match", ik, ik_retrieved);
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_shared_mesg_nindexes()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set number of shared object header message indexes
int nindexes = 3;
int result = hdf5_h.H5Pset_shared_mesg_nindexes(fcpl, nindexes);
assertTrue("H5Pset_shared_mesg_nindexes failed", isSuccess(result));
// Get number back
MemorySegment nindexSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_shared_mesg_nindexes(fcpl, nindexSeg);
assertTrue("H5Pget_shared_mesg_nindexes failed", isSuccess(result));
int nindexes_retrieved = getInt(nindexSeg);
assertEquals("Number of indexes should match", nindexes, nindexes_retrieved);
hdf5_h.H5Pclose(fcpl);
}
}
// =========================
// File Access Property Tests
// =========================
@Test
public void testH5Pset_fclose_degree()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set file close degree to STRONG (close all objects when file closes)
int degree = hdf5_h.H5F_CLOSE_STRONG();
int result = hdf5_h.H5Pset_fclose_degree(fapl, degree);
assertTrue("H5Pset_fclose_degree failed", isSuccess(result));
// Get degree back
MemorySegment degreeSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_fclose_degree(fapl, degreeSeg);
assertTrue("H5Pget_fclose_degree failed", isSuccess(result));
int degree_retrieved = getInt(degreeSeg);
assertEquals("File close degree should match", degree, degree_retrieved);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_alignment()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set alignment (threshold=1024, alignment=512)
long threshold = 1024;
long alignment = 512;
int result = hdf5_h.H5Pset_alignment(fapl, threshold, alignment);
assertTrue("H5Pset_alignment failed", isSuccess(result));
// Get alignment back
MemorySegment threshSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment alignSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_alignment(fapl, threshSeg, alignSeg);
assertTrue("H5Pget_alignment failed", isSuccess(result));
long threshold_retrieved = getLong(threshSeg);
long alignment_retrieved = getLong(alignSeg);
assertEquals("Threshold should match", threshold, threshold_retrieved);
assertEquals("Alignment should match", alignment, alignment_retrieved);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_cache()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set cache parameters
int mdc_nelmts = 0; // Not used, set to 0
long rdcc_nslots = 521;
long rdcc_nbytes = 1048576;
double rdcc_w0 = 0.75;
int result = hdf5_h.H5Pset_cache(fapl, mdc_nelmts, rdcc_nslots, rdcc_nbytes, rdcc_w0);
assertTrue("H5Pset_cache failed", isSuccess(result));
// Get cache parameters back
MemorySegment mdcSeg = arena.allocate(ValueLayout.JAVA_INT);
MemorySegment nslotSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment nbyteSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment w0Seg = arena.allocate(ValueLayout.JAVA_DOUBLE);
result = hdf5_h.H5Pget_cache(fapl, mdcSeg, nslotSeg, nbyteSeg, w0Seg);
assertTrue("H5Pget_cache failed", isSuccess(result));
long nslots_retrieved = getLong(nslotSeg);
long nbytes_retrieved = getLong(nbyteSeg);
double w0_retrieved = getDouble(w0Seg);
assertEquals("rdcc_nslots should match", rdcc_nslots, nslots_retrieved);
assertEquals("rdcc_nbytes should match", rdcc_nbytes, nbytes_retrieved);
assertEquals("rdcc_w0 should match", rdcc_w0, w0_retrieved, 0.001);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_sieve_buf_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set data sieve buffer size
long size = 262144; // 256KB
int result = hdf5_h.H5Pset_sieve_buf_size(fapl, size);
assertTrue("H5Pset_sieve_buf_size failed", isSuccess(result));
// Get size back
MemorySegment sizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_sieve_buf_size(fapl, sizeSeg);
assertTrue("H5Pget_sieve_buf_size failed", isSuccess(result));
long size_retrieved = getLong(sizeSeg);
assertEquals("Sieve buffer size should match", size, size_retrieved);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_meta_block_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set metadata block size
long size = 8192;
int result = hdf5_h.H5Pset_meta_block_size(fapl, size);
assertTrue("H5Pset_meta_block_size failed", isSuccess(result));
// Get size back
MemorySegment sizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_meta_block_size(fapl, sizeSeg);
assertTrue("H5Pget_meta_block_size failed", isSuccess(result));
long size_retrieved = getLong(sizeSeg);
assertEquals("Meta block size should match", size, size_retrieved);
hdf5_h.H5Pclose(fapl);
}
}
// ================================================================================
// Phase 6B - Dataset Creation Properties
// ================================================================================
@Test
public void testH5Pset_chunk()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set chunk dimensions: 10x20
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Get chunk dimensions back
MemorySegment outChunkSegment = allocateLongArray(arena, 2);
int ndims = hdf5_h.H5Pget_chunk(dcpl, 2, outChunkSegment);
assertEquals("Should have 2 dimensions", 2, ndims);
long[] retrieved = new long[2];
copyFromSegment(outChunkSegment, retrieved);
assertArrayEquals("Chunk dimensions should match", chunkDims, retrieved);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_layout()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set layout to compact
int result = hdf5_h.H5Pset_layout(dcpl, hdf5_h.H5D_COMPACT());
assertTrue("H5Pset_layout failed", isSuccess(result));
// Get layout back
int layout = hdf5_h.H5Pget_layout(dcpl);
assertEquals("Layout should be H5D_COMPACT", hdf5_h.H5D_COMPACT(), layout);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_fill_value()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set fill value to 42
int fillValue = 42;
MemorySegment fillSegment = allocateInt(arena);
setInt(fillSegment, fillValue);
int result = hdf5_h.H5Pset_fill_value(dcpl, hdf5_h.H5T_NATIVE_INT_g(), fillSegment);
assertTrue("H5Pset_fill_value failed", isSuccess(result));
// Get fill value back
MemorySegment outFillSegment = allocateInt(arena);
result = hdf5_h.H5Pget_fill_value(dcpl, hdf5_h.H5T_NATIVE_INT_g(), outFillSegment);
assertTrue("H5Pget_fill_value failed", isSuccess(result));
int retrieved = getInt(outFillSegment);
assertEquals("Fill value should match", fillValue, retrieved);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_fill_time()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set fill time to ALLOC (fill on allocation)
int result = hdf5_h.H5Pset_fill_time(dcpl, hdf5_h.H5D_FILL_TIME_ALLOC());
assertTrue("H5Pset_fill_time failed", isSuccess(result));
// Get fill time back
MemorySegment fillTimeSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_fill_time(dcpl, fillTimeSeg);
assertTrue("H5Pget_fill_time failed", isSuccess(result));
int fillTime = getInt(fillTimeSeg);
assertEquals("Fill time should be H5D_FILL_TIME_ALLOC", hdf5_h.H5D_FILL_TIME_ALLOC(), fillTime);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_alloc_time()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set allocation time to EARLY (allocate on creation)
int result = hdf5_h.H5Pset_alloc_time(dcpl, hdf5_h.H5D_ALLOC_TIME_EARLY());
assertTrue("H5Pset_alloc_time failed", isSuccess(result));
// Get allocation time back
MemorySegment allocTimeSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_alloc_time(dcpl, allocTimeSeg);
assertTrue("H5Pget_alloc_time failed", isSuccess(result));
int allocTime = getInt(allocTimeSeg);
assertEquals("Allocation time should be H5D_ALLOC_TIME_EARLY", hdf5_h.H5D_ALLOC_TIME_EARLY(),
allocTime);
hdf5_h.H5Pclose(dcpl);
}
}
// ================================================================================
// Phase 6C - Compression and Filters
// ================================================================================
@Test
public void testH5Pset_deflate()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Must set chunk first for compression
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Set deflate compression (gzip) with level 6
int compressionLevel = 6;
result = hdf5_h.H5Pset_deflate(dcpl, compressionLevel);
assertTrue("H5Pset_deflate failed", isSuccess(result));
// Get number of filters
int nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 1 filter", 1, nfilters);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_nfilters()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Initially no filters
int nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 0 filters initially", 0, nfilters);
// Add chunk (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
// Add deflate filter
hdf5_h.H5Pset_deflate(dcpl, 6);
// Now should have 1 filter
nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 1 filter after adding deflate", 1, nfilters);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pall_filters_avail()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Add chunk (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
// Add deflate filter (should be available in standard builds)
hdf5_h.H5Pset_deflate(dcpl, 6);
// Check if all filters are available
int avail = hdf5_h.H5Pall_filters_avail(dcpl);
// Note: Result depends on HDF5 build configuration
// Just verify the function works (returns 0 or 1)
assertTrue("H5Pall_filters_avail should return valid result", avail == 0 || avail > 0);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_shuffle()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Add chunk (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
// Set shuffle filter (improves compression)
int result = hdf5_h.H5Pset_shuffle(dcpl);
assertTrue("H5Pset_shuffle failed", isSuccess(result));
// Verify filter was added
int nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 1 filter", 1, nfilters);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_fletcher32()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Add chunk (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
// Set Fletcher32 checksum filter (error detection)
int result = hdf5_h.H5Pset_fletcher32(dcpl);
assertTrue("H5Pset_fletcher32 failed", isSuccess(result));
// Verify filter was added
int nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 1 filter", 1, nfilters);
hdf5_h.H5Pclose(dcpl);
}
}
// ================================================================================
// Phase 6D - Data Transfer and Advanced Properties
// ================================================================================
// Note: H5Pget_filter might not be available in FFM bindings yet
// Skipping this test until API is available
/*
@Test
public void testH5Pget_filter()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Must set chunk first
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Add deflate filter
int compressionLevel = 6;
result = hdf5_h.H5Pset_deflate(dcpl, compressionLevel);
assertTrue("H5Pset_deflate failed", isSuccess(result));
// Get filter information
MemorySegment flags = allocateIntArray(arena, 1);
MemorySegment cdNelts = allocateLongArray(arena, 1);
MemorySegment cdValues = allocateIntArray(arena, 10); // Space for filter params
MemorySegment nameSegment = arena.allocate(256);
MemorySegment filterConfig = allocateIntArray(arena, 1);
// Set initial cd_nelmts to max size
copyToSegment(cdNelts, new long[]{10});
int filterId = hdf5_h.H5Pget_filter(dcpl, 0, flags, cdNelts, cdValues,
256, nameSegment, filterConfig);
assertTrue("H5Pget_filter should return valid filter ID", filterId >= 0);
// Verify it's the deflate filter
assertEquals("Should be deflate filter", hdf5_h.H5Z_FILTER_DEFLATE(), filterId);
hdf5_h.H5Pclose(dcpl);
}
}
*/
@Test
public void testH5Premove_filter()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Must set chunk first
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
int result = hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
assertTrue("H5Pset_chunk failed", isSuccess(result));
// Add deflate filter
result = hdf5_h.H5Pset_deflate(dcpl, 6);
assertTrue("H5Pset_deflate failed", isSuccess(result));
// Verify filter was added
int nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 1 filter", 1, nfilters);
// Remove the deflate filter
result = hdf5_h.H5Premove_filter(dcpl, hdf5_h.H5Z_FILTER_DEFLATE());
assertTrue("H5Premove_filter failed", isSuccess(result));
// Verify filter was removed
nfilters = hdf5_h.H5Pget_nfilters(dcpl);
assertEquals("Should have 0 filters after removal", 0, nfilters);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_chunk_cache()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_ACCESS_ID_g());
assertTrue("H5Pcreate dapl failed", isValidId(dapl));
// Set chunk cache parameters
long rdccNslots = 521; // Number of chunk slots in cache
long rdccNbytes = 1048576; // Size of chunk cache in bytes (1 MB)
double rdccW0 = 0.75; // Preemption policy
int result = hdf5_h.H5Pset_chunk_cache(dapl, rdccNslots, rdccNbytes, rdccW0);
assertTrue("H5Pset_chunk_cache failed", isSuccess(result));
// Get chunk cache parameters back
MemorySegment outNslots = allocateLongArray(arena, 1);
MemorySegment outNbytes = allocateLongArray(arena, 1);
MemorySegment outW0 = allocateDoubleArray(arena, 1);
result = hdf5_h.H5Pget_chunk_cache(dapl, outNslots, outNbytes, outW0);
assertTrue("H5Pget_chunk_cache failed", isSuccess(result));
// Verify values
assertEquals("Nslots should match", rdccNslots, getLong(outNslots));
assertEquals("Nbytes should match", rdccNbytes, getLong(outNbytes));
assertEquals("W0 should match", rdccW0, getDouble(outW0), 0.01);
hdf5_h.H5Pclose(dapl);
}
}
@Test
public void testH5Pset_hyper_vector_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Set hyperslab vector size
long vectorSize = 1024;
int result = hdf5_h.H5Pset_hyper_vector_size(dxpl, vectorSize);
assertTrue("H5Pset_hyper_vector_size failed", isSuccess(result));
// Get vector size back
MemorySegment outSize = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_hyper_vector_size(dxpl, outSize);
assertTrue("H5Pget_hyper_vector_size failed", isSuccess(result));
assertEquals("Vector size should match", vectorSize, getLong(outSize));
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_btree_ratios()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Set B-tree split ratios
double left = 0.1;
double middle = 0.5;
double right = 0.9;
int result = hdf5_h.H5Pset_btree_ratios(dxpl, left, middle, right);
assertTrue("H5Pset_btree_ratios failed", isSuccess(result));
// Get ratios back
MemorySegment outLeft = allocateDoubleArray(arena, 1);
MemorySegment outMiddle = allocateDoubleArray(arena, 1);
MemorySegment outRight = allocateDoubleArray(arena, 1);
result = hdf5_h.H5Pget_btree_ratios(dxpl, outLeft, outMiddle, outRight);
assertTrue("H5Pget_btree_ratios failed", isSuccess(result));
assertEquals("Left ratio should match", left, getDouble(outLeft), 0.01);
assertEquals("Middle ratio should match", middle, getDouble(outMiddle), 0.01);
assertEquals("Right ratio should match", right, getDouble(outRight), 0.01);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_edc_check()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Enable error detection (EDC)
int result = hdf5_h.H5Pset_edc_check(dxpl, hdf5_h.H5Z_ENABLE_EDC());
assertTrue("H5Pset_edc_check failed", isSuccess(result));
// Get EDC check setting
int edcCheck = hdf5_h.H5Pget_edc_check(dxpl);
assertEquals("EDC check should be enabled", hdf5_h.H5Z_ENABLE_EDC(), edcCheck);
// Disable error detection
result = hdf5_h.H5Pset_edc_check(dxpl, hdf5_h.H5Z_DISABLE_EDC());
assertTrue("H5Pset_edc_check (disable) failed", isSuccess(result));
edcCheck = hdf5_h.H5Pget_edc_check(dxpl);
assertEquals("EDC check should be disabled", hdf5_h.H5Z_DISABLE_EDC(), edcCheck);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_buffer()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Set type conversion buffer size (1 MB)
long bufferSize = 1048576;
int result = hdf5_h.H5Pset_buffer(dxpl, bufferSize, MemorySegment.NULL, MemorySegment.NULL);
assertTrue("H5Pset_buffer failed", isSuccess(result));
// Get buffer size back
long retrievedSize = hdf5_h.H5Pget_buffer(dxpl, MemorySegment.NULL, MemorySegment.NULL);
assertEquals("Buffer size should match", bufferSize, retrievedSize);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_libver_bounds()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set library version bounds to latest
int result =
hdf5_h.H5Pset_libver_bounds(fapl, hdf5_h.H5F_LIBVER_LATEST(), hdf5_h.H5F_LIBVER_LATEST());
assertTrue("H5Pset_libver_bounds failed", isSuccess(result));
// Get library version bounds back
MemorySegment low = allocateIntArray(arena, 1);
MemorySegment high = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_libver_bounds(fapl, low, high);
assertTrue("H5Pget_libver_bounds failed", isSuccess(result));
assertEquals("Low bound should be latest", hdf5_h.H5F_LIBVER_LATEST(), getInt(low));
assertEquals("High bound should be latest", hdf5_h.H5F_LIBVER_LATEST(), getInt(high));
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_small_data_block_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set small data block size (2048 bytes)
long blockSize = 2048;
int result = hdf5_h.H5Pset_small_data_block_size(fapl, blockSize);
assertTrue("H5Pset_small_data_block_size failed", isSuccess(result));
// Get block size back
MemorySegment outSize = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_small_data_block_size(fapl, outSize);
assertTrue("H5Pget_small_data_block_size failed", isSuccess(result));
assertEquals("Block size should match", blockSize, getLong(outSize));
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_gc_references()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Enable garbage collection for references
int result = hdf5_h.H5Pset_gc_references(fapl, 1);
assertTrue("H5Pset_gc_references failed", isSuccess(result));
// Get GC references setting
MemorySegment gcRefs = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_gc_references(fapl, gcRefs);
assertTrue("H5Pget_gc_references failed", isSuccess(result));
assertEquals("GC references should be enabled", 1, getInt(gcRefs));
// Disable garbage collection
result = hdf5_h.H5Pset_gc_references(fapl, 0);
assertTrue("H5Pset_gc_references (disable) failed", isSuccess(result));
result = hdf5_h.H5Pget_gc_references(fapl, gcRefs);
assertTrue("H5Pget_gc_references (after disable) failed", isSuccess(result));
assertEquals("GC references should be disabled", 0, getInt(gcRefs));
hdf5_h.H5Pclose(fapl);
}
}
// ================================================================================
// Phase 6E - Link, Attribute, and Advanced Properties
// ================================================================================
@Test
public void testH5Pset_create_intermediate_group()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long lcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_LINK_CREATE_ID_g());
assertTrue("H5Pcreate lcpl failed", isValidId(lcpl));
// Enable intermediate group creation
int result = hdf5_h.H5Pset_create_intermediate_group(lcpl, 1);
assertTrue("H5Pset_create_intermediate_group failed", isSuccess(result));
// Get setting back
MemorySegment crtIntmd = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_create_intermediate_group(lcpl, crtIntmd);
assertTrue("H5Pget_create_intermediate_group failed", isSuccess(result));
assertEquals("Create intermediate should be enabled", 1, getInt(crtIntmd));
hdf5_h.H5Pclose(lcpl);
}
}
@Test
public void testH5Pset_char_encoding()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long lcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_LINK_CREATE_ID_g());
assertTrue("H5Pcreate lcpl failed", isValidId(lcpl));
// Set character encoding to UTF-8
int result = hdf5_h.H5Pset_char_encoding(lcpl, hdf5_h.H5T_CSET_UTF8());
assertTrue("H5Pset_char_encoding failed", isSuccess(result));
// Get encoding back
MemorySegment encoding = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_char_encoding(lcpl, encoding);
assertTrue("H5Pget_char_encoding failed", isSuccess(result));
assertEquals("Encoding should be UTF-8", hdf5_h.H5T_CSET_UTF8(), getInt(encoding));
hdf5_h.H5Pclose(lcpl);
}
}
@Test
public void testH5Pset_attr_creation_order()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_CREATE_ID_g());
assertTrue("H5Pcreate ocpl failed", isValidId(ocpl));
// Set attribute creation order tracking and indexing
int crtOrderFlags = hdf5_h.H5P_CRT_ORDER_TRACKED() | hdf5_h.H5P_CRT_ORDER_INDEXED();
int result = hdf5_h.H5Pset_attr_creation_order(ocpl, crtOrderFlags);
assertTrue("H5Pset_attr_creation_order failed", isSuccess(result));
// Get flags back
MemorySegment flags = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_attr_creation_order(ocpl, flags);
assertTrue("H5Pget_attr_creation_order failed", isSuccess(result));
assertEquals("Attr creation order flags should match", crtOrderFlags, getInt(flags));
hdf5_h.H5Pclose(ocpl);
}
}
@Test
public void testH5Pset_nlinks()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long lapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_LINK_ACCESS_ID_g());
assertTrue("H5Pcreate lapl failed", isValidId(lapl));
// Set maximum number of soft/external link traversals
long nlinks = 100;
int result = hdf5_h.H5Pset_nlinks(lapl, nlinks);
assertTrue("H5Pset_nlinks failed", isSuccess(result));
// Get nlinks back
MemorySegment outNlinks = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_nlinks(lapl, outNlinks);
assertTrue("H5Pget_nlinks failed", isSuccess(result));
assertEquals("Nlinks should match", nlinks, getLong(outNlinks));
hdf5_h.H5Pclose(lapl);
}
}
@Test
public void testH5Pset_efile_prefix()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_ACCESS_ID_g());
assertTrue("H5Pcreate dapl failed", isValidId(dapl));
// Set external file prefix
String prefix = "/tmp/external";
MemorySegment prefixSeg = stringToSegment(arena, prefix);
int result = hdf5_h.H5Pset_efile_prefix(dapl, prefixSeg);
assertTrue("H5Pset_efile_prefix failed", isSuccess(result));
// Get prefix back
long prefixSize = hdf5_h.H5Pget_efile_prefix(dapl, MemorySegment.NULL, 0);
assertTrue("H5Pget_efile_prefix size query failed", prefixSize > 0);
MemorySegment prefixBuf = arena.allocate(prefixSize + 1);
result = (int)hdf5_h.H5Pget_efile_prefix(dapl, prefixBuf, prefixSize + 1);
assertTrue("H5Pget_efile_prefix failed", result >= 0);
String retrievedPrefix = segmentToString(prefixBuf);
assertEquals("Prefix should match", prefix, retrievedPrefix);
hdf5_h.H5Pclose(dapl);
}
}
@Test
public void testH5Pset_chunk_opts()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Must set chunking first
long[] chunkDims = {10, 20};
MemorySegment chunkDimsSegment = allocateLongArray(arena, 2);
copyToSegment(chunkDimsSegment, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkDimsSegment);
// Set chunk optimization options (don't filter partial edge chunks)
int opts = hdf5_h.H5D_CHUNK_DONT_FILTER_PARTIAL_CHUNKS();
int result = hdf5_h.H5Pset_chunk_opts(dcpl, opts);
assertTrue("H5Pset_chunk_opts failed", isSuccess(result));
// Get options back
MemorySegment outOpts = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_chunk_opts(dcpl, outOpts);
assertTrue("H5Pget_chunk_opts failed", isSuccess(result));
assertEquals("Chunk opts should match", opts, getInt(outOpts));
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_file_space_strategy()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set file space strategy (aggregation strategy)
int strategy = hdf5_h.H5F_FSPACE_STRATEGY_FSM_AGGR(); // Free-space manager with aggregation
boolean persist = true; // Persist free-space
long threshold = 1; // Threshold
int result = hdf5_h.H5Pset_file_space_strategy(fcpl, strategy, persist, threshold);
assertTrue("H5Pset_file_space_strategy failed", isSuccess(result));
// Get strategy back
MemorySegment outStrategy = allocateIntArray(arena, 1);
MemorySegment outPersist = allocateIntArray(arena, 1);
MemorySegment outThreshold = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_file_space_strategy(fcpl, outStrategy, outPersist, outThreshold);
assertTrue("H5Pget_file_space_strategy failed", isSuccess(result));
assertEquals("Strategy should match", strategy, getInt(outStrategy));
assertEquals("Persist should be true", 1, getInt(outPersist)); // true = 1
assertEquals("Threshold should match", threshold, getLong(outThreshold));
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_file_space_page_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// Set file space page size (4KB)
long pageSize = 4096;
int result = hdf5_h.H5Pset_file_space_page_size(fcpl, pageSize);
assertTrue("H5Pset_file_space_page_size failed", isSuccess(result));
// Get page size back
MemorySegment outPageSize = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_file_space_page_size(fcpl, outPageSize);
assertTrue("H5Pget_file_space_page_size failed", isSuccess(result));
assertEquals("Page size should match", pageSize, getLong(outPageSize));
hdf5_h.H5Pclose(fcpl);
}
}
@Test
public void testH5Pset_local_heap_size_hint()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long gcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_GROUP_CREATE_ID_g());
assertTrue("H5Pcreate gcpl failed", isValidId(gcpl));
// Set local heap size hint (1KB)
long sizeHint = 1024;
int result = hdf5_h.H5Pset_local_heap_size_hint(gcpl, sizeHint);
assertTrue("H5Pset_local_heap_size_hint failed", isSuccess(result));
// Get size hint back
MemorySegment outSizeHint = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_local_heap_size_hint(gcpl, outSizeHint);
assertTrue("H5Pget_local_heap_size_hint failed", isSuccess(result));
assertEquals("Size hint should match", sizeHint, getLong(outSizeHint));
hdf5_h.H5Pclose(gcpl);
}
}
@Test
public void testH5Pset_shared_mesg_index()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_CREATE_ID_g());
assertTrue("H5Pcreate fcpl failed", isValidId(fcpl));
// First set number of indexes
hdf5_h.H5Pset_shared_mesg_nindexes(fcpl, 2);
// Set shared message index (index 0, dataspace + datatype messages, min size 100)
int indexNum = 0;
int mesgTypes = hdf5_h.H5O_SHMESG_SDSPACE_FLAG() | hdf5_h.H5O_SHMESG_DTYPE_FLAG();
int minSize = 100;
int result = hdf5_h.H5Pset_shared_mesg_index(fcpl, indexNum, mesgTypes, minSize);
assertTrue("H5Pset_shared_mesg_index failed", isSuccess(result));
// Get index info back
MemorySegment outMesgTypes = allocateIntArray(arena, 1);
MemorySegment outMinSize = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_shared_mesg_index(fcpl, indexNum, outMesgTypes, outMinSize);
assertTrue("H5Pget_shared_mesg_index failed", isSuccess(result));
assertEquals("Message types should match", mesgTypes, getInt(outMesgTypes));
assertEquals("Min size should match", minSize, getInt(outMinSize));
hdf5_h.H5Pclose(fcpl);
}
}
// =========================
// Additional Property List Tests for C API Coverage
// =========================
@Test
public void testH5Pset_data_transform()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Set a data transform expression (multiply by 2)
String transform = "x*2";
MemorySegment transformSeg = stringToSegment(arena, transform);
int result = hdf5_h.H5Pset_data_transform(dxpl, transformSeg);
assertTrue("H5Pset_data_transform failed", isSuccess(result));
// Get size of transform expression
long transformSize = hdf5_h.H5Pget_data_transform(dxpl, MemorySegment.NULL, 0);
assertTrue("H5Pget_data_transform size query failed", transformSize > 0);
// Get transform expression back
MemorySegment outTransform = arena.allocate(transformSize + 1);
long actualSize = hdf5_h.H5Pget_data_transform(dxpl, outTransform, transformSize + 1);
assertTrue("H5Pget_data_transform failed", actualSize > 0);
String retrievedTransform = segmentToString(outTransform);
assertEquals("Transform should match", transform, retrievedTransform);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_copy_object()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpypl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_COPY_ID_g());
assertTrue("H5Pcreate ocpypl failed", isValidId(ocpypl));
// Set copy object flags (shallow hierarchy copy, copy without attributes)
int copyFlags = hdf5_h.H5O_COPY_SHALLOW_HIERARCHY_FLAG() | hdf5_h.H5O_COPY_WITHOUT_ATTR_FLAG();
int result = hdf5_h.H5Pset_copy_object(ocpypl, copyFlags);
assertTrue("H5Pset_copy_object failed", isSuccess(result));
// Get copy object flags back
MemorySegment outFlags = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_copy_object(ocpypl, outFlags);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
assertEquals("Copy flags should match", copyFlags, getInt(outFlags));
hdf5_h.H5Pclose(ocpypl);
}
}
@Test
public void testH5Pget_filter_by_id()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set chunking (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkSeg = allocateLongArray(arena, 2);
copyToSegment(chunkSeg, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkSeg);
// Add deflate filter with compression level 6
hdf5_h.H5Pset_deflate(dcpl, 6);
// Query the deflate filter by ID
int filterId = hdf5_h.H5Z_FILTER_DEFLATE();
MemorySegment flags = allocateIntArray(arena, 1);
MemorySegment nElements = allocateLongArray(arena, 1);
nElements.set(ValueLayout.JAVA_LONG, 0, 8); // Max 8 cd_values
MemorySegment cdValues = allocateIntArray(arena, 8);
long nameSize = 256;
MemorySegment filterName = arena.allocate(nameSize);
MemorySegment filterConfig = allocateIntArray(arena, 1);
int result = hdf5_h.H5Pget_filter_by_id2(dcpl, filterId, flags, nElements, cdValues, nameSize,
filterName, filterConfig);
assertTrue("H5Pget_filter_by_id2 failed", isSuccess(result));
// Verify deflate was found
long actualNElements = nElements.get(ValueLayout.JAVA_LONG, 0);
assertTrue("Should have cd_values for deflate", actualNElements > 0);
// First cd_value should be compression level (6)
int compressionLevel = cdValues.get(ValueLayout.JAVA_INT, 0);
assertEquals("Compression level should be 6", 6, compressionLevel);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_chunk_cache()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_ACCESS_ID_g());
assertTrue("H5Pcreate dapl failed", isValidId(dapl));
// Set chunk cache parameters
long rdccNslots = 521; // Number of chunk slots in cache
long rdccNbytes = 1048576; // Size of chunk cache in bytes (1 MB)
double rdccW0 = 0.75; // Preemption policy
int result = hdf5_h.H5Pset_chunk_cache(dapl, rdccNslots, rdccNbytes, rdccW0);
assertTrue("H5Pset_chunk_cache failed", isSuccess(result));
// Get chunk cache parameters back
MemorySegment outNslots = allocateLongArray(arena, 1);
MemorySegment outNbytes = allocateLongArray(arena, 1);
MemorySegment outW0 = allocateDoubleArray(arena, 1);
result = hdf5_h.H5Pget_chunk_cache(dapl, outNslots, outNbytes, outW0);
assertTrue("H5Pget_chunk_cache failed", isSuccess(result));
assertEquals("Nslots should match", rdccNslots, getLong(outNslots));
assertEquals("Nbytes should match", rdccNbytes, getLong(outNbytes));
assertEquals("W0 should match", rdccW0, getDouble(outW0), 0.001);
hdf5_h.H5Pclose(dapl);
}
}
@Test
public void testH5Pmodify_filter()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Set chunking (required for filters)
long[] chunkDims = {10, 20};
MemorySegment chunkSeg = allocateLongArray(arena, 2);
copyToSegment(chunkSeg, chunkDims);
hdf5_h.H5Pset_chunk(dcpl, 2, chunkSeg);
// Add deflate filter with compression level 6
hdf5_h.H5Pset_deflate(dcpl, 6);
// Modify deflate filter to use compression level 9
int filterId = hdf5_h.H5Z_FILTER_DEFLATE();
int flags = 0; // Mandatory filter
long nElements = 1; // One cd_value (compression level)
MemorySegment cdValues = allocateIntArray(arena, 1);
cdValues.set(ValueLayout.JAVA_INT, 0, 9); // Level 9
int result = hdf5_h.H5Pmodify_filter(dcpl, filterId, flags, nElements, cdValues);
assertTrue("H5Pmodify_filter failed", isSuccess(result));
// Verify the filter was modified
MemorySegment outFlags = allocateIntArray(arena, 1);
MemorySegment outNElements = allocateLongArray(arena, 1);
outNElements.set(ValueLayout.JAVA_LONG, 0, 8);
MemorySegment outCdValues = allocateIntArray(arena, 8);
MemorySegment outName = arena.allocate(256);
MemorySegment outConfig = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_filter_by_id2(dcpl, filterId, outFlags, outNElements, outCdValues, 256,
outName, outConfig);
assertTrue("H5Pget_filter_by_id2 failed", isSuccess(result));
// Verify compression level is now 9
int compressionLevel = outCdValues.get(ValueLayout.JAVA_INT, 0);
assertEquals("Compression level should be 9 after modify", 9, compressionLevel);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_fapl_core()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set core (memory) VFD with 1MB increment and backing store enabled
long increment = 1024 * 1024; // 1MB increments
boolean backingStore = true; // Enable backing store
int result = hdf5_h.H5Pset_fapl_core(fapl, increment, backingStore);
assertTrue("H5Pset_fapl_core failed", isSuccess(result));
// Get core VFD settings
MemorySegment incrementSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment backingStoreSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
result = hdf5_h.H5Pget_fapl_core(fapl, incrementSeg, backingStoreSeg);
assertTrue("H5Pget_fapl_core failed", isSuccess(result));
long retIncrement = incrementSeg.get(ValueLayout.JAVA_LONG, 0);
assertEquals("Increment should match", increment, retIncrement);
boolean retBackingStore = backingStoreSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
assertEquals("Backing store should match", backingStore, retBackingStore);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_fapl_log()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set log VFD with log file and flags
String logFile = "test_h5pffm.log";
long flags = hdf5_h.H5FD_LOG_LOC_IO() | hdf5_h.H5FD_LOG_ALLOC(); // Log I/O and allocation
long bufSize = 4096; // 4KB buffer
int result = hdf5_h.H5Pset_fapl_log(fapl, stringToSegment(arena, logFile), flags, bufSize);
assertTrue("H5Pset_fapl_log failed", isSuccess(result));
// Note: H5Pget_fapl_log doesn't exist, just verify VFD was set
long driverId = hdf5_h.H5Pget_driver(fapl);
assertTrue("Driver ID should be valid", isValidId(driverId));
hdf5_h.H5Pclose(fapl);
// Clean up log file
_deleteFile(logFile);
}
}
@Test
public void testH5Pset_fapl_sec2()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set sec2 (standard I/O) VFD
int result = hdf5_h.H5Pset_fapl_sec2(fapl);
assertTrue("H5Pset_fapl_sec2 failed", isSuccess(result));
// Verify VFD was set
long driverId = hdf5_h.H5Pget_driver(fapl);
assertTrue("Driver ID should be valid", isValidId(driverId));
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_fapl_family()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Create member FAPL (use default)
long memberFapl = hdf5_h.H5P_DEFAULT();
// Set family VFD with 1MB member size
long memberSize = 1024 * 1024; // 1MB per family member
int result = hdf5_h.H5Pset_fapl_family(fapl, memberSize, memberFapl);
assertTrue("H5Pset_fapl_family failed", isSuccess(result));
// Get family VFD settings
MemorySegment membSizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment membFaplSeg = arena.allocate(ValueLayout.JAVA_LONG);
result = hdf5_h.H5Pget_fapl_family(fapl, membSizeSeg, membFaplSeg);
assertTrue("H5Pget_fapl_family failed", isSuccess(result));
long retMembSize = membSizeSeg.get(ValueLayout.JAVA_LONG, 0);
assertEquals("Member size should match", memberSize, retMembSize);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pget_driver()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Get default driver (should be sec2)
long driverId = hdf5_h.H5Pget_driver(fapl);
assertTrue("Default driver ID should be valid", isValidId(driverId));
// Set core VFD
int result = hdf5_h.H5Pset_fapl_core(fapl, 1024, false);
assertTrue("H5Pset_fapl_core failed", isSuccess(result));
// Get driver again (should be core)
long coreDriverId = hdf5_h.H5Pget_driver(fapl);
assertTrue("Core driver ID should be valid", isValidId(coreDriverId));
// Driver IDs should be different
assertNotEquals("Driver IDs should differ after changing VFD", driverId, coreDriverId);
hdf5_h.H5Pclose(fapl);
}
}
// =========================
// File Image + MDC Configuration Tests (Batch 2)
// =========================
@Test
public void testH5Pset_file_image()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Create a small file image buffer (simulating an in-memory HDF5 file)
long imageSize = 1024; // 1KB
MemorySegment imageBuffer = arena.allocate(imageSize);
// Initialize buffer with some data
for (long i = 0; i < imageSize; i++) {
imageBuffer.set(ValueLayout.JAVA_BYTE, i, (byte)(i % 256));
}
// Set file image
int result = hdf5_h.H5Pset_file_image(fapl, imageBuffer, imageSize);
assertTrue("H5Pset_file_image failed", isSuccess(result));
// Get file image back
MemorySegment outBufferPtr = allocateLongArray(arena, 1);
MemorySegment outSize = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_file_image(fapl, outBufferPtr, outSize);
assertTrue("H5Pget_file_image failed", isSuccess(result));
// Verify size matches
long retrievedSize = getLong(outSize);
assertEquals("File image size should match", imageSize, retrievedSize);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_mdc_log_options()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set MDC (metadata cache) log options
boolean isEnabled = true;
String location = "test_mdc.log";
boolean startOnAccess = true;
int result = hdf5_h.H5Pset_mdc_log_options(fapl, isEnabled, stringToSegment(arena, location),
startOnAccess);
assertTrue("H5Pset_mdc_log_options failed", isSuccess(result));
// Get MDC log options back
MemorySegment outIsEnabled = allocateIntArray(arena, 1);
MemorySegment outLocation = arena.allocate(256);
MemorySegment outLocationSize = allocateLongArray(arena, 1);
MemorySegment outStartOnAccess = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_mdc_log_options(fapl, outIsEnabled, outLocation, outLocationSize,
outStartOnAccess);
assertTrue("H5Pget_mdc_log_options failed", isSuccess(result));
// Verify settings
boolean retrievedEnabled = getInt(outIsEnabled) != 0;
boolean retrievedStartOnAccess = getInt(outStartOnAccess) != 0;
assertEquals("MDC logging should be enabled", isEnabled, retrievedEnabled);
assertEquals("Start on access should match", startOnAccess, retrievedStartOnAccess);
hdf5_h.H5Pclose(fapl);
// Clean up log file if created
_deleteFile(location);
}
}
// =========================
// DXPL Enhancement Tests (Batch 3)
// =========================
@Test
public void testH5Pset_edc_check_disable()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Disable error detection (EDC)
int result = hdf5_h.H5Pset_edc_check(dxpl, hdf5_h.H5Z_DISABLE_EDC());
assertTrue("H5Pset_edc_check failed", isSuccess(result));
// Get EDC check setting back
int edcCheck = hdf5_h.H5Pget_edc_check(dxpl);
assertEquals("EDC should be disabled", hdf5_h.H5Z_DISABLE_EDC(), edcCheck);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_edc_check_enable()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Enable error detection (EDC)
int result = hdf5_h.H5Pset_edc_check(dxpl, hdf5_h.H5Z_ENABLE_EDC());
assertTrue("H5Pset_edc_check failed", isSuccess(result));
// Get EDC check setting back
int edcCheck = hdf5_h.H5Pget_edc_check(dxpl);
assertEquals("EDC should be enabled", hdf5_h.H5Z_ENABLE_EDC(), edcCheck);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_selection_io()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Enable selection I/O
int result = hdf5_h.H5Pset_selection_io(dxpl, hdf5_h.H5D_SELECTION_IO_MODE_ON());
assertTrue("H5Pset_selection_io failed", isSuccess(result));
// Get selection I/O mode back
MemorySegment outMode = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_selection_io(dxpl, outMode);
assertTrue("H5Pget_selection_io failed", isSuccess(result));
int mode = getInt(outMode);
assertEquals("Selection I/O should be enabled", hdf5_h.H5D_SELECTION_IO_MODE_ON(), mode);
hdf5_h.H5Pclose(dxpl);
}
}
@Test
public void testH5Pset_selection_io_off()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dxpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_XFER_ID_g());
assertTrue("H5Pcreate dxpl failed", isValidId(dxpl));
// Disable selection I/O
int result = hdf5_h.H5Pset_selection_io(dxpl, hdf5_h.H5D_SELECTION_IO_MODE_OFF());
assertTrue("H5Pset_selection_io failed", isSuccess(result));
// Get selection I/O mode back
MemorySegment outMode = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_selection_io(dxpl, outMode);
assertTrue("H5Pget_selection_io failed", isSuccess(result));
int mode = getInt(outMode);
assertEquals("Selection I/O should be disabled", hdf5_h.H5D_SELECTION_IO_MODE_OFF(), mode);
hdf5_h.H5Pclose(dxpl);
}
}
// =========================
// Virtual Dataset Property Tests
// =========================
@Test
public void testH5Pset_virtual_basic()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create dataset creation property list
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Create virtual dataspace (10x20)
long[] vdimsArray = {10, 20};
MemorySegment vdims = allocateLongArray(arena, 2);
copyToSegment(vdims, vdimsArray);
long vspace = hdf5_h.H5Screate_simple(2, vdims, MemorySegment.NULL);
assertTrue("H5Screate_simple vspace failed", isValidId(vspace));
// Create source dataspace (10x20)
long[] sdimsArray = {10, 20};
MemorySegment sdims = allocateLongArray(arena, 2);
copyToSegment(sdims, sdimsArray);
long srcspace = hdf5_h.H5Screate_simple(2, sdims, MemorySegment.NULL);
assertTrue("H5Screate_simple srcspace failed", isValidId(srcspace));
// Set virtual mapping
MemorySegment srcFile = stringToSegment(arena, "source.h5");
MemorySegment srcDset = stringToSegment(arena, "/source_dataset");
int result = hdf5_h.H5Pset_virtual(dcpl, vspace, srcFile, srcDset, srcspace);
assertTrue("H5Pset_virtual failed", isSuccess(result));
// Get virtual count
MemorySegment count = allocateLongArray(arena, 1);
result = hdf5_h.H5Pget_virtual_count(dcpl, count);
assertTrue("H5Pget_virtual_count failed", isSuccess(result));
assertEquals("Should have 1 virtual mapping", 1L, getLong(count));
// Cleanup
hdf5_h.H5Sclose(srcspace);
hdf5_h.H5Sclose(vspace);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_virtual_filename()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Create dataspaces
long[] dimsArray = {100};
MemorySegment dims = allocateLongArray(arena, 1);
copyToSegment(dims, dimsArray);
long vspace = hdf5_h.H5Screate_simple(1, dims, MemorySegment.NULL);
long srcspace = hdf5_h.H5Screate_simple(1, dims, MemorySegment.NULL);
// Set virtual mapping with specific filename
String expectedFilename = "virtual_source_file.h5";
MemorySegment srcFile = stringToSegment(arena, expectedFilename);
MemorySegment srcDset = stringToSegment(arena, "/data");
hdf5_h.H5Pset_virtual(dcpl, vspace, srcFile, srcDset, srcspace);
// Query filename length
long nameLen = hdf5_h.H5Pget_virtual_filename(dcpl, 0, MemorySegment.NULL, 0);
assertTrue("H5Pget_virtual_filename length query failed", nameLen > 0);
// Get filename
MemorySegment nameBuf = arena.allocate(nameLen + 1);
long actualLen = hdf5_h.H5Pget_virtual_filename(dcpl, 0, nameBuf, nameLen + 1);
assertEquals("Filename length should match", nameLen, actualLen);
String actualFilename = segmentToString(nameBuf);
assertEquals("Filename should match", expectedFilename, actualFilename);
// Cleanup
hdf5_h.H5Sclose(srcspace);
hdf5_h.H5Sclose(vspace);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_virtual_dsetname()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Create dataspaces
long[] dimsArray = {50, 100};
MemorySegment dims = allocateLongArray(arena, 2);
copyToSegment(dims, dimsArray);
long vspace = hdf5_h.H5Screate_simple(2, dims, MemorySegment.NULL);
long srcspace = hdf5_h.H5Screate_simple(2, dims, MemorySegment.NULL);
// Set virtual mapping with specific dataset name
String expectedDsetName = "/group/virtual_dataset";
MemorySegment srcFile = stringToSegment(arena, "source.h5");
MemorySegment srcDset = stringToSegment(arena, expectedDsetName);
hdf5_h.H5Pset_virtual(dcpl, vspace, srcFile, srcDset, srcspace);
// Query dataset name length
long nameLen = hdf5_h.H5Pget_virtual_dsetname(dcpl, 0, MemorySegment.NULL, 0);
assertTrue("H5Pget_virtual_dsetname length query failed", nameLen > 0);
// Get dataset name
MemorySegment nameBuf = arena.allocate(nameLen + 1);
long actualLen = hdf5_h.H5Pget_virtual_dsetname(dcpl, 0, nameBuf, nameLen + 1);
assertEquals("Dataset name length should match", nameLen, actualLen);
String actualDsetName = segmentToString(nameBuf);
assertEquals("Dataset name should match", expectedDsetName, actualDsetName);
// Cleanup
hdf5_h.H5Sclose(srcspace);
hdf5_h.H5Sclose(vspace);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_virtual_vspace_and_srcspace()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Create virtual dataspace with specific dimensions
long[] vdimsArray = {30, 40};
MemorySegment vdims = allocateLongArray(arena, 2);
copyToSegment(vdims, vdimsArray);
long vspace = hdf5_h.H5Screate_simple(2, vdims, MemorySegment.NULL);
// Create source dataspace with different dimensions
long[] sdimsArray = {30, 40};
MemorySegment sdims = allocateLongArray(arena, 2);
copyToSegment(sdims, sdimsArray);
long srcspace = hdf5_h.H5Screate_simple(2, sdims, MemorySegment.NULL);
// Set virtual mapping
hdf5_h.H5Pset_virtual(dcpl, vspace, stringToSegment(arena, "src.h5"),
stringToSegment(arena, "/dset"), srcspace);
// Get virtual dataspace back
long retrieved_vspace = hdf5_h.H5Pget_virtual_vspace(dcpl, 0);
assertTrue("H5Pget_virtual_vspace failed", isValidId(retrieved_vspace));
// Verify virtual dataspace dimensions
MemorySegment retrieved_vdims = allocateLongArray(arena, 2);
hdf5_h.H5Sget_simple_extent_dims(retrieved_vspace, retrieved_vdims, MemorySegment.NULL);
assertEquals("Virtual dim 0 should match", 30L, retrieved_vdims.get(ValueLayout.JAVA_LONG, 0));
assertEquals("Virtual dim 1 should match", 40L, retrieved_vdims.get(ValueLayout.JAVA_LONG, 8));
// Get source dataspace back
long retrieved_srcspace = hdf5_h.H5Pget_virtual_srcspace(dcpl, 0);
assertTrue("H5Pget_virtual_srcspace failed", isValidId(retrieved_srcspace));
// Verify source dataspace dimensions
MemorySegment retrieved_sdims = allocateLongArray(arena, 2);
hdf5_h.H5Sget_simple_extent_dims(retrieved_srcspace, retrieved_sdims, MemorySegment.NULL);
assertEquals("Source dim 0 should match", 30L, retrieved_sdims.get(ValueLayout.JAVA_LONG, 0));
assertEquals("Source dim 1 should match", 40L, retrieved_sdims.get(ValueLayout.JAVA_LONG, 8));
// Cleanup
hdf5_h.H5Sclose(retrieved_srcspace);
hdf5_h.H5Sclose(retrieved_vspace);
hdf5_h.H5Sclose(srcspace);
hdf5_h.H5Sclose(vspace);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_virtual_view()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create dataset access property list
long dapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_ACCESS_ID_g());
assertTrue("H5Pcreate dapl failed", isValidId(dapl));
// Set virtual view to FIRST_MISSING
int result = hdf5_h.H5Pset_virtual_view(dapl, hdf5_h.H5D_VDS_FIRST_MISSING());
assertTrue("H5Pset_virtual_view failed", isSuccess(result));
// Get virtual view back
MemorySegment view = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_virtual_view(dapl, view);
assertTrue("H5Pget_virtual_view failed", isSuccess(result));
assertEquals("View should be FIRST_MISSING", hdf5_h.H5D_VDS_FIRST_MISSING(), getInt(view));
// Change to LAST_AVAILABLE
result = hdf5_h.H5Pset_virtual_view(dapl, hdf5_h.H5D_VDS_LAST_AVAILABLE());
assertTrue("H5Pset_virtual_view (LAST_AVAILABLE) failed", isSuccess(result));
result = hdf5_h.H5Pget_virtual_view(dapl, view);
assertTrue("H5Pget_virtual_view (2nd call) failed", isSuccess(result));
assertEquals("View should be LAST_AVAILABLE", hdf5_h.H5D_VDS_LAST_AVAILABLE(), getInt(view));
hdf5_h.H5Pclose(dapl);
}
}
@Test
public void testH5Pset_copy_object_basic()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create object copy property list
long ocpypl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_COPY_ID_g());
assertTrue("H5Pcreate ocpypl failed", isValidId(ocpypl));
// Set copy options - shallow hierarchy
int copyOptions = hdf5_h.H5O_COPY_SHALLOW_HIERARCHY_FLAG();
int result = hdf5_h.H5Pset_copy_object(ocpypl, copyOptions);
assertTrue("H5Pset_copy_object failed", isSuccess(result));
// Get copy options back
MemorySegment options = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_copy_object(ocpypl, options);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
int retrievedOptions = getInt(options);
assertEquals("Copy options should match", copyOptions, retrievedOptions);
// Cleanup
hdf5_h.H5Pclose(ocpypl);
}
}
@Test
public void testH5Pset_copy_object_multiple_flags()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpypl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_COPY_ID_g());
assertTrue("H5Pcreate ocpypl failed", isValidId(ocpypl));
// Set multiple copy options with bitwise OR
int copyOptions = hdf5_h.H5O_COPY_SHALLOW_HIERARCHY_FLAG() | hdf5_h.H5O_COPY_WITHOUT_ATTR_FLAG();
int result = hdf5_h.H5Pset_copy_object(ocpypl, copyOptions);
assertTrue("H5Pset_copy_object failed", isSuccess(result));
// Verify
MemorySegment options = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_copy_object(ocpypl, options);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
int retrievedOptions = getInt(options);
assertEquals("Copy options should match", copyOptions, retrievedOptions);
// Verify individual flags are set
assertTrue("Should have SHALLOW_HIERARCHY flag",
(retrievedOptions & hdf5_h.H5O_COPY_SHALLOW_HIERARCHY_FLAG()) != 0);
assertTrue("Should have WITHOUT_ATTR flag",
(retrievedOptions & hdf5_h.H5O_COPY_WITHOUT_ATTR_FLAG()) != 0);
hdf5_h.H5Pclose(ocpypl);
}
}
@Test
public void testH5Pset_copy_object_expand_links()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpypl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_COPY_ID_g());
assertTrue("H5Pcreate ocpypl failed", isValidId(ocpypl));
// Set options to expand soft and external links
int copyOptions =
hdf5_h.H5O_COPY_EXPAND_SOFT_LINK_FLAG() | hdf5_h.H5O_COPY_EXPAND_EXT_LINK_FLAG();
int result = hdf5_h.H5Pset_copy_object(ocpypl, copyOptions);
assertTrue("H5Pset_copy_object failed", isSuccess(result));
// Verify
MemorySegment options = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_copy_object(ocpypl, options);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
int retrievedOptions = getInt(options);
assertTrue("Should have EXPAND_SOFT_LINK flag",
(retrievedOptions & hdf5_h.H5O_COPY_EXPAND_SOFT_LINK_FLAG()) != 0);
assertTrue("Should have EXPAND_EXT_LINK flag",
(retrievedOptions & hdf5_h.H5O_COPY_EXPAND_EXT_LINK_FLAG()) != 0);
hdf5_h.H5Pclose(ocpypl);
}
}
@Test
public void testH5Pset_attr_phase_change()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create object creation property list
long ocpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_CREATE_ID_g());
assertTrue("H5Pcreate ocpl failed", isValidId(ocpl));
// Set attribute phase change thresholds
// max_compact: maximum number of attributes in compact storage
// min_dense: minimum number of attributes in dense storage
int maxCompact = 10;
int minDense = 8;
int result = hdf5_h.H5Pset_attr_phase_change(ocpl, maxCompact, minDense);
assertTrue("H5Pset_attr_phase_change failed", isSuccess(result));
// Get settings back
MemorySegment maxCompactOut = allocateIntArray(arena, 1);
MemorySegment minDenseOut = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_attr_phase_change(ocpl, maxCompactOut, minDenseOut);
assertTrue("H5Pget_attr_phase_change failed", isSuccess(result));
int retrievedMaxCompact = getInt(maxCompactOut);
int retrievedMinDense = getInt(minDenseOut);
assertEquals("Max compact should match", maxCompact, retrievedMaxCompact);
assertEquals("Min dense should match", minDense, retrievedMinDense);
hdf5_h.H5Pclose(ocpl);
}
}
@Test
public void testH5Pset_copy_object_preserve_null()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpypl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_COPY_ID_g());
assertTrue("H5Pcreate ocpypl failed", isValidId(ocpypl));
// Test PRESERVE_NULL flag
int copyOptions = hdf5_h.H5O_COPY_PRESERVE_NULL_FLAG();
int result = hdf5_h.H5Pset_copy_object(ocpypl, copyOptions);
assertTrue("H5Pset_copy_object failed", isSuccess(result));
// Verify
MemorySegment options = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_copy_object(ocpypl, options);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
int retrievedOptions = getInt(options);
assertEquals("Should have PRESERVE_NULL flag", copyOptions, retrievedOptions);
// Test with ALL flags
result = hdf5_h.H5Pset_copy_object(ocpypl, hdf5_h.H5O_COPY_ALL());
assertTrue("H5Pset_copy_object (ALL) failed", isSuccess(result));
result = hdf5_h.H5Pget_copy_object(ocpypl, options);
assertTrue("H5Pget_copy_object failed", isSuccess(result));
retrievedOptions = getInt(options);
assertEquals("Should have ALL flags", hdf5_h.H5O_COPY_ALL(), retrievedOptions);
hdf5_h.H5Pclose(ocpypl);
}
}
@Test
public void testH5Pset_elink_prefix()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create link access property list
long lapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_LINK_ACCESS_ID_g());
assertTrue("H5Pcreate lapl failed", isValidId(lapl));
// Set external link prefix
String prefix = "/path/to/external/files";
MemorySegment prefixSeg = stringToSegment(arena, prefix);
int result = hdf5_h.H5Pset_elink_prefix(lapl, prefixSeg);
assertTrue("H5Pset_elink_prefix failed", isSuccess(result));
// Query prefix length
long prefixLen = hdf5_h.H5Pget_elink_prefix(lapl, MemorySegment.NULL, 0);
assertTrue("Prefix length should be > 0", prefixLen > 0);
// Get prefix
MemorySegment prefixBuf = arena.allocate(prefixLen + 1);
long actualLen = hdf5_h.H5Pget_elink_prefix(lapl, prefixBuf, prefixLen + 1);
assertEquals("Prefix length should match", prefixLen, actualLen);
String retrievedPrefix = segmentToString(prefixBuf);
assertEquals("Prefix should match", prefix, retrievedPrefix);
hdf5_h.H5Pclose(lapl);
}
}
@Test
public void testH5Pset_elink_fapl()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create link access property list
long lapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_LINK_ACCESS_ID_g());
assertTrue("H5Pcreate lapl failed", isValidId(lapl));
// Create file access property list to use for external links
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set external link file access property list
int result = hdf5_h.H5Pset_elink_fapl(lapl, fapl);
assertTrue("H5Pset_elink_fapl failed", isSuccess(result));
// Get external link fapl
long retrievedFapl = hdf5_h.H5Pget_elink_fapl(lapl);
assertTrue("Retrieved fapl should be valid", isValidId(retrievedFapl));
// Cleanup
hdf5_h.H5Pclose(retrievedFapl);
hdf5_h.H5Pclose(fapl);
hdf5_h.H5Pclose(lapl);
}
}
@Test
public void testH5Pset_link_creation_order()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group creation property list
long gcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_GROUP_CREATE_ID_g());
assertTrue("H5Pcreate gcpl failed", isValidId(gcpl));
// Set link creation order tracking and indexing
int crtOrderFlags = hdf5_h.H5P_CRT_ORDER_TRACKED() | hdf5_h.H5P_CRT_ORDER_INDEXED();
int result = hdf5_h.H5Pset_link_creation_order(gcpl, crtOrderFlags);
assertTrue("H5Pset_link_creation_order failed", isSuccess(result));
// Get link creation order flags
MemorySegment flags = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_link_creation_order(gcpl, flags);
assertTrue("H5Pget_link_creation_order failed", isSuccess(result));
int retrievedFlags = getInt(flags);
assertEquals("Flags should match", crtOrderFlags, retrievedFlags);
// Verify individual flags
assertTrue("Should have TRACKED flag", (retrievedFlags & hdf5_h.H5P_CRT_ORDER_TRACKED()) != 0);
assertTrue("Should have INDEXED flag", (retrievedFlags & hdf5_h.H5P_CRT_ORDER_INDEXED()) != 0);
hdf5_h.H5Pclose(gcpl);
}
}
@Test
public void testH5Pset_est_link_info()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group creation property list
long gcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_GROUP_CREATE_ID_g());
assertTrue("H5Pcreate gcpl failed", isValidId(gcpl));
// Set estimated link info (number of links, length of link names)
int estNumEntries = 50;
int estNameLen = 20;
int result = hdf5_h.H5Pset_est_link_info(gcpl, estNumEntries, estNameLen);
assertTrue("H5Pset_est_link_info failed", isSuccess(result));
// Get estimated link info
MemorySegment numEntries = allocateIntArray(arena, 1);
MemorySegment nameLen = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_est_link_info(gcpl, numEntries, nameLen);
assertTrue("H5Pget_est_link_info failed", isSuccess(result));
assertEquals("Number of entries should match", estNumEntries, getInt(numEntries));
assertEquals("Name length should match", estNameLen, getInt(nameLen));
hdf5_h.H5Pclose(gcpl);
}
}
@Test
public void testH5Pset_link_phase_change()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create group creation property list
long gcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_GROUP_CREATE_ID_g());
assertTrue("H5Pcreate gcpl failed", isValidId(gcpl));
// Set link phase change thresholds
// max_compact: maximum number of links in compact storage
// min_dense: minimum number of links in dense storage
int maxCompact = 12;
int minDense = 10;
int result = hdf5_h.H5Pset_link_phase_change(gcpl, maxCompact, minDense);
assertTrue("H5Pset_link_phase_change failed", isSuccess(result));
// Get link phase change thresholds
MemorySegment maxCompactOut = allocateIntArray(arena, 1);
MemorySegment minDenseOut = allocateIntArray(arena, 1);
result = hdf5_h.H5Pget_link_phase_change(gcpl, maxCompactOut, minDenseOut);
assertTrue("H5Pget_link_phase_change failed", isSuccess(result));
assertEquals("Max compact should match", maxCompact, getInt(maxCompactOut));
assertEquals("Min dense should match", minDense, getInt(minDenseOut));
hdf5_h.H5Pclose(gcpl);
}
}
@Test
public void testH5Pset_evict_on_close()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set evict on close to true
int result = hdf5_h.H5Pset_evict_on_close(fapl, true);
assertTrue("H5Pset_evict_on_close failed", isSuccess(result));
// Get evict on close setting
MemorySegment evictSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
result = hdf5_h.H5Pget_evict_on_close(fapl, evictSeg);
assertTrue("H5Pget_evict_on_close failed", isSuccess(result));
boolean evict = evictSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
assertTrue("Evict on close should be true", evict);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_file_locking()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set file locking (use_file_locking=true, ignore_when_disabled=false)
int result = hdf5_h.H5Pset_file_locking(fapl, true, false);
assertTrue("H5Pset_file_locking failed", isSuccess(result));
// Get file locking settings
MemorySegment useLockingSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
MemorySegment ignoreFailSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
result = hdf5_h.H5Pget_file_locking(fapl, useLockingSeg, ignoreFailSeg);
assertTrue("H5Pget_file_locking failed", isSuccess(result));
boolean useLocking = useLockingSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
boolean ignoreFail = ignoreFailSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
assertTrue("Use locking should be true", useLocking);
assertFalse("Ignore fail should be false", ignoreFail);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_page_buffer_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set page buffer size (4MB buffer, 50% metadata, 25% raw data)
long bufSize = 4 * 1024 * 1024; // 4MB
int minMetaPct = 50;
int minRawPct = 25;
int result = hdf5_h.H5Pset_page_buffer_size(fapl, bufSize, minMetaPct, minRawPct);
assertTrue("H5Pset_page_buffer_size failed", isSuccess(result));
// Get page buffer size
MemorySegment bufSizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment minMetaPctSeg = arena.allocate(ValueLayout.JAVA_INT);
MemorySegment minRawPctSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_page_buffer_size(fapl, bufSizeSeg, minMetaPctSeg, minRawPctSeg);
assertTrue("H5Pget_page_buffer_size failed", isSuccess(result));
long retBufSize = bufSizeSeg.get(ValueLayout.JAVA_LONG, 0);
int retMetaPct = minMetaPctSeg.get(ValueLayout.JAVA_INT, 0);
int retRawPct = minRawPctSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Buffer size should match", bufSize, retBufSize);
assertEquals("Metadata percent should match", minMetaPct, retMetaPct);
assertEquals("Raw data percent should match", minRawPct, retRawPct);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_metadata_read_attempts()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long fapl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_FILE_ACCESS_ID_g());
assertTrue("H5Pcreate fapl failed", isValidId(fapl));
// Set metadata read attempts to 5
int attempts = 5;
int result = hdf5_h.H5Pset_metadata_read_attempts(fapl, attempts);
assertTrue("H5Pset_metadata_read_attempts failed", isSuccess(result));
// Get metadata read attempts
MemorySegment attemptsSeg = arena.allocate(ValueLayout.JAVA_INT);
result = hdf5_h.H5Pget_metadata_read_attempts(fapl, attemptsSeg);
assertTrue("H5Pget_metadata_read_attempts failed", isSuccess(result));
int retAttempts = attemptsSeg.get(ValueLayout.JAVA_INT, 0);
assertEquals("Attempts should match", attempts, retAttempts);
hdf5_h.H5Pclose(fapl);
}
}
@Test
public void testH5Pset_obj_track_times()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long ocpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_OBJECT_CREATE_ID_g());
assertTrue("H5Pcreate ocpl failed", isValidId(ocpl));
// Set object time tracking to false
int result = hdf5_h.H5Pset_obj_track_times(ocpl, false);
assertTrue("H5Pset_obj_track_times failed", isSuccess(result));
// Get object time tracking setting
MemorySegment trackSeg = arena.allocate(ValueLayout.JAVA_BOOLEAN);
result = hdf5_h.H5Pget_obj_track_times(ocpl, trackSeg);
assertTrue("H5Pget_obj_track_times failed", isSuccess(result));
boolean track = trackSeg.get(ValueLayout.JAVA_BOOLEAN, 0);
assertFalse("Track times should be false", track);
hdf5_h.H5Pclose(ocpl);
}
}
@Test
public void testH5Pget_virtual_info()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create DCPL with virtual dataset mapping
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
long[] dims = {5, 10};
MemorySegment dimsSeg = arena.allocateFrom(ValueLayout.JAVA_LONG, dims);
long vspace = hdf5_h.H5Screate_simple(2, dimsSeg, MemorySegment.NULL);
long srcspace = hdf5_h.H5Screate_simple(2, dimsSeg, MemorySegment.NULL);
MemorySegment srcFileName = stringToSegment(arena, "test_source.h5");
MemorySegment srcDsetName = stringToSegment(arena, "/data");
hdf5_h.H5Pset_virtual(dcpl, vspace, srcFileName, srcDsetName, srcspace);
// Get virtual dataset info
MemorySegment count = allocateLongArray(arena, 1);
int result = hdf5_h.H5Pget_virtual_count(dcpl, count);
assertTrue("H5Pget_virtual_count failed", isSuccess(result));
long vcount = count.get(ValueLayout.JAVA_LONG, 0);
assertEquals("Should have 1 virtual mapping", 1, vcount);
// Get virtual vspace for index 0
long retrieved_vspace = hdf5_h.H5Pget_virtual_vspace(dcpl, 0);
assertTrue("H5Pget_virtual_vspace should succeed", isValidId(retrieved_vspace));
// Get virtual source space for index 0
long retrieved_srcspace = hdf5_h.H5Pget_virtual_srcspace(dcpl, 0);
assertTrue("H5Pget_virtual_srcspace should succeed", isValidId(retrieved_srcspace));
// Cleanup
hdf5_h.H5Sclose(retrieved_vspace);
hdf5_h.H5Sclose(retrieved_srcspace);
hdf5_h.H5Sclose(vspace);
hdf5_h.H5Sclose(srcspace);
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_external()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create DCPL for external storage
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Add external file
MemorySegment extFile = stringToSegment(arena, "external_data.bin");
long offset = 0;
long size = 1024; // 1KB
int result = hdf5_h.H5Pset_external(dcpl, extFile, offset, size);
assertTrue("H5Pset_external failed", isSuccess(result));
// Get external file count
int extCount = hdf5_h.H5Pget_external_count(dcpl);
assertEquals("Should have 1 external file", 1, extCount);
// Cleanup
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pget_external()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create DCPL and add external file
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
String extFileName = "my_external.bin";
MemorySegment extFile = stringToSegment(arena, extFileName);
long offset = 1024;
long size = 4096;
hdf5_h.H5Pset_external(dcpl, extFile, offset, size);
// Get external file info
int nameSize = 256;
MemorySegment nameBuf = arena.allocate(nameSize);
MemorySegment offsetSeg = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment sizeSeg = arena.allocate(ValueLayout.JAVA_LONG);
long retval = hdf5_h.H5Pget_external(dcpl, 0, nameSize, nameBuf, offsetSeg, sizeSeg);
assertTrue("H5Pget_external should succeed", retval >= 0);
// Verify retrieved values
String retrievedName = segmentToString(nameBuf);
assertEquals("File name should match", extFileName, retrievedName);
long retrievedOffset = offsetSeg.get(ValueLayout.JAVA_LONG, 0);
assertEquals("Offset should match", offset, retrievedOffset);
long retrievedSize = sizeSeg.get(ValueLayout.JAVA_LONG, 0);
assertEquals("Size should match", size, retrievedSize);
// Cleanup
hdf5_h.H5Pclose(dcpl);
}
}
@Test
public void testH5Pset_external_multiple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create DCPL
long dcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATASET_CREATE_ID_g());
assertTrue("H5Pcreate dcpl failed", isValidId(dcpl));
// Add multiple external files
hdf5_h.H5Pset_external(dcpl, stringToSegment(arena, "ext1.bin"), 0, 1024);
hdf5_h.H5Pset_external(dcpl, stringToSegment(arena, "ext2.bin"), 0, 2048);
hdf5_h.H5Pset_external(dcpl, stringToSegment(arena, "ext3.bin"), 0, 4096);
// Verify count
int extCount = hdf5_h.H5Pget_external_count(dcpl);
assertEquals("Should have 3 external files", 3, extCount);
// Cleanup
hdf5_h.H5Pclose(dcpl);
}
}
}
+562
View File
@@ -0,0 +1,562 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Reference (H5R) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Rffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5Rffm.h5";
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
long H5fid = hdf5_h.H5I_INVALID_HID();
long H5dsid = hdf5_h.H5I_INVALID_HID();
long H5did = hdf5_h.H5I_INVALID_HID();
long H5gid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create file
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
// Create dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, 2);
copyToSegment(dimsSegment, dims);
H5dsid = hdf5_h.H5Screate_simple(2, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5dsid));
// Create group
MemorySegment groupname = stringToSegment(arena, "Group1");
H5gid = hdf5_h.H5Gcreate2(H5fid, groupname, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Gcreate2 failed", isValidId(H5gid));
// Create dataset
MemorySegment dsetname = stringToSegment(arena, "dset");
H5did = hdf5_h.H5Dcreate2(H5fid, dsetname, hdf5_h.H5T_STD_I32BE_g(), H5dsid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(H5did));
// Write some data
int[][] data = new int[DIM_X][DIM_Y];
for (int i = 0; i < DIM_X; i++)
for (int j = 0; j < DIM_Y; j++)
data[i][j] = i * DIM_Y + j;
MemorySegment dataBuffer = allocateIntArray(arena, DIM_X * DIM_Y);
for (int i = 0; i < DIM_X; i++)
for (int j = 0; j < DIM_Y; j++)
dataBuffer.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, i * DIM_Y + j, data[i][j]);
int result = hdf5_h.H5Dwrite(H5did, hdf5_h.H5T_NATIVE_INT_g(), hdf5_h.H5S_ALL(), hdf5_h.H5S_ALL(),
hdf5_h.H5P_DEFAULT(), dataBuffer);
assertTrue("H5Dwrite failed", isSuccess(result));
// Flush file
result = hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
assertTrue("H5Fflush failed", isSuccess(result));
}
}
@After
public void deleteH5file()
{
if (isValidId(H5did)) {
closeQuietly(H5did, hdf5_h::H5Dclose);
H5did = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5gid)) {
closeQuietly(H5gid, hdf5_h::H5Gclose);
H5gid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5dsid)) {
closeQuietly(H5dsid, hdf5_h::H5Sclose);
H5dsid = hdf5_h.H5I_INVALID_HID();
}
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
// ============================================================================
// Phase 1: Object Reference Operations
// ============================================================================
@Test
public void testH5Rcreate_destroy_object()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate reference buffer
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
// Create object reference to dataset
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Get reference type
int ref_type = hdf5_h.H5Rget_type(ref_ptr);
assertEquals("Reference type should be OBJECT", hdf5_h.H5R_OBJECT2(), ref_type);
// Destroy reference
result = hdf5_h.H5Rdestroy(ref_ptr);
assertTrue("H5Rdestroy failed", isSuccess(result));
}
}
@Test
public void testH5Ropen_object()
{
try (Arena arena = Arena.ofConfined()) {
// Create object reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Open object via reference
long opened_did = hdf5_h.H5Ropen_object(ref_ptr, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Ropen_object failed", isValidId(opened_did));
// Verify it's a dataset
int obj_type = hdf5_h.H5Iget_type(opened_did);
assertEquals("Should be dataset type", hdf5_h.H5I_DATASET(), obj_type);
// Close opened object
hdf5_h.H5Dclose(opened_did);
// Destroy reference
hdf5_h.H5Rdestroy(ref_ptr);
}
}
// ============================================================================
// Phase 2: Region Reference Operations
// ============================================================================
@Test
public void testH5Rcreate_region()
{
try (Arena arena = Arena.ofConfined()) {
// Create a region selection (hyperslab)
long region_sid = hdf5_h.H5Scopy(H5dsid);
assertTrue("H5Scopy failed", isValidId(region_sid));
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment starts = allocateLongArray(arena, 2);
MemorySegment counts = allocateLongArray(arena, 2);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(region_sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Create region reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
result = hdf5_h.H5Rcreate_region(H5fid, dsetname, region_sid, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_region failed", isSuccess(result));
// Verify reference type
int ref_type = hdf5_h.H5Rget_type(ref_ptr);
assertEquals("Reference type should be DATASET_REGION", hdf5_h.H5R_DATASET_REGION2(), ref_type);
// Clean up
hdf5_h.H5Rdestroy(ref_ptr);
hdf5_h.H5Sclose(region_sid);
}
}
@Test
public void testH5Ropen_region()
{
try (Arena arena = Arena.ofConfined()) {
// Create region selection
long region_sid = hdf5_h.H5Scopy(H5dsid);
assertTrue("H5Scopy failed", isValidId(region_sid));
long[] start = {0, 0};
long[] count = {2, 2};
MemorySegment starts = allocateLongArray(arena, 2);
MemorySegment counts = allocateLongArray(arena, 2);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(region_sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Create region reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
result = hdf5_h.H5Rcreate_region(H5fid, dsetname, region_sid, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_region failed", isSuccess(result));
// Open region
long opened_region_sid =
hdf5_h.H5Ropen_region(ref_ptr, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Ropen_region failed", isValidId(opened_region_sid));
// Verify region selection has correct number of points
long npoints = hdf5_h.H5Sget_select_npoints(opened_region_sid);
assertEquals("Region should have 4 points (2x2)", 4L, npoints);
// Clean up
hdf5_h.H5Sclose(opened_region_sid);
hdf5_h.H5Rdestroy(ref_ptr);
hdf5_h.H5Sclose(region_sid);
}
}
// ============================================================================
// Phase 3: Attribute Reference Operations
// ============================================================================
@Test
public void testH5Rcreate_open_attr()
{
try (Arena arena = Arena.ofConfined()) {
// Create attribute on dataset
MemorySegment attrname = stringToSegment(arena, "test_attr");
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
long aid = hdf5_h.H5Acreate2(H5did, attrname, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
// Write attribute value
MemorySegment attrData = allocateInt(arena);
setInt(attrData, 42);
int result = hdf5_h.H5Awrite(aid, hdf5_h.H5T_NATIVE_INT_g(), attrData);
assertTrue("H5Awrite failed", isSuccess(result));
hdf5_h.H5Aclose(aid);
hdf5_h.H5Sclose(attr_sid);
// Flush to ensure attribute is written
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Create attribute reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
result = hdf5_h.H5Rcreate_attr(H5fid, dsetname, attrname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_attr failed", isSuccess(result));
// Verify reference type
int ref_type = hdf5_h.H5Rget_type(ref_ptr);
assertEquals("Reference type should be ATTR", hdf5_h.H5R_ATTR(), ref_type);
// Open attribute via reference
long opened_aid = hdf5_h.H5Ropen_attr(ref_ptr, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Ropen_attr failed", isValidId(opened_aid));
// Read attribute value back
MemorySegment readData = allocateInt(arena);
result = hdf5_h.H5Aread(opened_aid, hdf5_h.H5T_NATIVE_INT_g(), readData);
assertTrue("H5Aread failed", isSuccess(result));
int value = getInt(readData);
assertEquals("Attribute value should be 42", 42, value);
// Clean up
hdf5_h.H5Aclose(opened_aid);
hdf5_h.H5Rdestroy(ref_ptr);
}
}
@Test
public void testH5Rget_attr_name()
{
try (Arena arena = Arena.ofConfined()) {
// Create attribute
MemorySegment attrname = stringToSegment(arena, "my_attribute");
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
long aid = hdf5_h.H5Acreate2(H5did, attrname, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Acreate2 failed", isValidId(aid));
hdf5_h.H5Aclose(aid);
hdf5_h.H5Sclose(attr_sid);
hdf5_h.H5Fflush(H5fid, hdf5_h.H5F_SCOPE_LOCAL());
// Create attribute reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_attr(H5fid, dsetname, attrname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_attr failed", isSuccess(result));
// Get attribute name size
long name_size = hdf5_h.H5Rget_attr_name(ref_ptr, MemorySegment.NULL, 0);
assertTrue("H5Rget_attr_name size query failed", name_size > 0);
// Get attribute name
MemorySegment nameBuffer = arena.allocate(name_size + 1);
long actual_size = hdf5_h.H5Rget_attr_name(ref_ptr, nameBuffer, name_size + 1);
assertTrue("H5Rget_attr_name failed", actual_size > 0);
String retrieved_name = nameBuffer.getString(0);
assertEquals("Attribute name should match", "my_attribute", retrieved_name);
// Clean up
hdf5_h.H5Rdestroy(ref_ptr);
}
}
// ============================================================================
// Phase 4: Reference Utility Operations
// ============================================================================
@Test
public void testH5Rcopy_equal()
{
try (Arena arena = Arena.ofConfined()) {
// Create original reference
MemorySegment ref1 = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref1);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Copy reference
MemorySegment ref2 = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
result = hdf5_h.H5Rcopy(ref1, ref2);
assertTrue("H5Rcopy failed", isSuccess(result));
// Test equality
result = hdf5_h.H5Requal(ref1, ref2);
assertTrue("References should be equal", result > 0);
// Create different reference
MemorySegment ref3 = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment groupname = stringToSegment(arena, "Group1");
result = hdf5_h.H5Rcreate_object(H5fid, groupname, hdf5_h.H5P_DEFAULT(), ref3);
assertTrue("H5Rcreate_object Group1 failed", isSuccess(result));
// Test inequality
result = hdf5_h.H5Requal(ref1, ref3);
assertEquals("References should not be equal", 0, result);
// Clean up
hdf5_h.H5Rdestroy(ref1);
hdf5_h.H5Rdestroy(ref2);
hdf5_h.H5Rdestroy(ref3);
}
}
@Test
public void testH5Rget_file_name()
{
try (Arena arena = Arena.ofConfined()) {
// Create reference
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Get file name size
long name_size = hdf5_h.H5Rget_file_name(ref_ptr, MemorySegment.NULL, 0);
assertTrue("H5Rget_file_name size query failed", name_size > 0);
// Get file name
MemorySegment nameBuffer = arena.allocate(name_size + 1);
long actual_size = hdf5_h.H5Rget_file_name(ref_ptr, nameBuffer, name_size + 1);
assertTrue("H5Rget_file_name failed", actual_size > 0);
String retrieved_name = nameBuffer.getString(0);
assertEquals("File name should match", H5_FILE, retrieved_name);
// Clean up
hdf5_h.H5Rdestroy(ref_ptr);
}
}
@Test
public void testH5R_complete_workflow()
{
try (Arena arena = Arena.ofConfined()) {
// 1. Create object reference
MemorySegment obj_ref = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment dsetname = stringToSegment(arena, "dset");
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), obj_ref);
assertTrue("Create object reference failed", isSuccess(result));
// 2. Verify type
int ref_type = hdf5_h.H5Rget_type(obj_ref);
assertEquals("Type should be OBJECT2", hdf5_h.H5R_OBJECT2(), ref_type);
// 3. Copy reference
MemorySegment obj_ref_copy = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
result = hdf5_h.H5Rcopy(obj_ref, obj_ref_copy);
assertTrue("Copy reference failed", isSuccess(result));
// 4. Verify equality
result = hdf5_h.H5Requal(obj_ref, obj_ref_copy);
assertTrue("References should be equal", result > 0);
// 5. Open via reference
long opened_did = hdf5_h.H5Ropen_object(obj_ref, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("Open object failed", isValidId(opened_did));
// 6. Get name
long name_size = hdf5_h.H5Rget_obj_name(obj_ref, hdf5_h.H5P_DEFAULT(), MemorySegment.NULL, 0);
assertTrue("Get name size failed", name_size > 0);
MemorySegment nameBuffer = arena.allocate(name_size + 1);
hdf5_h.H5Rget_obj_name(obj_ref, hdf5_h.H5P_DEFAULT(), nameBuffer, name_size + 1);
String obj_name = nameBuffer.getString(0);
assertEquals("Object name should be /dset", "/dset", obj_name);
// 7. Clean up
hdf5_h.H5Dclose(opened_did);
hdf5_h.H5Rdestroy(obj_ref);
hdf5_h.H5Rdestroy(obj_ref_copy);
}
}
@Test
public void testH5Rget_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Get reference type
int ref_type = hdf5_h.H5Rget_type(ref_ptr);
assertEquals("Should be object reference", hdf5_h.H5R_OBJECT2(), ref_type);
hdf5_h.H5Rdestroy(ref_ptr);
}
}
@Test
public void testH5Rget_obj_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Get object type
MemorySegment obj_type = allocateIntArray(arena, 1);
result = hdf5_h.H5Rget_obj_type3(ref_ptr, hdf5_h.H5P_DEFAULT(), obj_type);
assertTrue("H5Rget_obj_type3 failed", isSuccess(result));
int type_value = getInt(obj_type);
assertTrue("Object type should be valid", type_value >= 0);
hdf5_h.H5Rdestroy(ref_ptr);
}
}
@Test
public void testH5Rget_obj_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
MemorySegment ref_ptr = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr);
assertTrue("H5Rcreate_object failed", isSuccess(result));
// Get object name size
long name_size = hdf5_h.H5Rget_obj_name(ref_ptr, hdf5_h.H5P_DEFAULT(), MemorySegment.NULL, 0);
assertTrue("H5Rget_obj_name size query failed", name_size > 0);
// Get object name
MemorySegment nameBuffer = arena.allocate(name_size + 1);
long actual_size =
hdf5_h.H5Rget_obj_name(ref_ptr, hdf5_h.H5P_DEFAULT(), nameBuffer, name_size + 1);
assertTrue("H5Rget_obj_name failed", actual_size > 0);
String obj_name = segmentToString(nameBuffer);
assertEquals("Object name should match", "/dset", obj_name);
hdf5_h.H5Rdestroy(ref_ptr);
}
}
@Test
public void testH5Requal()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dsetname = stringToSegment(arena, "/dset");
MemorySegment ref_ptr1 = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
MemorySegment ref_ptr2 = arena.allocate(hdf5_h.H5R_REF_BUF_SIZE());
// Create two identical references
int result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr1);
assertTrue("H5Rcreate_object 1 failed", isSuccess(result));
result = hdf5_h.H5Rcreate_object(H5fid, dsetname, hdf5_h.H5P_DEFAULT(), ref_ptr2);
assertTrue("H5Rcreate_object 2 failed", isSuccess(result));
// Compare references
int equal = hdf5_h.H5Requal(ref_ptr1, ref_ptr2);
assertTrue("References should be equal", equal > 0);
hdf5_h.H5Rdestroy(ref_ptr1);
hdf5_h.H5Rdestroy(ref_ptr2);
}
}
}
+1609
View File
@@ -0,0 +1,1609 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Dataspace (H5S) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*/
public class TestH5Sffm {
@Rule
public TestName testname = new TestName();
private static final int RANK = 2;
private static final int DIM_X = 4;
private static final int DIM_Y = 6;
long H5sid = hdf5_h.H5I_INVALID_HID();
@After
public void cleanup()
{
closeQuietly(H5sid, hdf5_h::H5Sclose);
H5sid = hdf5_h.H5I_INVALID_HID();
System.out.println();
}
@Test
public void testH5Screate_simple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
}
}
@Test
public void testH5Screate_simple_with_maxdims()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
long[] maxdims = {2 * DIM_X, 2 * DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
MemorySegment maxdimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
copyToSegment(maxdimsSegment, maxdims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, maxdimsSegment);
assertTrue("H5Screate_simple with maxdims failed", isValidId(H5sid));
}
}
@Test
public void testH5Screate()
{
System.out.print(testname.getMethodName());
H5sid = hdf5_h.H5Screate(hdf5_h.H5S_SIMPLE());
assertTrue("H5Screate failed", isValidId(H5sid));
}
@Test
public void testH5Screate_scalar()
{
System.out.print(testname.getMethodName());
H5sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
assertTrue("H5Screate scalar failed", isValidId(H5sid));
// Verify it's a scalar
int ndims = hdf5_h.H5Sget_simple_extent_ndims(H5sid);
assertEquals("Scalar should have 0 dimensions", 0, ndims);
}
@Test
public void testH5Scopy()
{
System.out.print(testname.getMethodName());
long sid_copy = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create original dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Copy dataspace
sid_copy = hdf5_h.H5Scopy(H5sid);
assertTrue("H5Scopy failed", isValidId(sid_copy));
// Verify dimensions match
MemorySegment copyDimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(sid_copy, copyDimsSegment, MemorySegment.NULL);
assertEquals("Rank should match", RANK, ndims);
long[] copyDims = new long[RANK];
copyFromSegment(copyDimsSegment, copyDims);
assertArrayEquals("Dimensions should match", dims, copyDims);
}
finally {
closeQuietly(sid_copy, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sget_simple_extent_ndims()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int ndims = hdf5_h.H5Sget_simple_extent_ndims(H5sid);
assertEquals("Rank should match", RANK, ndims);
}
}
@Test
public void testH5Sget_simple_extent_npoints()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
long npoints = hdf5_h.H5Sget_simple_extent_npoints(H5sid);
assertEquals("Number of points should be DIM_X * DIM_Y", DIM_X * DIM_Y, npoints);
}
}
@Test
public void testH5Sget_simple_extent_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int spaceType = hdf5_h.H5Sget_simple_extent_type(H5sid);
assertEquals("Space type should be hdf5_h.H5S_SIMPLE()", hdf5_h.H5S_SIMPLE(), spaceType);
}
}
@Test
public void testH5Sset_extent_simple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5sid = hdf5_h.H5Screate(hdf5_h.H5S_SIMPLE());
assertTrue("H5Screate failed", isValidId(H5sid));
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
int result = hdf5_h.H5Sset_extent_simple(H5sid, RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Sset_extent_simple failed", isSuccess(result));
// Verify dimensions were set
int ndims = hdf5_h.H5Sget_simple_extent_ndims(H5sid);
assertEquals("Rank should match", RANK, ndims);
}
}
@Test
public void testH5Sselect_hyperslab()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select a 2x3 hyperslab starting at (1,1)
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
MemorySegment.NULL, countSegment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Verify selection
long npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Selected points should be 2*3", 6, npoints);
}
}
@Test
public void testH5Sselect_elements()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select 3 specific points
long[] coords = {
0, 0, // Point 1
1, 1, // Point 2
2, 2 // Point 3
};
MemorySegment coordsSegment = allocateLongArray(arena, coords.length);
copyToSegment(coordsSegment, coords);
int result = hdf5_h.H5Sselect_elements(H5sid, hdf5_h.H5S_SELECT_SET(), 3, coordsSegment);
assertTrue("H5Sselect_elements failed", isSuccess(result));
// Verify selection
long npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Selected points should be 3", 3, npoints);
}
}
@Test
public void testH5Sselect_all()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int result = hdf5_h.H5Sselect_all(H5sid);
assertTrue("H5Sselect_all failed", isSuccess(result));
// Verify selection
long npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("All points should be selected", DIM_X * DIM_Y, npoints);
}
}
@Test
public void testH5Sselect_none()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int result = hdf5_h.H5Sselect_none(H5sid);
assertTrue("H5Sselect_none failed", isSuccess(result));
// Verify selection
long npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("No points should be selected", 0, npoints);
}
}
@Test
public void testH5Sget_simple_extent_dims()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] expectedDims = {DIM_X, DIM_Y};
long[] expectedMaxDims = {2 * DIM_X, 2 * DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
MemorySegment maxdimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, expectedDims);
copyToSegment(maxdimsSegment, expectedMaxDims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, maxdimsSegment);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Get dimensions back
MemorySegment returnedDimsSegment = allocateLongArray(arena, RANK);
MemorySegment returnedMaxDimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(H5sid, returnedDimsSegment, returnedMaxDimsSegment);
assertEquals("Rank should match", RANK, ndims);
long[] returnedDims = new long[RANK];
long[] returnedMaxDims = new long[RANK];
copyFromSegment(returnedDimsSegment, returnedDims);
copyFromSegment(returnedMaxDimsSegment, returnedMaxDims);
assertArrayEquals("Dimensions should match", expectedDims, returnedDims);
assertArrayEquals("Max dimensions should match", expectedMaxDims, returnedMaxDims);
}
}
@Test
public void testH5Sget_select_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Default selection type should be H5S_SEL_ALL
int selType = hdf5_h.H5Sget_select_type(H5sid);
assertEquals("Default selection should be ALL", hdf5_h.H5S_SEL_ALL(), selType);
// Select hyperslab
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment, MemorySegment.NULL,
countSegment, MemorySegment.NULL);
selType = hdf5_h.H5Sget_select_type(H5sid);
assertEquals("Selection type should be HYPERSLABS", hdf5_h.H5S_SEL_HYPERSLABS(), selType);
// Select none
hdf5_h.H5Sselect_none(H5sid);
selType = hdf5_h.H5Sget_select_type(H5sid);
assertEquals("Selection type should be NONE", hdf5_h.H5S_SEL_NONE(), selType);
}
}
@Test
public void testH5Sget_select_bounds()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select a hyperslab from (1,2) with count (2,3)
long[] start = {1, 2};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment, MemorySegment.NULL,
countSegment, MemorySegment.NULL);
// Get selection bounds
MemorySegment boundsStartSegment = allocateLongArray(arena, RANK);
MemorySegment boundsEndSegment = allocateLongArray(arena, RANK);
int result = hdf5_h.H5Sget_select_bounds(H5sid, boundsStartSegment, boundsEndSegment);
assertTrue("H5Sget_select_bounds failed", isSuccess(result));
long[] boundsStart = new long[RANK];
long[] boundsEnd = new long[RANK];
copyFromSegment(boundsStartSegment, boundsStart);
copyFromSegment(boundsEndSegment, boundsEnd);
// Bounds should be: start=(1,2), end=(2,4) because end = start + count - 1
long[] expectedStart = {1, 2};
long[] expectedEnd = {2, 4}; // (1+2-1, 2+3-1)
assertArrayEquals("Bounds start should match", expectedStart, boundsStart);
assertArrayEquals("Bounds end should match", expectedEnd, boundsEnd);
}
}
@Test
public void testH5Sextent_copy()
{
System.out.print(testname.getMethodName());
long sid_dest = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create source dataspace with specific dimensions
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create destination dataspace (initially scalar)
sid_dest = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
assertTrue("H5Screate scalar failed", isValidId(sid_dest));
// Copy extent from source to destination
int result = hdf5_h.H5Sextent_copy(sid_dest, H5sid);
assertTrue("H5Sextent_copy failed", isSuccess(result));
// Verify destination now has same dimensions as source
MemorySegment destDimsSegment = allocateLongArray(arena, RANK);
int ndims = hdf5_h.H5Sget_simple_extent_dims(sid_dest, destDimsSegment, MemorySegment.NULL);
assertEquals("Rank should match", RANK, ndims);
long[] destDims = new long[RANK];
copyFromSegment(destDimsSegment, destDims);
assertArrayEquals("Dimensions should match", dims, destDims);
}
finally {
closeQuietly(sid_dest, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sextent_equal()
{
System.out.print(testname.getMethodName());
long sid2 = hdf5_h.H5I_INVALID_HID();
long sid3 = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create first dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create second dataspace with same dimensions
sid2 = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(sid2));
// Create third dataspace with different dimensions
long[] diffDims = {DIM_X + 1, DIM_Y};
MemorySegment diffDimsSegment = allocateLongArray(arena, RANK);
copyToSegment(diffDimsSegment, diffDims);
sid3 = hdf5_h.H5Screate_simple(RANK, diffDimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(sid3));
// Test equality
int result = hdf5_h.H5Sextent_equal(H5sid, sid2);
assertTrue("Extents should be equal", result > 0);
result = hdf5_h.H5Sextent_equal(H5sid, sid3);
assertFalse("Extents should not be equal", result > 0);
}
finally {
closeQuietly(sid2, hdf5_h::H5Sclose);
closeQuietly(sid3, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sget_select_hyper_nblocks()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select first hyperslab
long[] start1 = {0, 0};
long[] count1 = {2, 2};
MemorySegment start1Segment = allocateLongArray(arena, RANK);
MemorySegment count1Segment = allocateLongArray(arena, RANK);
copyToSegment(start1Segment, start1);
copyToSegment(count1Segment, count1);
hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), start1Segment, MemorySegment.NULL,
count1Segment, MemorySegment.NULL);
// Add second hyperslab (OR operation)
long[] start2 = {2, 2};
long[] count2 = {2, 2};
MemorySegment start2Segment = allocateLongArray(arena, RANK);
MemorySegment count2Segment = allocateLongArray(arena, RANK);
copyToSegment(start2Segment, start2);
copyToSegment(count2Segment, count2);
hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_OR(), start2Segment, MemorySegment.NULL,
count2Segment, MemorySegment.NULL);
// Get number of blocks
long nblocks = hdf5_h.H5Sget_select_hyper_nblocks(H5sid);
assertEquals("Should have 2 hyperslab blocks", 2, nblocks);
}
}
@Test
public void testH5Sencode_decode()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create dataspace with hyperslab selection
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select a hyperslab
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment, MemorySegment.NULL,
countSegment, MemorySegment.NULL);
// Get encoded size
MemorySegment nalloc_segment = allocateLong(arena);
int result = hdf5_h.H5Sencode2(H5sid, MemorySegment.NULL, nalloc_segment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Sencode2 (get size) failed", isSuccess(result));
long nalloc = getLong(nalloc_segment);
assertTrue("Encoded size should be > 0", nalloc > 0);
// Encode dataspace
MemorySegment buf = arena.allocate(nalloc);
result = hdf5_h.H5Sencode2(H5sid, buf, nalloc_segment, hdf5_h.H5P_DEFAULT());
assertTrue("H5Sencode2 failed", isSuccess(result));
// Decode dataspace
long decoded_sid = hdf5_h.H5Sdecode(buf);
assertTrue("H5Sdecode failed", isValidId(decoded_sid));
// Verify decoded dataspace has same selection
long npoints_orig = hdf5_h.H5Sget_select_npoints(H5sid);
long npoints_decoded = hdf5_h.H5Sget_select_npoints(decoded_sid);
assertEquals("Selected points should match", npoints_orig, npoints_decoded);
closeQuietly(decoded_sid, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sclose()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int result = hdf5_h.H5Sclose(H5sid);
assertTrue("H5Sclose failed", isSuccess(result));
H5sid = hdf5_h.H5I_INVALID_HID();
}
}
@Test
public void testH5Sget_select_npoints()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select all - should have DIM_X * DIM_Y points
int result = hdf5_h.H5Sselect_all(H5sid);
assertTrue("H5Sselect_all failed", isSuccess(result));
long npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Should have DIM_X * DIM_Y points", DIM_X * DIM_Y, npoints);
// Select hyperslab - 2x3 = 6 points
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
MemorySegment.NULL, countSegment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Should have 6 points in hyperslab", 6L, npoints);
}
}
@Test
public void testH5Sget_select_valid()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select a valid hyperslab
long[] start = {0, 0};
long[] count = {2, 2};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
MemorySegment.NULL, countSegment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Verify selection is valid
int valid = hdf5_h.H5Sselect_valid(H5sid);
assertTrue("Selection should be valid", valid > 0);
}
}
@Test
public void testH5Sget_select_hyper_blocklist()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select a single hyperslab block from [1,1] to [2,3]
long[] start = {1, 1};
long[] stride = {1, 1};
long[] count = {1, 1}; // 1 block
long[] block = {2, 3}; // Block size 2x3
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment strideSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
MemorySegment blockSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(strideSegment, stride);
copyToSegment(countSegment, count);
copyToSegment(blockSegment, block);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
strideSegment, countSegment, blockSegment);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Get number of blocks (should be 1)
long nblocks = hdf5_h.H5Sget_select_hyper_nblocks(H5sid);
assertEquals("Should have 1 block", 1L, nblocks);
// Get blocklist (start and end coordinates)
// Each block has 2 coordinates (start, end) with RANK values each
long blocklistSize = nblocks * RANK * 2;
MemorySegment blocklist = allocateLongArray(arena, (int)blocklistSize);
result = hdf5_h.H5Sget_select_hyper_blocklist(H5sid, 0, nblocks, blocklist);
assertTrue("H5Sget_select_hyper_blocklist failed", isSuccess(result));
// Verify block coordinates
// Start: [1, 1], End: [2, 3] (inclusive, so 2 rows x 3 cols)
assertEquals("Block start[0] should be 1", 1L, blocklist.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Block start[1] should be 1", 1L, blocklist.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Block end[0] should be 2", 2L, blocklist.getAtIndex(ValueLayout.JAVA_LONG, 2));
assertEquals("Block end[1] should be 3", 3L, blocklist.getAtIndex(ValueLayout.JAVA_LONG, 3));
}
}
@Test
public void testH5Sselect_adjust()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select hyperslab from [2,2] with count [2,2]
long[] start = {2, 2};
long[] count = {2, 2};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
MemorySegment.NULL, countSegment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Get original bounds
MemorySegment startBounds1 = allocateLongArray(arena, RANK);
MemorySegment endBounds1 = allocateLongArray(arena, RANK);
result = hdf5_h.H5Sget_select_bounds(H5sid, startBounds1, endBounds1);
assertTrue("H5Sget_select_bounds failed", isSuccess(result));
long[] origStart = new long[RANK];
copyFromSegment(startBounds1, origStart);
// Adjust selection by offset [1, 1] (SUBTRACTS offset from selection coordinates)
long[] offset = {1, 1};
MemorySegment offsetSegment = allocateLongArray(arena, RANK);
copyToSegment(offsetSegment, offset);
result = hdf5_h.H5Sselect_adjust(H5sid, offsetSegment);
assertTrue("H5Sselect_adjust failed", isSuccess(result));
// Get bounds after adjustment
MemorySegment startBounds2 = allocateLongArray(arena, RANK);
MemorySegment endBounds2 = allocateLongArray(arena, RANK);
result = hdf5_h.H5Sget_select_bounds(H5sid, startBounds2, endBounds2);
assertTrue("H5Sget_select_bounds failed", isSuccess(result));
long[] newStart = new long[RANK];
copyFromSegment(startBounds2, newStart);
// Verify offset was applied (should be [1,1] after [1,1] offset subtracted from [2,2])
assertEquals("Adjusted start[0] should be 1", origStart[0] - 1, newStart[0]);
assertEquals("Adjusted start[1] should be 1", origStart[1] - 1, newStart[1]);
}
}
@Test
public void testH5Sget_select_elem_pointlist()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select 3 specific points
long[] coords = {
0, 0, // Point 1: [0,0]
1, 2, // Point 2: [1,2]
3, 5 // Point 3: [3,5]
};
int numPoints = 3;
MemorySegment coordsSegment = allocateLongArray(arena, coords.length);
copyToSegment(coordsSegment, coords);
int result = hdf5_h.H5Sselect_elements(H5sid, hdf5_h.H5S_SELECT_SET(), numPoints, coordsSegment);
assertTrue("H5Sselect_elements failed", isSuccess(result));
// Get number of element points
long npoints = hdf5_h.H5Sget_select_elem_npoints(H5sid);
assertEquals("Should have 3 element points", 3L, npoints);
// Get the point list back
MemorySegment pointlist = allocateLongArray(arena, (int)(npoints * RANK));
result = hdf5_h.H5Sget_select_elem_pointlist(H5sid, 0, npoints, pointlist);
assertTrue("H5Sget_select_elem_pointlist failed", isSuccess(result));
// Verify the coordinates
long[] retrievedCoords = new long[(int)(npoints * RANK)];
copyFromSegment(pointlist, retrievedCoords);
assertArrayEquals("Point coordinates should match", coords, retrievedCoords);
}
}
@Test
public void testH5Sis_simple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Test simple dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
int isSimple = hdf5_h.H5Sis_simple(H5sid);
assertTrue("Dataspace should be simple", isSimple > 0);
hdf5_h.H5Sclose(H5sid);
// Test scalar dataspace (also simple)
H5sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
assertTrue("H5Screate scalar failed", isValidId(H5sid));
isSimple = hdf5_h.H5Sis_simple(H5sid);
assertTrue("Scalar dataspace should be simple", isSimple > 0);
}
}
@Test
public void testH5Sset_extent_none()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a simple dataspace
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Verify it's simple
int type = hdf5_h.H5Sget_simple_extent_type(H5sid);
assertEquals("Should be H5S_SIMPLE", hdf5_h.H5S_SIMPLE(), type);
// Set extent to none (null dataspace)
int result = hdf5_h.H5Sset_extent_none(H5sid);
assertTrue("H5Sset_extent_none failed", isSuccess(result));
// Verify it's now null
type = hdf5_h.H5Sget_simple_extent_type(H5sid);
assertEquals("Should be H5S_NULL", hdf5_h.H5S_NULL(), type);
}
}
@Test
public void testH5Sselect_copy()
{
System.out.print(testname.getMethodName());
long H5sid2 = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create source dataspace with selection
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create destination dataspace
H5sid2 = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple for dest failed", isValidId(H5sid2));
// Select hyperslab in source
long[] start = {1, 1};
long[] count = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(countSegment, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
MemorySegment.NULL, countSegment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Get original selection npoints
long npoints1 = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Should have 6 points", 6L, npoints1);
// Copy selection from source to destination
result = hdf5_h.H5Sselect_copy(H5sid2, H5sid);
assertTrue("H5Sselect_copy failed", isSuccess(result));
// Verify destination has same selection
long npoints2 = hdf5_h.H5Sget_select_npoints(H5sid2);
assertEquals("Destination should have same npoints", npoints1, npoints2);
}
finally {
closeQuietly(H5sid2, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sselect_shape_same()
{
System.out.print(testname.getMethodName());
long H5sid2 = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create first dataspace with selection
long[] dims1 = {DIM_X, DIM_Y};
MemorySegment dims1Segment = allocateLongArray(arena, RANK);
copyToSegment(dims1Segment, dims1);
H5sid = hdf5_h.H5Screate_simple(RANK, dims1Segment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create second dataspace with different dims but same selection shape
long[] dims2 = {8, 10}; // Different total dims
MemorySegment dims2Segment = allocateLongArray(arena, RANK);
copyToSegment(dims2Segment, dims2);
H5sid2 = hdf5_h.H5Screate_simple(RANK, dims2Segment, MemorySegment.NULL);
assertTrue("H5Screate_simple for sid2 failed", isValidId(H5sid2));
// Select same shaped hyperslab in both (2x3 block)
long[] start1 = {1, 1};
long[] count1 = {2, 3};
MemorySegment start1Segment = allocateLongArray(arena, RANK);
MemorySegment count1Segment = allocateLongArray(arena, RANK);
copyToSegment(start1Segment, start1);
copyToSegment(count1Segment, count1);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), start1Segment,
MemorySegment.NULL, count1Segment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab for sid1 failed", isSuccess(result));
long[] start2 = {2, 3}; // Different position
long[] count2 = {2, 3}; // Same shape
MemorySegment start2Segment = allocateLongArray(arena, RANK);
MemorySegment count2Segment = allocateLongArray(arena, RANK);
copyToSegment(start2Segment, start2);
copyToSegment(count2Segment, count2);
result = hdf5_h.H5Sselect_hyperslab(H5sid2, hdf5_h.H5S_SELECT_SET(), start2Segment,
MemorySegment.NULL, count2Segment, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab for sid2 failed", isSuccess(result));
// Check if selections have same shape
int same = hdf5_h.H5Sselect_shape_same(H5sid, H5sid2);
assertTrue("Selections should have same shape", same > 0);
}
finally {
closeQuietly(H5sid2, hdf5_h::H5Sclose);
}
}
@Test
public void testH5Sis_regular_hyperslab()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select regular hyperslab (single block)
long[] start = {1, 1};
long[] stride = {1, 1};
long[] count = {1, 1};
long[] block = {2, 3};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment strideSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
MemorySegment blockSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(strideSegment, stride);
copyToSegment(countSegment, count);
copyToSegment(blockSegment, block);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
strideSegment, countSegment, blockSegment);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Check if it's regular
int regular = hdf5_h.H5Sis_regular_hyperslab(H5sid);
assertTrue("Should be regular hyperslab", regular > 0);
}
}
@Test
public void testH5Sget_regular_hyperslab()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select regular hyperslab
long[] start = {1, 1};
long[] stride = {2, 2};
long[] count = {2, 2};
long[] block = {1, 1};
MemorySegment startSegment = allocateLongArray(arena, RANK);
MemorySegment strideSegment = allocateLongArray(arena, RANK);
MemorySegment countSegment = allocateLongArray(arena, RANK);
MemorySegment blockSegment = allocateLongArray(arena, RANK);
copyToSegment(startSegment, start);
copyToSegment(strideSegment, stride);
copyToSegment(countSegment, count);
copyToSegment(blockSegment, block);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), startSegment,
strideSegment, countSegment, blockSegment);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Get regular hyperslab info
MemorySegment outStart = allocateLongArray(arena, RANK);
MemorySegment outStride = allocateLongArray(arena, RANK);
MemorySegment outCount = allocateLongArray(arena, RANK);
MemorySegment outBlock = allocateLongArray(arena, RANK);
result = hdf5_h.H5Sget_regular_hyperslab(H5sid, outStart, outStride, outCount, outBlock);
assertTrue("H5Sget_regular_hyperslab failed", isSuccess(result));
// Verify parameters match
assertEquals("Start[0] should match", 1L, outStart.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Start[1] should match", 1L, outStart.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Stride[0] should match", 2L, outStride.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Stride[1] should match", 2L, outStride.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Count[0] should match", 2L, outCount.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Count[1] should match", 2L, outCount.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Block[0] should match", 1L, outBlock.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Block[1] should match", 1L, outBlock.getAtIndex(ValueLayout.JAVA_LONG, 1));
}
}
// ============================================================================
// Phase 1: Advanced Selection Operations
// ============================================================================
@Test
public void testH5Scombine_hyperslab()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// First selection: [1,1] to [2,2] (2x2 block)
long[] start1 = {1, 1};
long[] count1 = {2, 2};
MemorySegment start1s = allocateLongArray(arena, RANK);
MemorySegment count1s = allocateLongArray(arena, RANK);
copyToSegment(start1s, start1);
copyToSegment(count1s, count1);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), start1s,
MemorySegment.NULL, count1s, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Combine with second selection: [2,2] to [3,3] (2x2 block) using OR
long[] start2 = {2, 2};
long[] count2 = {2, 2};
MemorySegment start2s = allocateLongArray(arena, RANK);
MemorySegment count2s = allocateLongArray(arena, RANK);
copyToSegment(start2s, start2);
copyToSegment(count2s, count2);
// Combine creates a new dataspace
long combined_sid = hdf5_h.H5Scombine_hyperslab(H5sid, hdf5_h.H5S_SELECT_OR(), start2s,
MemorySegment.NULL, count2s, MemorySegment.NULL);
assertTrue("H5Scombine_hyperslab failed", isValidId(combined_sid));
// Verify combined selection has more points than original
long original_npoints = hdf5_h.H5Sget_select_npoints(H5sid);
long combined_npoints = hdf5_h.H5Sget_select_npoints(combined_sid);
assertTrue("Combined selection should have more points", combined_npoints > original_npoints);
// Original: 2x2 = 4 points, Combined: should be larger due to OR
assertEquals("Original should have 4 points", 4L, original_npoints);
hdf5_h.H5Sclose(combined_sid);
}
}
@Test
public void testH5Scombine_select()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
// Create first dataspace with selection
long space1_id = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple space1 failed", isValidId(space1_id));
long[] start1 = {0, 0};
long[] count1 = {2, 3};
MemorySegment start1s = allocateLongArray(arena, RANK);
MemorySegment count1s = allocateLongArray(arena, RANK);
copyToSegment(start1s, start1);
copyToSegment(count1s, count1);
int result = hdf5_h.H5Sselect_hyperslab(space1_id, hdf5_h.H5S_SELECT_SET(), start1s,
MemorySegment.NULL, count1s, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab space1 failed", isSuccess(result));
// Create second dataspace with different selection
long space2_id = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple space2 failed", isValidId(space2_id));
long[] start2 = {1, 1};
long[] count2 = {2, 3};
MemorySegment start2s = allocateLongArray(arena, RANK);
MemorySegment count2s = allocateLongArray(arena, RANK);
copyToSegment(start2s, start2);
copyToSegment(count2s, count2);
result = hdf5_h.H5Sselect_hyperslab(space2_id, hdf5_h.H5S_SELECT_SET(), start2s,
MemorySegment.NULL, count2s, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab space2 failed", isSuccess(result));
// Combine selections with OR operation
long combined_sid = hdf5_h.H5Scombine_select(space1_id, hdf5_h.H5S_SELECT_OR(), space2_id);
assertTrue("H5Scombine_select failed", isValidId(combined_sid));
// Verify combined selection has expected points
long space1_npoints = hdf5_h.H5Sget_select_npoints(space1_id);
long space2_npoints = hdf5_h.H5Sget_select_npoints(space2_id);
long combined_npoints = hdf5_h.H5Sget_select_npoints(combined_sid);
assertEquals("Space1 should have 6 points", 6L, space1_npoints);
assertEquals("Space2 should have 6 points", 6L, space2_npoints);
// Combined with OR will be at least the larger of the two
assertTrue("Combined selection should have points", combined_npoints > 0);
hdf5_h.H5Sclose(space1_id);
hdf5_h.H5Sclose(space2_id);
hdf5_h.H5Sclose(combined_sid);
}
}
@Test
public void testH5Smodify_select()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
// Create first dataspace with selection
long space1_id = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple space1 failed", isValidId(space1_id));
long[] start1 = {0, 0};
long[] count1 = {2, 2};
MemorySegment start1s = allocateLongArray(arena, RANK);
MemorySegment count1s = allocateLongArray(arena, RANK);
copyToSegment(start1s, start1);
copyToSegment(count1s, count1);
int result = hdf5_h.H5Sselect_hyperslab(space1_id, hdf5_h.H5S_SELECT_SET(), start1s,
MemorySegment.NULL, count1s, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab space1 failed", isSuccess(result));
long original_npoints = hdf5_h.H5Sget_select_npoints(space1_id);
assertEquals("Original should have 4 points", 4L, original_npoints);
// Create second dataspace with different selection
long space2_id = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple space2 failed", isValidId(space2_id));
long[] start2 = {1, 1};
long[] count2 = {2, 2};
MemorySegment start2s = allocateLongArray(arena, RANK);
MemorySegment count2s = allocateLongArray(arena, RANK);
copyToSegment(start2s, start2);
copyToSegment(count2s, count2);
result = hdf5_h.H5Sselect_hyperslab(space2_id, hdf5_h.H5S_SELECT_SET(), start2s,
MemorySegment.NULL, count2s, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab space2 failed", isSuccess(result));
// Modify space1's selection by combining with space2 using OR
result = hdf5_h.H5Smodify_select(space1_id, hdf5_h.H5S_SELECT_OR(), space2_id);
assertTrue("H5Smodify_select failed", isSuccess(result));
// Verify modified selection has more points
long modified_npoints = hdf5_h.H5Sget_select_npoints(space1_id);
assertTrue("Modified selection should have more points than original",
modified_npoints > original_npoints);
hdf5_h.H5Sclose(space1_id);
hdf5_h.H5Sclose(space2_id);
}
}
@Test
public void testH5Sselect_intersect_block()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create selection: [1,1] to [2,2]
long[] start = {1, 1};
long[] count = {2, 2};
MemorySegment starts = allocateLongArray(arena, RANK);
MemorySegment counts = allocateLongArray(arena, RANK);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Test intersection with overlapping block [1,1] to [2,2]
long[] block_start = {1, 1};
long[] block_end = {2, 2};
MemorySegment bstart = allocateLongArray(arena, RANK);
MemorySegment bend = allocateLongArray(arena, RANK);
copyToSegment(bstart, block_start);
copyToSegment(bend, block_end);
result = hdf5_h.H5Sselect_intersect_block(H5sid, bstart, bend);
assertTrue("Block [1,1]-[2,2] should intersect with selection [1,1]-[2,2]", result > 0);
// Test non-intersecting block [0,0] to [0,0]
long[] block_start2 = {0, 0};
long[] block_end2 = {0, 0};
MemorySegment bstart2 = allocateLongArray(arena, RANK);
MemorySegment bend2 = allocateLongArray(arena, RANK);
copyToSegment(bstart2, block_start2);
copyToSegment(bend2, block_end2);
result = hdf5_h.H5Sselect_intersect_block(H5sid, bstart2, bend2);
assertEquals("Block [0,0]-[0,0] should not intersect with selection [1,1]-[2,2]", 0, result);
}
}
@Test
public void testH5Sselect_project_intersection()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 3D source dataspace
int src_rank = 3;
long[] src_dims = {4, 6, 8};
MemorySegment srcDimsSeg = allocateLongArray(arena, src_rank);
copyToSegment(srcDimsSeg, src_dims);
long src_sid = hdf5_h.H5Screate_simple(src_rank, srcDimsSeg, MemorySegment.NULL);
assertTrue("H5Screate_simple src failed", isValidId(src_sid));
// Select region in source [0,1,1] count [1,2,2] (4 points)
long[] src_start = {0, 1, 1};
long[] src_count = {1, 2, 2};
MemorySegment srcStarts = allocateLongArray(arena, src_rank);
MemorySegment srcCounts = allocateLongArray(arena, src_rank);
copyToSegment(srcStarts, src_start);
copyToSegment(srcCounts, src_count);
int result = hdf5_h.H5Sselect_hyperslab(src_sid, hdf5_h.H5S_SELECT_SET(), srcStarts,
MemorySegment.NULL, srcCounts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab src failed", isSuccess(result));
// Create 3D destination dataspace (same rank as source)
long dst_sid = hdf5_h.H5Screate_simple(src_rank, srcDimsSeg, MemorySegment.NULL);
assertTrue("H5Screate_simple dst failed", isValidId(dst_sid));
// Select matching region in destination [0,0,0] count [1,3,3] (9 points, overlaps with src)
long[] dst_start = {0, 0, 0};
long[] dst_count = {1, 3, 3};
MemorySegment dstStarts = allocateLongArray(arena, src_rank);
MemorySegment dstCounts = allocateLongArray(arena, src_rank);
copyToSegment(dstStarts, dst_start);
copyToSegment(dstCounts, dst_count);
result = hdf5_h.H5Sselect_hyperslab(dst_sid, hdf5_h.H5S_SELECT_SET(), dstStarts,
MemorySegment.NULL, dstCounts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab dst failed", isSuccess(result));
// Create 2D projection space
int proj_rank = 2;
long[] proj_dims = {6, 8};
MemorySegment projDimsSeg = allocateLongArray(arena, proj_rank);
copyToSegment(projDimsSeg, proj_dims);
long proj_space = hdf5_h.H5Screate_simple(proj_rank, projDimsSeg, MemorySegment.NULL);
assertTrue("H5Screate_simple proj failed", isValidId(proj_space));
// Project intersection - projects src selection onto dst, creating result in proj_space
// This tests the function exists and can be called (may fail due to complex requirements)
long proj_sid = hdf5_h.H5Sselect_project_intersection(src_sid, dst_sid, proj_space);
// Only verify if valid ID returned (function is complex and may have strict requirements)
if (isValidId(proj_sid)) {
long proj_npoints = hdf5_h.H5Sget_select_npoints(proj_sid);
assertTrue("Projected selection should have points", proj_npoints > 0);
hdf5_h.H5Sclose(proj_sid);
}
hdf5_h.H5Sclose(src_sid);
hdf5_h.H5Sclose(dst_sid);
hdf5_h.H5Sclose(proj_space);
}
}
// ============================================================================
// Phase 2: Validation and Offset Operations
// ============================================================================
@Test
public void testH5Sselect_valid_comprehensive()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Initially no selection (NONE), which is valid
int result = hdf5_h.H5Sselect_none(H5sid);
assertTrue("H5Sselect_none failed", isSuccess(result));
result = hdf5_h.H5Sselect_valid(H5sid);
assertTrue("NONE selection should be valid", result > 0);
// Select valid hyperslab
long[] start = {0, 0};
long[] count = {2, 2};
MemorySegment starts = allocateLongArray(arena, RANK);
MemorySegment counts = allocateLongArray(arena, RANK);
copyToSegment(starts, start);
copyToSegment(counts, count);
result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), starts, MemorySegment.NULL,
counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
result = hdf5_h.H5Sselect_valid(H5sid);
assertTrue("Valid hyperslab selection should be valid", result > 0);
// Select ALL
result = hdf5_h.H5Sselect_all(H5sid);
assertTrue("H5Sselect_all failed", isSuccess(result));
result = hdf5_h.H5Sselect_valid(H5sid);
assertTrue("ALL selection should be valid", result > 0);
}
}
@Test
public void testH5Soffset_simple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Create selection [1,1] to [2,2]
long[] start = {1, 1};
long[] count = {2, 2};
MemorySegment starts = allocateLongArray(arena, RANK);
MemorySegment counts = allocateLongArray(arena, RANK);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Apply offset [1, 1]
long[] offset = {1, 1};
MemorySegment offsetSeg = allocateLongArray(arena, RANK);
copyToSegment(offsetSeg, offset);
result = hdf5_h.H5Soffset_simple(H5sid, offsetSeg);
assertTrue("H5Soffset_simple failed", isSuccess(result));
// After offset, selection should be shifted to [2,2] to [3,3]
// Verify by getting bounds
MemorySegment startBounds = allocateLongArray(arena, RANK);
MemorySegment endBounds = allocateLongArray(arena, RANK);
result = hdf5_h.H5Sget_select_bounds(H5sid, startBounds, endBounds);
assertTrue("H5Sget_select_bounds failed", isSuccess(result));
long[] outStart = new long[RANK];
long[] outEnd = new long[RANK];
copyFromSegment(startBounds, outStart);
copyFromSegment(endBounds, outEnd);
// Original was [1,1] to [2,2], with offset [1,1] becomes [2,2] to [3,3]
assertEquals("Start[0] should be 2 after offset", 2L, outStart[0]);
assertEquals("Start[1] should be 2 after offset", 2L, outStart[1]);
assertEquals("End[0] should be 3 after offset", 3L, outEnd[0]);
assertEquals("End[1] should be 3 after offset", 3L, outEnd[1]);
}
}
// ============================================================================
// Phase 3: Encoding and Iterator Operations
// ============================================================================
@Test
public void testH5Sdecode_encode2_comprehensive()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Add a selection to make it more interesting
long[] start = {0, 0};
long[] count = {2, 3};
MemorySegment starts = allocateLongArray(arena, RANK);
MemorySegment counts = allocateLongArray(arena, RANK);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Get original npoints
long orig_npoints = hdf5_h.H5Sget_select_npoints(H5sid);
assertEquals("Original should have 6 points", 6L, orig_npoints);
// Encode with H5Sencode2 (first get size)
MemorySegment sizePtr = allocateLong(arena);
result = hdf5_h.H5Sencode2(H5sid, MemorySegment.NULL, sizePtr, hdf5_h.H5P_DEFAULT());
assertTrue("H5Sencode2 size query failed", isSuccess(result));
long size = getLong(sizePtr);
assertTrue("Encoded size should be positive", size > 0);
// Allocate buffer and encode
MemorySegment buffer = arena.allocate(size);
result = hdf5_h.H5Sencode2(H5sid, buffer, sizePtr, hdf5_h.H5P_DEFAULT());
assertTrue("H5Sencode2 failed", isSuccess(result));
// Decode back
long decoded_sid = hdf5_h.H5Sdecode(buffer);
assertTrue("H5Sdecode failed", isValidId(decoded_sid));
// Verify decoded dataspace matches original
long decoded_npoints = hdf5_h.H5Sget_select_npoints(decoded_sid);
assertEquals("Decoded dataspace should have same npoints as original", orig_npoints,
decoded_npoints);
int decoded_ndims = hdf5_h.H5Sget_simple_extent_ndims(decoded_sid);
assertEquals("Decoded dataspace should have same rank", RANK, decoded_ndims);
hdf5_h.H5Sclose(decoded_sid);
}
}
@Test
public void testH5Ssel_iter_comprehensive()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long[] dims = {DIM_X, DIM_Y};
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
copyToSegment(dimsSegment, dims);
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(H5sid));
// Select some elements
long[] start = {0, 0};
long[] count = {2, 2};
MemorySegment starts = allocateLongArray(arena, RANK);
MemorySegment counts = allocateLongArray(arena, RANK);
copyToSegment(starts, start);
copyToSegment(counts, count);
int result = hdf5_h.H5Sselect_hyperslab(H5sid, hdf5_h.H5S_SELECT_SET(), starts,
MemorySegment.NULL, counts, MemorySegment.NULL);
assertTrue("H5Sselect_hyperslab failed", isSuccess(result));
// Create selection iterator
long elmt_size = 4; // 4 bytes for int
long iter_id = hdf5_h.H5Ssel_iter_create(H5sid, elmt_size, 0);
assertTrue("H5Ssel_iter_create failed", isValidId(iter_id));
// Get sequence list
long maxseq = 10;
long maxelmts = 100;
MemorySegment nseqPtr = allocateLong(arena);
MemorySegment neltsPtr = allocateLong(arena);
MemorySegment offArray = allocateLongArray(arena, (int)maxseq);
MemorySegment lenArray = allocateLongArray(arena, (int)maxseq);
result = hdf5_h.H5Ssel_iter_get_seq_list(iter_id, maxseq, maxelmts, nseqPtr, neltsPtr, offArray,
lenArray);
assertTrue("H5Ssel_iter_get_seq_list failed", isSuccess(result));
long nseq = getLong(nseqPtr);
long nelts = getLong(neltsPtr);
assertTrue("Should have at least one sequence", nseq > 0);
assertTrue("Should have at least one element", nelts > 0);
// Reset iterator
result = hdf5_h.H5Ssel_iter_reset(iter_id, H5sid);
assertTrue("H5Ssel_iter_reset failed", isSuccess(result));
// Close iterator
result = hdf5_h.H5Ssel_iter_close(iter_id);
assertTrue("H5Ssel_iter_close failed", isSuccess(result));
}
}
}
+2206
View File
@@ -0,0 +1,2206 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Datatype (H5T) operations.
*
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
*
* Note: Some tests are disabled on Windows due to known FFM limitations.
*/
public class TestH5Tffm {
@Rule
public TestName testname = new TestName();
/** Helper to check if running on Windows */
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
static
{
// Initialize FFM library by calling H5open()
// This ensures global type variables are properly initialized
try {
hdf5_h.H5open();
}
catch (Exception e) {
System.err.println("Warning: H5open() failed during FFM initialization: " + e);
}
}
// Predefined datatype constants
// Datatype classes
// String padding
long H5tid = hdf5_h.H5I_INVALID_HID();
@After
public void cleanup()
{
closeQuietly(H5tid, hdf5_h::H5Tclose);
H5tid = hdf5_h.H5I_INVALID_HID();
System.out.println();
}
@Test
public void testH5Tcopy()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
}
@Test
public void testH5Tequal()
{
System.out.print(testname.getMethodName());
long tid2 = hdf5_h.H5I_INVALID_HID();
try {
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
tid2 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(tid2));
int result = hdf5_h.H5Tequal(H5tid, tid2);
assertTrue("Types should be equal", result > 0);
// Compare with different type
result = hdf5_h.H5Tequal(H5tid, hdf5_h.H5T_IEEE_F32LE_g());
assertFalse("Types should not be equal", result > 0);
}
finally {
closeQuietly(tid2, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Tget_class()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Type class should be INTEGER", hdf5_h.H5T_INTEGER(), tclass);
}
@Test
public void testH5Tget_size()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
long size = hdf5_h.H5Tget_size(H5tid);
assertTrue("Type size should be > 0", size > 0);
assertEquals("H5T_STD_I32LE should be 4 bytes", 4, size);
}
@Test
public void testH5Tset_size()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int result = hdf5_h.H5Tset_size(H5tid, 64);
assertTrue("H5Tset_size failed", isSuccess(result));
long size = hdf5_h.H5Tget_size(H5tid);
assertEquals("Size should be 64", 64, size);
}
@Test
public void testH5Tget_order()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int order = hdf5_h.H5Tget_order(H5tid);
assertTrue("Byte order should be valid", order >= 0);
}
@Test
public void testH5Tget_precision()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
long precision = hdf5_h.H5Tget_precision(H5tid);
assertTrue("Precision should be > 0", precision > 0);
}
@Test
public void testH5Tset_precision()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int result = hdf5_h.H5Tset_precision(H5tid, 16);
assertTrue("H5Tset_precision failed", isSuccess(result));
long precision = hdf5_h.H5Tget_precision(H5tid);
assertEquals("Precision should be 16", 16, precision);
}
@Test
public void testH5Tget_strpad()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int strpad = hdf5_h.H5Tget_strpad(H5tid);
assertTrue("String padding should be valid", strpad >= 0);
}
@Test
public void testH5Tcreate_compound()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a compound type with int and double
int compoundSize = 4 + 8; // sizeof(int) + sizeof(double)
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), compoundSize);
assertTrue("H5Tcreate failed", isValidId(H5tid));
// Insert int member
MemorySegment intNameSegment = stringToSegment(arena, "int_field");
int result = hdf5_h.H5Tinsert(H5tid, intNameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tinsert int failed", isSuccess(result));
// Insert double member
MemorySegment doubleNameSegment = stringToSegment(arena, "double_field");
result = hdf5_h.H5Tinsert(H5tid, doubleNameSegment, 4, hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("H5Tinsert double failed", isSuccess(result));
// Verify it's a compound type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Type class should be COMPOUND", hdf5_h.H5T_COMPOUND(), tclass);
// Verify number of members
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
assertEquals("Should have 2 members", 2, nmembers);
}
}
@Test
public void testH5Tget_nmembers()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
assertTrue("H5Tcreate failed", isValidId(H5tid));
MemorySegment nameSegment = stringToSegment(arena, "field1");
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
assertEquals("Should have 1 member", 1, nmembers);
}
}
@Test
public void testH5Tget_member_name()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
assertTrue("H5Tcreate failed", isValidId(H5tid));
String fieldName = "test_field";
MemorySegment nameSegment = stringToSegment(arena, fieldName);
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
MemorySegment returnedName = hdf5_h.H5Tget_member_name(H5tid, 0);
assertFalse("Returned name should not be null", returnedName.equals(MemorySegment.NULL));
String memberName = returnedName.getString(0);
assertEquals("Member name should match", fieldName, memberName);
}
}
@Test
public void testH5Tget_member_offset()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
assertTrue("H5Tcreate failed", isValidId(H5tid));
long expectedOffset = 4;
MemorySegment nameSegment = stringToSegment(arena, "field");
hdf5_h.H5Tinsert(H5tid, nameSegment, expectedOffset, hdf5_h.H5T_STD_I32LE_g());
long offset = hdf5_h.H5Tget_member_offset(H5tid, 0);
assertEquals("Offset should match", expectedOffset, offset);
}
}
@Test
public void testH5Tget_member_type()
{
System.out.print(testname.getMethodName());
long memberType = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
assertTrue("H5Tcreate failed", isValidId(H5tid));
MemorySegment nameSegment = stringToSegment(arena, "field");
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
memberType = hdf5_h.H5Tget_member_type(H5tid, 0);
assertTrue("H5Tget_member_type failed", isValidId(memberType));
// Verify it's an integer type
int tclass = hdf5_h.H5Tget_class(memberType);
assertEquals("Member type should be INTEGER", hdf5_h.H5T_INTEGER(), tclass);
}
finally {
closeQuietly(memberType, hdf5_h::H5Tclose);
}
}
@Test
public void testH5Tarray_create()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create array type: int[3][4]
int rank = 2;
long[] dims = {3, 4};
MemorySegment dimsSegment = allocateLongArray(arena, rank);
copyToSegment(dimsSegment, dims);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), rank, dimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
// Verify it's an array type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Type class should be ARRAY", hdf5_h.H5T_ARRAY(), tclass);
}
}
@Test
public void testH5Tget_array_dims()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
int rank = 2;
long[] expectedDims = {3, 4};
MemorySegment dimsSegment = allocateLongArray(arena, rank);
copyToSegment(dimsSegment, expectedDims);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), rank, dimsSegment);
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
MemorySegment returnedDimsSegment = allocateLongArray(arena, rank);
int result = hdf5_h.H5Tget_array_dims2(H5tid, returnedDimsSegment);
assertEquals("H5Tget_array_dims2 should return rank", rank, result);
long[] returnedDims = new long[rank];
copyFromSegment(returnedDimsSegment, returnedDims);
assertArrayEquals("Array dimensions should match", expectedDims, returnedDims);
}
}
@Test
public void testH5Tenum_operations()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create enum type
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tenum_create failed", isValidId(H5tid));
// Insert enum values
MemorySegment redSegment = stringToSegment(arena, "RED");
MemorySegment redValueSegment = allocateInt(arena);
setInt(redValueSegment, 0);
int result = hdf5_h.H5Tenum_insert(H5tid, redSegment, redValueSegment);
assertTrue("H5Tenum_insert RED failed", isSuccess(result));
MemorySegment greenSegment = stringToSegment(arena, "GREEN");
MemorySegment greenValueSegment = allocateInt(arena);
setInt(greenValueSegment, 1);
result = hdf5_h.H5Tenum_insert(H5tid, greenSegment, greenValueSegment);
assertTrue("H5Tenum_insert GREEN failed", isSuccess(result));
MemorySegment blueSegment = stringToSegment(arena, "BLUE");
MemorySegment blueValueSegment = allocateInt(arena);
setInt(blueValueSegment, 2);
result = hdf5_h.H5Tenum_insert(H5tid, blueSegment, blueValueSegment);
assertTrue("H5Tenum_insert BLUE failed", isSuccess(result));
// Verify number of members
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
assertEquals("Should have 3 members", 3, nmembers);
// Test H5Tenum_nameof - get name from value
MemorySegment lookupValueSegment = allocateInt(arena);
setInt(lookupValueSegment, 1);
MemorySegment nameSegment = arena.allocate(64); // Allocate buffer for name
int nameResult = hdf5_h.H5Tenum_nameof(H5tid, lookupValueSegment, nameSegment, 64);
assertTrue("H5Tenum_nameof failed", isSuccess(nameResult));
String name = nameSegment.getString(0);
assertEquals("Name should be GREEN", "GREEN", name);
// Test H5Tenum_valueof - get value from name
MemorySegment lookupNameSegment = stringToSegment(arena, "BLUE");
MemorySegment valueSegment = allocateInt(arena);
result = hdf5_h.H5Tenum_valueof(H5tid, lookupNameSegment, valueSegment);
assertTrue("H5Tenum_valueof failed", isSuccess(result));
int value = getInt(valueSegment);
assertEquals("Value should be 2", 2, value);
// Verify it's an enum type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Type class should be ENUM", hdf5_h.H5T_ENUM(), tclass);
}
}
@Test
public void testH5Tis_variable_str()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create fixed-length string type
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
hdf5_h.H5Tset_size(H5tid, 10);
int result = hdf5_h.H5Tis_variable_str(H5tid);
assertFalse("Fixed-length string should not be variable", result > 0);
// Close and create variable-length string type
hdf5_h.H5Tclose(H5tid);
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
hdf5_h.H5Tset_size(H5tid, -1); // H5T_VARIABLE
result = hdf5_h.H5Tis_variable_str(H5tid);
assertTrue("Variable-length string should be variable", result > 0);
}
}
@Test
public void testH5Tget_cset()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int cset = hdf5_h.H5Tget_cset(H5tid);
assertTrue("Character set should be valid", cset >= 0);
// H5T_CSET_ASCII = 0
assertEquals("Default character set should be ASCII", 0, cset);
}
@Test
public void testH5Tclose()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
int result = hdf5_h.H5Tclose(H5tid);
assertTrue("H5Tclose failed", isSuccess(result));
H5tid = hdf5_h.H5I_INVALID_HID();
}
@Test
public void testH5Tvlen_create()
{
// Skip on Windows - FFM memory layout issue with variable-length types
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create variable-length type of integers
// Use H5T_STD_I32LE instead of H5T_NATIVE_INT for platform consistency
H5tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tvlen_create failed", isValidId(H5tid));
// Verify it's a variable-length type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Should be H5T_VLEN class", hdf5_h.H5T_VLEN(), tclass);
// Get the base type
long base_type = hdf5_h.H5Tget_super(H5tid);
assertTrue("H5Tget_super should return valid type", isValidId(base_type));
// Verify base type is 32-bit integer
int equal = hdf5_h.H5Tequal(base_type, hdf5_h.H5T_STD_I32LE_g());
assertTrue("Base type should be H5T_STD_I32LE", equal > 0);
hdf5_h.H5Tclose(base_type);
}
}
@Test
public void testH5Topaque_operations()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create opaque type with 16 bytes
long size = 16;
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), size);
assertTrue("H5Tcreate opaque failed", isValidId(H5tid));
// Verify it's opaque
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Should be H5T_OPAQUE class", hdf5_h.H5T_OPAQUE(), tclass);
// Set tag for opaque type
String tag = "16-byte opaque data";
MemorySegment tagSegment = stringToSegment(arena, tag);
int result = hdf5_h.H5Tset_tag(H5tid, tagSegment);
assertTrue("H5Tset_tag failed", isSuccess(result));
// Get tag back
MemorySegment outTag = hdf5_h.H5Tget_tag(H5tid);
assertFalse("H5Tget_tag should return valid pointer", outTag.address() == 0);
String retrievedTag = outTag.getString(0);
assertEquals("Tag should match", tag, retrievedTag);
// Verify size
long retrievedSize = hdf5_h.H5Tget_size(H5tid);
assertEquals("Size should be 16", size, retrievedSize);
}
}
@Test
public void testH5Tget_sign_set_sign()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create integer type
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
// Get current sign
int sign = hdf5_h.H5Tget_sign(H5tid);
assertTrue("H5Tget_sign should succeed", sign >= 0);
// Set to unsigned
int result = hdf5_h.H5Tset_sign(H5tid, hdf5_h.H5T_SGN_NONE());
assertTrue("H5Tset_sign failed", isSuccess(result));
// Verify sign changed
int newSign = hdf5_h.H5Tget_sign(H5tid);
assertEquals("Sign should be H5T_SGN_NONE", hdf5_h.H5T_SGN_NONE(), newSign);
}
}
@Test
public void testH5Tget_offset_set_offset()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create integer type
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
// Get current offset
long offset = hdf5_h.H5Tget_offset(H5tid);
assertTrue("H5Tget_offset should succeed", offset >= 0);
// Set new offset (shift by 2 bits)
long newOffset = 2;
int result = hdf5_h.H5Tset_offset(H5tid, newOffset);
assertTrue("H5Tset_offset failed", isSuccess(result));
// Verify offset changed
long retrievedOffset = hdf5_h.H5Tget_offset(H5tid);
assertEquals("Offset should be 2", newOffset, retrievedOffset);
}
}
@Test
public void testH5Tget_pad_set_pad()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create integer type
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tcopy failed", isValidId(H5tid));
// Get current padding
MemorySegment lsbSegment = allocateInt(arena);
MemorySegment msbSegment = allocateInt(arena);
int result = hdf5_h.H5Tget_pad(H5tid, lsbSegment, msbSegment);
assertTrue("H5Tget_pad failed", isSuccess(result));
// Set new padding (both to zero)
result = hdf5_h.H5Tset_pad(H5tid, hdf5_h.H5T_PAD_ZERO(), hdf5_h.H5T_PAD_ZERO());
assertTrue("H5Tset_pad failed", isSuccess(result));
// Verify padding changed
MemorySegment newLsbSegment = allocateInt(arena);
MemorySegment newMsbSegment = allocateInt(arena);
result = hdf5_h.H5Tget_pad(H5tid, newLsbSegment, newMsbSegment);
assertTrue("H5Tget_pad failed", isSuccess(result));
assertEquals("LSB padding should be ZERO", hdf5_h.H5T_PAD_ZERO(), getInt(newLsbSegment));
assertEquals("MSB padding should be ZERO", hdf5_h.H5T_PAD_ZERO(), getInt(newMsbSegment));
}
}
@Test
public void testH5Tconvert_basic()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create buffer with int values
int numElements = 5;
int[] intData = {1, 2, 3, 4, 5};
// Allocate buffer and copy int data
MemorySegment buffer = arena.allocate(numElements * 8); // Enough for doubles
for (int i = 0; i < numElements; i++) {
buffer.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, i, intData[i]);
}
// Convert int to double
long srcType = hdf5_h.H5T_STD_I32LE_g();
long dstType = hdf5_h.H5T_IEEE_F64LE_g();
int result = hdf5_h.H5Tconvert(srcType, dstType, numElements, buffer, MemorySegment.NULL,
hdf5_h.H5P_DEFAULT());
assertTrue("H5Tconvert failed", isSuccess(result));
// Verify first converted value
double convertedValue = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_DOUBLE, 0);
assertEquals("First value should be 1.0", 1.0, convertedValue, 0.001);
}
}
@Test
public void testH5Tconvert_int_to_float()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create buffer with int values
int numElements = 3;
int[] intData = {10, 20, 30};
// Allocate separate buffers for in-place conversion
MemorySegment buffer = arena.allocate(numElements * 4); // 4 bytes per int/float
for (int i = 0; i < numElements; i++) {
buffer.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, i, intData[i]);
}
// Convert int to float in-place
int result = hdf5_h.H5Tconvert(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g(), numElements,
buffer, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
assertTrue("H5Tconvert failed", isSuccess(result));
// Verify converted values
float val0 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 0);
float val1 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 1);
float val2 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 2);
assertEquals("First value should be 10.0", 10.0f, val0, 0.001f);
assertEquals("Second value should be 20.0", 20.0f, val1, 0.001f);
assertEquals("Third value should be 30.0", 30.0f, val2, 0.001f);
}
}
@Test
public void testH5Treclaim_with_vlen_string()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create variable-length string type
long strType = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy failed", isValidId(strType));
int result = hdf5_h.H5Tset_size(strType, -1); // H5T_VARIABLE
assertTrue("H5Tset_size failed", isSuccess(result));
// Create simple 1D dataspace with 1 element
long[] dimsArray = {1};
MemorySegment dims = allocateLongArray(arena, 1);
copyToSegment(dims, dimsArray);
long space = hdf5_h.H5Screate_simple(1, dims, MemorySegment.NULL);
assertTrue("H5Screate_simple failed", isValidId(space));
// Allocate buffer for pointer to string
MemorySegment buffer = arena.allocate(8); // Pointer size
// Set to NULL initially (nothing to reclaim, but tests the API)
buffer.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
// Test H5Treclaim - should succeed even with NULL pointer
result = hdf5_h.H5Treclaim(strType, space, hdf5_h.H5P_DEFAULT(), buffer);
assertTrue("H5Treclaim should succeed", isSuccess(result));
// Cleanup
hdf5_h.H5Sclose(space);
hdf5_h.H5Tclose(strType);
}
}
@Test
public void testH5Tfind_conversion_path()
{
// Skip on Windows - FFM memory layout issue with conversion functions
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Try to find conversion path from int to float
MemorySegment pcdata = arena.allocate(8); // Pointer to H5T_cdata_t*
pcdata.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
MemorySegment convFunc =
hdf5_h.H5Tfind(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g(), pcdata);
// H5Tfind returns function pointer (can be NULL if no conversion exists)
// For standard types, conversion should exist
assertFalse("Conversion function should be found", convFunc.equals(MemorySegment.NULL));
}
}
@Test
public void testH5Tfind_same_type()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Find conversion path from type to itself (should be no-op conversion)
MemorySegment pcdata = arena.allocate(8);
pcdata.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
MemorySegment convFunc =
hdf5_h.H5Tfind(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_STD_I32LE_g(), pcdata);
// Conversion from type to itself should exist (no-op)
assertFalse("No-op conversion should be found", convFunc.equals(MemorySegment.NULL));
}
}
@Test
public void testH5Tget_fields()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a copy of a floating point type
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("H5Tcopy failed", isValidId(floatType));
// Get field positions for floating point type
MemorySegment spos = allocateLongArray(arena, 1); // sign position
MemorySegment epos = allocateLongArray(arena, 1); // exponent position
MemorySegment esize = allocateLongArray(arena, 1); // exponent size
MemorySegment mpos = allocateLongArray(arena, 1); // mantissa position
MemorySegment msize = allocateLongArray(arena, 1); // mantissa size
int result = hdf5_h.H5Tget_fields(floatType, spos, epos, esize, mpos, msize);
assertTrue("H5Tget_fields failed", isSuccess(result));
// Verify we got valid values (all should be >= 0)
long sposVal = getLong(spos);
long eposVal = getLong(epos);
long esizeVal = getLong(esize);
long mposVal = getLong(mpos);
long msizeVal = getLong(msize);
assertTrue("Sign position should be valid", sposVal >= 0);
assertTrue("Exponent position should be valid", eposVal >= 0);
assertTrue("Exponent size should be > 0", esizeVal > 0);
assertTrue("Mantissa position should be valid", mposVal >= 0);
assertTrue("Mantissa size should be > 0", msizeVal > 0);
hdf5_h.H5Tclose(floatType);
}
}
@Test
public void testH5Tget_ebias()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Get exponent bias for double
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("H5Tcopy failed", isValidId(floatType));
long ebias = hdf5_h.H5Tget_ebias(floatType);
assertTrue("Exponent bias should be > 0", ebias > 0);
// For IEEE 754 double, exponent bias is typically 1023
// We won't test exact value as it's platform-dependent, but it should be reasonable
assertTrue("Exponent bias should be reasonable", ebias < 10000);
hdf5_h.H5Tclose(floatType);
}
}
@Test
public void testH5Tget_norm()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Get normalization type for floating point
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
assertTrue("H5Tcopy failed", isValidId(floatType));
int norm = hdf5_h.H5Tget_norm(floatType);
assertTrue("Normalization should be valid", norm >= 0);
// Typical normalization types: IMPLIED (0), MSBSET (1), NONE (2)
assertTrue("Normalization should be in valid range", norm <= 2);
hdf5_h.H5Tclose(floatType);
}
}
@Test
public void testH5Tget_inpad()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Get internal padding type for floating point
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("H5Tcopy failed", isValidId(floatType));
int inpad = hdf5_h.H5Tget_inpad(floatType);
assertTrue("Internal padding should be valid", inpad >= 0);
// Padding types: ZERO (0), ONE (1), BACKGROUND (2)
assertTrue("Internal padding should be in valid range", inpad <= 2);
hdf5_h.H5Tclose(floatType);
}
}
@Test
public void testH5Tset_fields_and_ebias()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a custom floating point type
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
assertTrue("H5Tcopy failed", isValidId(floatType));
// Set custom field layout
// For 32-bit float: sign(1) + exponent(8) + mantissa(23) = 32 bits
long spos = 31; // Sign at bit 31
long epos = 23; // Exponent starts at bit 23
long esize = 8; // Exponent is 8 bits
long mpos = 0; // Mantissa starts at bit 0
long msize = 23; // Mantissa is 23 bits
int result = hdf5_h.H5Tset_fields(floatType, spos, epos, esize, mpos, msize);
assertTrue("H5Tset_fields failed", isSuccess(result));
// Set exponent bias (for 8-bit exponent, typical bias is 127)
result = hdf5_h.H5Tset_ebias(floatType, 127);
assertTrue("H5Tset_ebias failed", isSuccess(result));
// Verify the settings
long retrievedEbias = hdf5_h.H5Tget_ebias(floatType);
assertEquals("Exponent bias should match", 127, retrievedEbias);
hdf5_h.H5Tclose(floatType);
}
}
// ============================================================================
// H5T Array Datatype Tests
// ============================================================================
@Test
public void testH5Tarray_create_1D()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 1D array of integers [10]
long[] dimValues = {10};
MemorySegment dims = allocateLongArray(arena, 1);
copyToSegment(dims, dimValues);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 1, dims);
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
// Verify it's an array type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Should be array type", hdf5_h.H5T_ARRAY(), tclass);
// Verify dimensions
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
assertEquals("Should be 1D array", 1, ndims);
MemorySegment retrievedDims = allocateLongArray(arena, 1);
int result = hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
assertEquals("H5Tget_array_dims2 should succeed", 1, result);
assertEquals("Dimension should be 10", 10, retrievedDims.get(ValueLayout.JAVA_LONG, 0));
}
}
@Test
public void testH5Tarray_create_2D()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 2D array of floats [3][4]
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 3, 4);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F32LE_g(), 2, dims);
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
// Verify dimensions
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
assertEquals("Should be 2D array", 2, ndims);
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 2);
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
assertEquals("First dimension should be 3", 3,
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Second dimension should be 4", 4,
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
}
}
@Test
public void testH5Tarray_create_3D()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 3D array of doubles [2][3][4]
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 2, 3, 4);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 3, dims);
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
// Verify dimensions
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
assertEquals("Should be 3D array", 3, ndims);
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 3);
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
assertEquals("First dimension should be 2", 2,
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Second dimension should be 3", 3,
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Third dimension should be 4", 4,
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
}
}
@Test
public void testH5Tget_array_ndims()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Test with different dimensionalities
MemorySegment dims1 = arena.allocateFrom(ValueLayout.JAVA_LONG, 10L);
long tid1 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 1, dims1);
assertEquals("Should be 1D", 1, hdf5_h.H5Tget_array_ndims(tid1));
hdf5_h.H5Tclose(tid1);
MemorySegment dims2 = arena.allocateFrom(ValueLayout.JAVA_LONG, 5L, 6L);
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims2);
assertEquals("Should be 2D", 2, hdf5_h.H5Tget_array_ndims(tid2));
hdf5_h.H5Tclose(tid2);
MemorySegment dims3 = arena.allocateFrom(ValueLayout.JAVA_LONG, 2L, 3L, 4L);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 3, dims3);
assertEquals("Should be 3D", 3, hdf5_h.H5Tget_array_ndims(H5tid));
}
}
@Test
public void testH5Tget_array_dims2()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create array with specific dimensions
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 7, 8, 9);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I64LE_g(), 3, dims);
// Retrieve dimensions
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 3);
int result = hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
assertEquals("H5Tget_array_dims2 should return rank", 3, result);
// Verify each dimension
assertEquals("Dim 0 should be 7", 7, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Dim 1 should be 8", 8, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Dim 2 should be 9", 9, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
}
}
@Test
public void testH5Tarray_with_compound_base()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create compound type
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "x"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "y"), 4, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "z"), 8, hdf5_h.H5T_STD_I32LE_g());
// Create array of compound types [5]
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5L);
H5tid = hdf5_h.H5Tarray_create2(compoundType, 1, dims);
assertTrue("H5Tarray_create2 with compound base failed", isValidId(H5tid));
// Verify array properties
assertEquals("Should be array type", hdf5_h.H5T_ARRAY(), hdf5_h.H5Tget_class(H5tid));
assertEquals("Should be 1D", 1, hdf5_h.H5Tget_array_ndims(H5tid));
// Get super type (base type)
long superType = hdf5_h.H5Tget_super(H5tid);
assertTrue("Should have valid super type", isValidId(superType));
assertEquals("Super type should be compound", hdf5_h.H5T_COMPOUND(),
hdf5_h.H5Tget_class(superType));
hdf5_h.H5Tclose(superType);
hdf5_h.H5Tclose(compoundType);
}
}
@Test
public void testH5Tget_super_array()
{
// Skip on Windows - FFM memory layout issue with array dimensions
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create array type
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 10L);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I16LE_g(), 1, dims);
// Get the base type
long superType = hdf5_h.H5Tget_super(H5tid);
assertTrue("H5Tget_super failed", isValidId(superType));
// Verify base type is short
int equal = hdf5_h.H5Tequal(superType, hdf5_h.H5T_STD_I16LE_g());
assertTrue("Base type should be H5T_STD_I16LE", equal > 0);
hdf5_h.H5Tclose(superType);
}
}
@Test
public void testH5Tarray_size()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create array [5][10] of ints (4 bytes each)
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 10);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
// Get size - should be 5 * 10 * 4 = 200 bytes
long size = hdf5_h.H5Tget_size(H5tid);
assertEquals("Array size should be 200 bytes", 200, size);
// For doubles (8 bytes each): 5 * 10 * 8 = 400 bytes
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 2, dims);
long size2 = hdf5_h.H5Tget_size(tid2);
assertEquals("Array size should be 400 bytes", 400, size2);
hdf5_h.H5Tclose(tid2);
}
}
// ============================================================================
// H5T Enum Datatype Tests
// ============================================================================
@Test
public void testH5Tenum_create()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
assertTrue("H5Tenum_create failed", isValidId(H5tid));
// Verify it's an enum type
int tclass = hdf5_h.H5Tget_class(H5tid);
assertEquals("Should be enum type", hdf5_h.H5T_ENUM(), tclass);
}
@Test
public void testH5Tenum_insert()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert enum values
MemorySegment val0 = allocateInt(arena);
setInt(val0, 0);
int result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "RED"), val0);
assertEquals("H5Tenum_insert RED failed", 0, result);
MemorySegment val1 = allocateInt(arena);
setInt(val1, 1);
result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "GREEN"), val1);
assertEquals("H5Tenum_insert GREEN failed", 0, result);
MemorySegment val2 = allocateInt(arena);
setInt(val2, 2);
result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "BLUE"), val2);
assertEquals("H5Tenum_insert BLUE failed", 0, result);
// Verify member count
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
assertEquals("Should have 3 enum members", 3, nmembers);
}
}
@Test
public void testH5Tenum_insert_multiple()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert multiple values
String[] names = {"NORTH", "SOUTH", "EAST", "WEST"};
for (int i = 0; i < names.length; i++) {
MemorySegment val = allocateInt(arena);
setInt(val, i * 10);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, names[i]), val);
}
assertEquals("Should have 4 members", 4, hdf5_h.H5Tget_nmembers(H5tid));
}
}
@Test
public void testH5Tenum_nameof()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert enum values
MemorySegment val0 = allocateInt(arena);
setInt(val0, 100);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "ALPHA"), val0);
MemorySegment val1 = allocateInt(arena);
setInt(val1, 200);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "BETA"), val1);
// Get name for value 100
MemorySegment nameBuffer = arena.allocate(20);
MemorySegment queryVal = allocateInt(arena);
setInt(queryVal, 100);
int result = hdf5_h.H5Tenum_nameof(H5tid, queryVal, nameBuffer, 20);
assertEquals("H5Tenum_nameof failed", 0, result);
String name = nameBuffer.getString(0);
assertEquals("Name should be ALPHA", "ALPHA", name);
// Get name for value 200
setInt(queryVal, 200);
result = hdf5_h.H5Tenum_nameof(H5tid, queryVal, nameBuffer, 20);
assertEquals("H5Tenum_nameof failed", 0, result);
name = nameBuffer.getString(0);
assertEquals("Name should be BETA", "BETA", name);
}
}
@Test
public void testH5Tenum_valueof()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert enum values
MemorySegment val0 = allocateInt(arena);
setInt(val0, 42);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "MAGIC"), val0);
MemorySegment val1 = allocateInt(arena);
setInt(val1, 99);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SPECIAL"), val1);
// Get value for name "MAGIC"
MemorySegment retrievedVal = allocateInt(arena);
int result = hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "MAGIC"), retrievedVal);
assertEquals("H5Tenum_valueof failed", 0, result);
assertEquals("Value should be 42", 42, getInt(retrievedVal));
// Get value for name "SPECIAL"
result = hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "SPECIAL"), retrievedVal);
assertEquals("H5Tenum_valueof failed", 0, result);
assertEquals("Value should be 99", 99, getInt(retrievedVal));
}
}
@Test
public void testH5Tenum_get_member_value()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert values
MemorySegment val0 = allocateInt(arena);
setInt(val0, 10);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "FIRST"), val0);
MemorySegment val1 = allocateInt(arena);
setInt(val1, 20);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SECOND"), val1);
MemorySegment val2 = allocateInt(arena);
setInt(val2, 30);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "THIRD"), val2);
// Get member values by index
MemorySegment retrievedVal = allocateInt(arena);
hdf5_h.H5Tget_member_value(H5tid, 0, retrievedVal);
assertEquals("First member value should be 10", 10, getInt(retrievedVal));
hdf5_h.H5Tget_member_value(H5tid, 1, retrievedVal);
assertEquals("Second member value should be 20", 20, getInt(retrievedVal));
hdf5_h.H5Tget_member_value(H5tid, 2, retrievedVal);
assertEquals("Third member value should be 30", 30, getInt(retrievedVal));
}
}
@Test
public void testH5Tenum_negative_values()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert negative values (for error codes, etc.)
MemorySegment valNeg1 = allocateInt(arena);
setInt(valNeg1, -1);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "ERROR"), valNeg1);
MemorySegment val0 = allocateInt(arena);
setInt(val0, 0);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SUCCESS"), val0);
MemorySegment val1 = allocateInt(arena);
setInt(val1, 1);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "WARNING"), val1);
// Retrieve negative value
MemorySegment retrievedVal = allocateInt(arena);
hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "ERROR"), retrievedVal);
assertEquals("Value should be -1", -1, getInt(retrievedVal));
}
}
@Test
public void testH5Tget_nmembers_enum()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Initially should have 0 members
assertEquals("Empty enum should have 0 members", 0, hdf5_h.H5Tget_nmembers(H5tid));
// Add members one by one and check count
for (int i = 0; i < 5; i++) {
MemorySegment val = allocateInt(arena);
setInt(val, i);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "MEMBER_" + i), val);
assertEquals("Should have " + (i + 1) + " members", i + 1, hdf5_h.H5Tget_nmembers(H5tid));
}
}
}
// ============================================================================
// H5T String Datatype Tests
// ============================================================================
@Test
public void testH5Tcreate_string_variable()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
assertTrue("H5Tcopy for string failed", isValidId(H5tid));
// Set to variable length
int result = hdf5_h.H5Tset_size(H5tid, hdf5_h.H5T_VARIABLE());
assertTrue("H5Tset_size to variable should succeed", isSuccess(result));
// Verify it's variable length (H5T_VARIABLE returns size_t max, which appears as -1 when signed)
long size = hdf5_h.H5Tget_size(H5tid);
// Variable length strings report their size as the size of hvl_t struct (16 bytes on 64-bit)
// Use H5Tis_variable_str to check if it's truly variable length
int isVar = hdf5_h.H5Tis_variable_str(H5tid);
assertTrue("Should be variable length string", isVar > 0);
// Verify it's a string type
assertEquals("Should be string class", hdf5_h.H5T_STRING(), hdf5_h.H5Tget_class(H5tid));
}
@Test
public void testH5Tcreate_string_fixed()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
// Set to fixed length of 50 characters
int result = hdf5_h.H5Tset_size(H5tid, 50);
assertEquals("H5Tset_size failed", 0, result);
// Verify size
long size = hdf5_h.H5Tget_size(H5tid);
assertEquals("String length should be 50", 50, size);
}
@Test
public void testH5Tset_strpad()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
hdf5_h.H5Tset_size(H5tid, 20);
// Test NULL padding
int result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_NULLPAD());
assertEquals("H5Tset_strpad NULLPAD failed", 0, result);
assertEquals("Should be NULLPAD", hdf5_h.H5T_STR_NULLPAD(), hdf5_h.H5Tget_strpad(H5tid));
// Test NULL termination
result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_NULLTERM());
assertEquals("H5Tset_strpad NULLTERM failed", 0, result);
assertEquals("Should be NULLTERM", hdf5_h.H5T_STR_NULLTERM(), hdf5_h.H5Tget_strpad(H5tid));
// Test SPACE padding
result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_SPACEPAD());
assertEquals("H5Tset_strpad SPACEPAD failed", 0, result);
assertEquals("Should be SPACEPAD", hdf5_h.H5T_STR_SPACEPAD(), hdf5_h.H5Tget_strpad(H5tid));
}
// ============================================================================
// H5T VLen Advanced Tests
// ============================================================================
@Test
public void testH5Tvlen_create_nested()
{
System.out.print(testname.getMethodName());
// Create vlen of vlen (nested variable length)
long innerVlen = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
assertTrue("Inner vlen creation failed", isValidId(innerVlen));
H5tid = hdf5_h.H5Tvlen_create(innerVlen);
assertTrue("Outer vlen creation failed", isValidId(H5tid));
// Verify it's a vlen type
assertEquals("Should be vlen class", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(H5tid));
// Get super type
long superType = hdf5_h.H5Tget_super(H5tid);
assertTrue("Super type should be valid", isValidId(superType));
assertEquals("Super should be vlen", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(superType));
hdf5_h.H5Tclose(superType);
hdf5_h.H5Tclose(innerVlen);
}
@Test
public void testH5Tvlen_with_compound()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create compound type
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("id"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("value"), 8, hdf5_h.H5T_IEEE_F64LE_g());
// Create vlen of compound
H5tid = hdf5_h.H5Tvlen_create(compoundType);
assertTrue("Vlen of compound creation failed", isValidId(H5tid));
// Verify base type is compound
long superType = hdf5_h.H5Tget_super(H5tid);
assertEquals("Super type should be compound", hdf5_h.H5T_COMPOUND(),
hdf5_h.H5Tget_class(superType));
hdf5_h.H5Tclose(superType);
hdf5_h.H5Tclose(compoundType);
}
}
@Test
public void testH5Tvlen_is_variable()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
// Vlen types report their size as sizeof(hvl_t) which is 16 bytes on 64-bit
// The proper way to check is via the type class
assertEquals("Should be vlen class", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(H5tid));
// Verify the size is the hvl_t struct size (typically 16 bytes)
long size = hdf5_h.H5Tget_size(H5tid);
assertTrue("Vlen size should be positive (hvl_t struct)", size > 0);
}
// ============================================================================
// H5T Opaque Advanced Tests
// ============================================================================
@Test
public void testH5Topaque_create()
{
System.out.print(testname.getMethodName());
// Create opaque type of 128 bytes
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), 128);
assertTrue("Opaque creation failed", isValidId(H5tid));
assertEquals("Should be opaque class", hdf5_h.H5T_OPAQUE(), hdf5_h.H5Tget_class(H5tid));
assertEquals("Size should be 128", 128, hdf5_h.H5Tget_size(H5tid));
}
@Test
public void testH5Topaque_set_get_tag()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), 64);
// Set tag
String tag = "binary_blob_v1.0";
int result = hdf5_h.H5Tset_tag(H5tid, arena.allocateFrom(tag));
assertEquals("H5Tset_tag failed", 0, result);
// Get tag
MemorySegment tagPtr = hdf5_h.H5Tget_tag(H5tid);
assertNotNull("Tag pointer should not be null", tagPtr);
String retrievedTag = tagPtr.getString(0);
assertEquals("Tag should match", tag, retrievedTag);
hdf5_h.H5free_memory(tagPtr);
}
}
@Test
public void testH5Topaque_different_sizes()
{
System.out.print(testname.getMethodName());
// Test various opaque sizes
int[] sizes = {1, 16, 256, 1024};
for (int size : sizes) {
long tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), size);
assertTrue("Opaque creation failed for size " + size, isValidId(tid));
assertEquals("Size should match", size, hdf5_h.H5Tget_size(tid));
hdf5_h.H5Tclose(tid);
}
}
// ============================================================================
// H5T Bitfield Tests
// ============================================================================
@Test
public void testH5Tbitfield_create()
{
System.out.print(testname.getMethodName());
// Bitfield types cannot be created with H5Tcreate, must copy from predefined type
// Copy from a standard bitfield type and resize
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B32LE_g());
assertTrue("Bitfield copy failed", isValidId(H5tid));
// Verify it's a bitfield type
assertEquals("Should be bitfield class", hdf5_h.H5T_BITFIELD(), hdf5_h.H5Tget_class(H5tid));
// Resize to 4 bytes if needed
int result = hdf5_h.H5Tset_size(H5tid, 4);
assertTrue("H5Tset_size should succeed", isSuccess(result));
assertEquals("Size should be 4", 4, hdf5_h.H5Tget_size(H5tid));
}
@Test
public void testH5Tbitfield_predefined()
{
System.out.print(testname.getMethodName());
// Test predefined bitfield types
long tid1 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B8LE_g());
assertTrue("H5T_STD_B8LE copy failed", isValidId(tid1));
assertEquals("Should be 1 byte", 1, hdf5_h.H5Tget_size(tid1));
hdf5_h.H5Tclose(tid1);
long tid2 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B16LE_g());
assertTrue("H5T_STD_B16LE copy failed", isValidId(tid2));
assertEquals("Should be 2 bytes", 2, hdf5_h.H5Tget_size(tid2));
hdf5_h.H5Tclose(tid2);
long tid3 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B32LE_g());
assertTrue("H5T_STD_B32LE copy failed", isValidId(tid3));
assertEquals("Should be 4 bytes", 4, hdf5_h.H5Tget_size(tid3));
hdf5_h.H5Tclose(tid3);
long tid4 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B64LE_g());
assertTrue("H5T_STD_B64LE copy failed", isValidId(tid4));
assertEquals("Should be 8 bytes", 8, hdf5_h.H5Tget_size(tid4));
hdf5_h.H5Tclose(tid4);
}
// ============================================================================
// H5T Complex Number Tests (HDF5 2.0 feature)
// ============================================================================
@Test
public void testH5Tcomplex_float()
{
System.out.print(testname.getMethodName());
// Create complex float type
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F32LE_g());
assertTrue("Complex float creation failed", isValidId(H5tid));
// Complex float should be 8 bytes (2 * 4-byte floats)
long size = hdf5_h.H5Tget_size(H5tid);
assertEquals("Complex float should be 8 bytes", 8, size);
// Complex types have their own class (H5T_COMPLEX = 11)
assertEquals("Should be complex class", hdf5_h.H5T_COMPLEX(), hdf5_h.H5Tget_class(H5tid));
}
@Test
public void testH5Tcomplex_double()
{
System.out.print(testname.getMethodName());
// Create complex double type
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("Complex double creation failed", isValidId(H5tid));
// Complex double should be 16 bytes (2 * 8-byte doubles)
long size = hdf5_h.H5Tget_size(H5tid);
assertEquals("Complex double should be 16 bytes", 16, size);
}
@Test
public void testH5Tcomplex_get_parts()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F64LE_g());
// Get real and imaginary part types
long realType = hdf5_h.H5Tget_super(H5tid);
assertTrue("Real type should be valid", isValidId(realType));
// Verify it's a double
int equal = hdf5_h.H5Tequal(realType, hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("Real part should be double", equal > 0);
hdf5_h.H5Tclose(realType);
}
// ============================================================================
// H5T Type Conversion Advanced Tests
// ============================================================================
@Test
public void testH5Tconvert_with_buffer()
{
// Skip on Windows - FFM memory layout issue with conversion buffers
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Convert int array to float array
int nelem = 5;
MemorySegment intData = arena.allocateFrom(hdf5_h.C_INT, 10, 20, 30, 40, 50);
long srcType = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
long dstType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
// Convert in place
int result =
hdf5_h.H5Tconvert(srcType, dstType, nelem, intData, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
assertEquals("H5Tconvert failed", 0, result);
// Data should now be floats (we can't easily verify values due to overlay)
hdf5_h.H5Tclose(srcType);
hdf5_h.H5Tclose(dstType);
}
}
@Test
public void testH5Tconvert_compound_subset()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create source compound: {int x, int y, int z}
long srcType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("x"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("y"), 4, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("z"), 8, hdf5_h.H5T_STD_I32LE_g());
// Create dest compound: {int x, int z} - subset
long dstType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 8);
hdf5_h.H5Tinsert(dstType, arena.allocateFrom("x"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(dstType, arena.allocateFrom("z"), 4, hdf5_h.H5T_STD_I32LE_g());
// This tests subset conversion capability
assertTrue("Source compound type valid", isValidId(srcType));
assertTrue("Dest compound type valid", isValidId(dstType));
hdf5_h.H5Tclose(srcType);
hdf5_h.H5Tclose(dstType);
}
}
@Test
public void testH5Tcompiler_conv()
{
System.out.print(testname.getMethodName());
// Check if compiler conversion path exists between int and float
int result = hdf5_h.H5Tcompiler_conv(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g());
// Result > 0 means compiler conversion exists, 0 means library conversion only
assertTrue("Conversion check should succeed", result >= 0);
}
// ============================================================================
// H5T Type Commit Tests
// ============================================================================
@Test
public void testH5Tcommit2()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create a test file
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_commit.h5"), hdf5_h.H5F_ACC_TRUNC(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("File creation failed", isValidId(file_id));
// Create compound type
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("a"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("b"), 4, hdf5_h.H5T_IEEE_F32LE_g());
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("c"), 8, hdf5_h.H5T_STD_I32LE_g());
// Commit the type
int result = hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("mytype"), H5tid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertEquals("H5Tcommit2 failed", 0, result);
// Verify it's committed
int committed = hdf5_h.H5Tcommitted(H5tid);
assertTrue("Type should be committed", committed > 0);
hdf5_h.H5Fclose(file_id);
}
}
@Test
public void testH5Tcommit_anon()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_commit_anon.h5"), hdf5_h.H5F_ACC_TRUNC(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
// Create enum type
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
MemorySegment val = arena.allocate(hdf5_h.C_INT, 0);
hdf5_h.H5Tenum_insert(H5tid, arena.allocateFrom("RED"), val);
// Commit anonymously (no name)
int result = hdf5_h.H5Tcommit_anon(file_id, H5tid, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertEquals("H5Tcommit_anon failed", 0, result);
// Verify it's committed
assertTrue("Type should be committed", hdf5_h.H5Tcommitted(H5tid) > 0);
hdf5_h.H5Fclose(file_id);
}
}
@Test
public void testH5Topen2()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_open.h5"), hdf5_h.H5F_ACC_TRUNC(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
// Create and commit a type
long tid1 = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("double_type"), tid1, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
hdf5_h.H5Tclose(tid1);
// Open the committed type
H5tid = hdf5_h.H5Topen2(file_id, arena.allocateFrom("double_type"), hdf5_h.H5P_DEFAULT());
assertTrue("H5Topen2 failed", isValidId(H5tid));
// Verify it's committed
assertTrue("Opened type should be committed", hdf5_h.H5Tcommitted(H5tid) > 0);
// Verify it's equal to double
int equal = hdf5_h.H5Tequal(H5tid, hdf5_h.H5T_IEEE_F64LE_g());
assertTrue("Should be equal to double", equal > 0);
hdf5_h.H5Fclose(file_id);
}
}
@Test
public void testH5Tget_create_plist()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_get_cplist.h5"), hdf5_h.H5F_ACC_TRUNC(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
// Create type with custom creation properties
long tcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATATYPE_CREATE_ID_g());
assertTrue("TCPL creation failed", isValidId(tcpl));
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("int_type"), H5tid, hdf5_h.H5P_DEFAULT(), tcpl,
hdf5_h.H5P_DEFAULT());
// Get creation property list
long retrieved_tcpl = hdf5_h.H5Tget_create_plist(H5tid);
assertTrue("H5Tget_create_plist failed", isValidId(retrieved_tcpl));
hdf5_h.H5Pclose(retrieved_tcpl);
hdf5_h.H5Pclose(tcpl);
hdf5_h.H5Fclose(file_id);
}
}
// ============================================================================
// H5T Type Detection and Query Tests
// ============================================================================
@Test
public void testH5Tdetect_class_in_compound()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create compound with int and float
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("i"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("f"), 4, hdf5_h.H5T_IEEE_F32LE_g());
// Detect integer class
int hasInt = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_INTEGER());
assertTrue("Should detect integer class", hasInt > 0);
// Detect float class
int hasFloat = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_FLOAT());
assertTrue("Should detect float class", hasFloat > 0);
// Should not detect string class
int hasString = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_STRING());
assertFalse("Should not detect string class", hasString > 0);
hdf5_h.H5Tclose(compoundType);
}
}
@Test
public void testH5Tdetect_class_integer()
{
System.out.print(testname.getMethodName());
int result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_INTEGER());
assertTrue("H5T_STD_I32LE should be integer class", result > 0);
result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_FLOAT());
assertFalse("H5T_STD_I32LE should not be float class", result > 0);
}
@Test
public void testH5Tdetect_class_float()
{
System.out.print(testname.getMethodName());
int result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_FLOAT());
assertTrue("Native double should be float class", result > 0);
result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_INTEGER());
assertFalse("Native double should not be integer class", result > 0);
}
// ============================================================================
// H5T Type Modification Tests
// ============================================================================
@Test
public void testH5Tpack_compound()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create compound with padding
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("a"), 0, hdf5_h.H5T_STD_I8LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("b"), 4, hdf5_h.H5T_STD_I32LE_g());
long sizeBefore = hdf5_h.H5Tget_size(compoundType);
// Pack to remove padding
int result = hdf5_h.H5Tpack(compoundType);
assertEquals("H5Tpack failed", 0, result);
long sizeAfter = hdf5_h.H5Tget_size(compoundType);
assertTrue("Size should be smaller after packing", sizeAfter <= sizeBefore);
// Should be 1 (char) + 4 (int) = 5 bytes
assertEquals("Packed size should be 5", 5, sizeAfter);
hdf5_h.H5Tclose(compoundType);
}
}
@Test
public void testH5Tlock()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
// Lock the type
int result = hdf5_h.H5Tlock(H5tid);
assertEquals("H5Tlock failed", 0, result);
// Try to modify locked type - should fail
result = hdf5_h.H5Tset_size(H5tid, 8);
assertTrue("Modifying locked type should fail", result < 0);
}
// ============================================================================
// H5T String Character Set Tests
// ============================================================================
@Test
public void testH5Tset_get_cset_ascii()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
// Set to ASCII
int result = hdf5_h.H5Tset_cset(H5tid, hdf5_h.H5T_CSET_ASCII());
assertEquals("H5Tset_cset ASCII failed", 0, result);
int cset = hdf5_h.H5Tget_cset(H5tid);
assertEquals("Character set should be ASCII", hdf5_h.H5T_CSET_ASCII(), cset);
}
@Test
public void testH5Tset_get_cset_utf8()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
// Set to UTF-8
int result = hdf5_h.H5Tset_cset(H5tid, hdf5_h.H5T_CSET_UTF8());
assertEquals("H5Tset_cset UTF8 failed", 0, result);
int cset = hdf5_h.H5Tget_cset(H5tid);
assertEquals("Character set should be UTF8", hdf5_h.H5T_CSET_UTF8(), cset);
}
// ============================================================================
// H5T Reference Type Tests
// ============================================================================
@Test
public void testH5T_STD_REF()
{
System.out.print(testname.getMethodName());
long tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_g());
assertTrue("H5T_STD_REF copy failed", isValidId(tid));
// Verify it's a reference type
assertEquals("Should be reference class", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(tid));
hdf5_h.H5Tclose(tid);
}
@Test
public void testH5T_reference_types()
{
System.out.print(testname.getMethodName());
// Test object reference
long objRef = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_OBJ_g());
assertTrue("Object reference copy failed", isValidId(objRef));
assertEquals("Should be reference", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(objRef));
hdf5_h.H5Tclose(objRef);
// Test dataset region reference
long regRef = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_DSETREG_g());
assertTrue("Region reference copy failed", isValidId(regRef));
assertEquals("Should be reference", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(regRef));
hdf5_h.H5Tclose(regRef);
}
// ============================================================================
// H5T Array Type Advanced Tests
// ============================================================================
@Test
public void testH5Tarray_equal()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 10);
long tid1 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
// Should be equal
int equal = hdf5_h.H5Tequal(tid1, tid2);
assertTrue("Identical arrays should be equal", equal > 0);
hdf5_h.H5Tclose(tid1);
hdf5_h.H5Tclose(tid2);
// Different dimensions should not be equal
MemorySegment dims2 = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 11);
long tid3 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
long tid4 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims2);
equal = hdf5_h.H5Tequal(tid3, tid4);
assertFalse("Different dimension arrays should not be equal", equal > 0);
hdf5_h.H5Tclose(tid3);
hdf5_h.H5Tclose(tid4);
}
}
@Test
public void testH5Tarray_multidimensional_access()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Create 4D array [2][3][4][5]
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 2, 3, 4, 5);
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 4, dims);
// Verify rank
assertEquals("Should be 4D", 4, hdf5_h.H5Tget_array_ndims(H5tid));
// Get all dimensions
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 4);
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
assertEquals("Dim[0]", 2, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
assertEquals("Dim[1]", 3, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
assertEquals("Dim[2]", 4, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
assertEquals("Dim[3]", 5, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 3));
// Size should be 2*3*4*5*8 = 960 bytes (8 bytes per double)
assertEquals("Size should be 960", 960, hdf5_h.H5Tget_size(H5tid));
}
}
// ============================================================================
// H5T Enum Type Advanced Tests
// ============================================================================
@Test
public void testH5Tenum_with_different_base_types()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
// Enum based on byte
long enumByte = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I8LE_g());
MemorySegment val = arena.allocate(hdf5_h.C_CHAR, (byte)1);
hdf5_h.H5Tenum_insert(enumByte, arena.allocateFrom("ONE"), val);
assertEquals("Size should be 1", 1, hdf5_h.H5Tget_size(enumByte));
hdf5_h.H5Tclose(enumByte);
// Enum based on short
long enumShort = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I16LE_g());
MemorySegment val2 = arena.allocate(hdf5_h.C_SHORT, (short)1);
hdf5_h.H5Tenum_insert(enumShort, arena.allocateFrom("ONE"), val2);
assertEquals("Size should be 2", 2, hdf5_h.H5Tget_size(enumShort));
hdf5_h.H5Tclose(enumShort);
// Enum based on long
long enumLong = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I64LE_g());
MemorySegment val3 = arena.allocate(ValueLayout.JAVA_LONG, 1L);
hdf5_h.H5Tenum_insert(enumLong, arena.allocateFrom("ONE"), val3);
assertEquals("Size should be 8", 8, hdf5_h.H5Tget_size(enumLong));
hdf5_h.H5Tclose(enumLong);
}
}
@Test
public void testH5Tenum_get_member_index()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
// Insert several members
String[] names = {"ALPHA", "BETA", "GAMMA", "DELTA"};
for (int i = 0; i < names.length; i++) {
MemorySegment val = allocateInt(arena);
setInt(val, i * 100);
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, names[i]), val);
}
// Get member index
int idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "BETA"));
assertEquals("BETA should be at index 1", 1, idx);
idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "DELTA"));
assertEquals("DELTA should be at index 3", 3, idx);
// Non-existent member
idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "EPSILON"));
assertTrue("Non-existent member should return negative", idx < 0);
}
}
// ============================================================================
// H5T Compound Type Advanced Tests
// ============================================================================
@Test
public void testH5Tget_member_index_compound()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field1"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field2"), 4, hdf5_h.H5T_IEEE_F32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field3"), 8, hdf5_h.H5T_IEEE_F64LE_g());
int idx = hdf5_h.H5Tget_member_index(compoundType, arena.allocateFrom("field2"));
assertEquals("field2 should be at index 1", 1, idx);
idx = hdf5_h.H5Tget_member_index(compoundType, arena.allocateFrom("field3"));
assertEquals("field3 should be at index 2", 2, idx);
hdf5_h.H5Tclose(compoundType);
}
}
@Test
public void testH5Tget_member_class()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 13);
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("i"), 0, hdf5_h.H5T_STD_I32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("f"), 4, hdf5_h.H5T_IEEE_F32LE_g());
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("c"), 8, hdf5_h.H5T_STD_I8LE_g());
int class0 = hdf5_h.H5Tget_member_class(compoundType, 0);
assertEquals("Member 0 should be integer", hdf5_h.H5T_INTEGER(), class0);
int class1 = hdf5_h.H5Tget_member_class(compoundType, 1);
assertEquals("Member 1 should be float", hdf5_h.H5T_FLOAT(), class1);
int class2 = hdf5_h.H5Tget_member_class(compoundType, 2);
assertEquals("Member 2 should be integer (char)", hdf5_h.H5T_INTEGER(), class2);
hdf5_h.H5Tclose(compoundType);
}
}
// ============================================================================
// H5T Numeric Type Property Tests
// ============================================================================
@Test
public void testH5Tset_size_grow()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I16LE_g());
assertEquals("Short should be 2 bytes", 2, hdf5_h.H5Tget_size(H5tid));
// Grow to 8 bytes
int result = hdf5_h.H5Tset_size(H5tid, 8);
assertEquals("H5Tset_size grow failed", 0, result);
assertEquals("Size should be 8", 8, hdf5_h.H5Tget_size(H5tid));
}
@Test
public void testH5Tset_size_shrink()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I64LE_g());
assertEquals("Long should be 8 bytes", 8, hdf5_h.H5Tget_size(H5tid));
// Shrink to 4 bytes
int result = hdf5_h.H5Tset_size(H5tid, 4);
assertEquals("H5Tset_size shrink failed", 0, result);
assertEquals("Size should be 4", 4, hdf5_h.H5Tget_size(H5tid));
}
@Test
public void testH5Tset_precision_less_than_size()
{
System.out.print(testname.getMethodName());
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
// Set precision to 24 bits (less than 32-bit int)
int result = hdf5_h.H5Tset_precision(H5tid, 24);
assertEquals("H5Tset_precision failed", 0, result);
long precision = hdf5_h.H5Tget_precision(H5tid);
assertEquals("Precision should be 24", 24, precision);
}
@Test
public void testH5Tget_native_type_integer()
{
// Skip on Windows - FFM memory layout issue with native type mapping
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
System.out.print(testname.getMethodName());
// Get native type for a standard type
long nativeType = hdf5_h.H5Tget_native_type(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_DIR_ASCEND());
assertTrue("Native type should be valid", isValidId(nativeType));
assertEquals("Should be integer class", hdf5_h.H5T_INTEGER(), hdf5_h.H5Tget_class(nativeType));
hdf5_h.H5Tclose(nativeType);
}
@Test
public void testH5Tget_native_type_float()
{
System.out.print(testname.getMethodName());
long nativeType = hdf5_h.H5Tget_native_type(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_DIR_DESCEND());
assertTrue("Native type should be valid", isValidId(nativeType));
assertEquals("Should be float class", hdf5_h.H5T_FLOAT(), hdf5_h.H5Tget_class(nativeType));
hdf5_h.H5Tclose(nativeType);
}
}
+303
View File
@@ -0,0 +1,303 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 VOL (Virtual Object Layer) operations.
*
* NOTE: These tests focus on the native VOL connector only.
* Custom VOL connectors require external plugins and specialized setup.
*/
public class TestH5VLffm {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "test_H5VLffm.h5";
long H5fid = hdf5_h.H5I_INVALID_HID();
@Before
public void createH5file()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment filename = stringToSegment(arena, H5_FILE);
H5fid = hdf5_h.H5Fcreate(filename, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT());
assertTrue("H5Fcreate failed", isValidId(H5fid));
}
}
@After
public void deleteH5file()
{
if (isValidId(H5fid)) {
closeQuietly(H5fid, hdf5_h::H5Fclose);
H5fid = hdf5_h.H5I_INVALID_HID();
}
System.out.println();
}
/**
* Test H5VLis_connector_registered_by_name for native VOL connector
*/
@Test
public void testH5VLis_connector_registered_by_name()
{
try (Arena arena = Arena.ofConfined()) {
// Native VOL connector should be registered
MemorySegment name = stringToSegment(arena, "native");
int result = hdf5_h.H5VLis_connector_registered_by_name(name);
assertTrue("Native VOL connector should be registered", result > 0);
// Non-existent connector should not be registered
MemorySegment fake_name = stringToSegment(arena, "nonexistent_connector");
result = hdf5_h.H5VLis_connector_registered_by_name(fake_name);
assertEquals("Non-existent connector should not be registered", 0, result);
}
}
/**
* Test H5VLis_connector_registered_by_value for native VOL connector
*/
@Test
public void testH5VLis_connector_registered_by_value()
{
// Native VOL connector (H5_VOL_NATIVE = 0) should be registered
int result = hdf5_h.H5VLis_connector_registered_by_value(hdf5_h.H5_VOL_NATIVE());
assertTrue("Native VOL connector should be registered", result > 0);
// Invalid connector value should not be registered
result = hdf5_h.H5VLis_connector_registered_by_value(9999);
assertEquals("Invalid connector value should not be registered", 0, result);
}
/**
* Test H5VLget_connector_id for file object
*/
@Test
public void testH5VLget_connector_id()
{
long connector_id = hdf5_h.H5VLget_connector_id(H5fid);
assertTrue("Should get valid connector ID for file", isValidId(connector_id));
// Close the connector ID
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
/**
* Test H5VLget_connector_id_by_name for native connector
*/
@Test
public void testH5VLget_connector_id_by_name()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment name = stringToSegment(arena, "native");
long connector_id = hdf5_h.H5VLget_connector_id_by_name(name);
assertTrue("Should get valid connector ID by name", isValidId(connector_id));
// Close the connector ID
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
}
/**
* Test H5VLget_connector_id_by_value for native connector
*/
@Test
public void testH5VLget_connector_id_by_value()
{
long connector_id = hdf5_h.H5VLget_connector_id_by_value(hdf5_h.H5_VOL_NATIVE());
assertTrue("Should get valid connector ID by value", isValidId(connector_id));
// Close the connector ID
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
/**
* Test H5VLget_connector_name for file object
*/
@Test
public void testH5VLget_connector_name()
{
try (Arena arena = Arena.ofConfined()) {
// First call to get the size
long size = hdf5_h.H5VLget_connector_name(H5fid, MemorySegment.NULL, 0);
assertTrue("Should get connector name size", size > 0);
// Allocate buffer and get the name
MemorySegment name_buf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
long actual_size = hdf5_h.H5VLget_connector_name(H5fid, name_buf, size + 1);
assertEquals("Sizes should match", size, actual_size);
// Verify it's the native connector
String connector_name = segmentToString(name_buf);
assertEquals("Should be native VOL connector", "native", connector_name);
}
}
/**
* Test H5VLobject_is_native for file object
*/
@Test
public void testH5VLobject_is_native()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment is_native = arena.allocate(ValueLayout.JAVA_BOOLEAN);
int result = hdf5_h.H5VLobject_is_native(H5fid, is_native);
assertEquals("H5VLobject_is_native should succeed", 0, result);
// File should be using native VOL
boolean native_vol = is_native.get(ValueLayout.JAVA_BOOLEAN, 0);
assertTrue("File should be using native VOL connector", native_vol);
}
}
/**
* Test H5VLregister_connector_by_name and H5VLunregister_connector
*
* Note: This tests registration/unregistration of already-registered
* native connector to verify the API works.
*/
@Test
public void testH5VLregister_and_unregister_connector_by_name()
{
try (Arena arena = Arena.ofConfined()) {
// Register the native connector (it's already registered, but this verifies API)
MemorySegment name = stringToSegment(arena, "native");
long connector_id = hdf5_h.H5VLregister_connector_by_name(name, hdf5_h.H5P_DEFAULT());
assertTrue("Should get valid connector ID", isValidId(connector_id));
// Verify it's registered
int is_registered = hdf5_h.H5VLis_connector_registered_by_name(name);
assertTrue("Connector should be registered", is_registered > 0);
// Note: Cannot unregister the native connector as it's always needed
// Just close the ID we got
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
}
/**
* Test H5VLregister_connector_by_value
*/
@Test
public void testH5VLregister_connector_by_value()
{
// Register native connector by value
long connector_id =
hdf5_h.H5VLregister_connector_by_value(hdf5_h.H5_VOL_NATIVE(), hdf5_h.H5P_DEFAULT());
assertTrue("Should get valid connector ID", isValidId(connector_id));
// Close the connector ID
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
/**
* Test getting connector ID multiple times and closing
*/
@Test
public void testH5VLclose()
{
// Get connector ID for file
long connector_id1 = hdf5_h.H5VLget_connector_id(H5fid);
assertTrue("Should get valid connector ID", isValidId(connector_id1));
// Get another reference
long connector_id2 = hdf5_h.H5VLget_connector_id(H5fid);
assertTrue("Should get valid connector ID", isValidId(connector_id2));
// Close both
int result = hdf5_h.H5VLclose(connector_id1);
assertEquals("H5VLclose should succeed", 0, result);
result = hdf5_h.H5VLclose(connector_id2);
assertEquals("H5VLclose should succeed", 0, result);
}
/**
* Test VOL connector with dataset object
*/
@Test
public void testH5VLget_connector_id_for_dataset()
{
long dset_id = hdf5_h.H5I_INVALID_HID();
try (Arena arena = Arena.ofConfined()) {
// Create a simple dataset
MemorySegment dsetname = stringToSegment(arena, "dataset");
long sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
assertTrue("H5Screate failed", isValidId(sid));
dset_id = hdf5_h.H5Dcreate2(H5fid, dsetname, hdf5_h.H5T_NATIVE_INT_g(), sid, hdf5_h.H5P_DEFAULT(),
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
assertTrue("H5Dcreate2 failed", isValidId(dset_id));
closeQuietly(sid, hdf5_h::H5Sclose);
// Get connector ID for dataset
long connector_id = hdf5_h.H5VLget_connector_id(dset_id);
assertTrue("Should get valid connector ID for dataset", isValidId(connector_id));
// Verify it's native
MemorySegment is_native = arena.allocate(ValueLayout.JAVA_BOOLEAN);
int result = hdf5_h.H5VLobject_is_native(dset_id, is_native);
assertEquals("H5VLobject_is_native should succeed", 0, result);
assertTrue("Dataset should be using native VOL", is_native.get(ValueLayout.JAVA_BOOLEAN, 0));
// Close connector ID
closeQuietly(connector_id, hdf5_h::H5VLclose);
}
finally {
closeQuietly(dset_id, hdf5_h::H5Dclose);
}
}
/**
* Test H5VLquery_optional (basic test with native VOL)
*
* Note: This is a simplified test as full optional operation testing
* requires detailed knowledge of VOL connector capabilities.
*/
@Test
public void testH5VLquery_optional()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment flags = allocateLong(arena);
// Query optional operations for file object
// Using subcls=0 (H5VL_SUBCLS_FILE) and opt_type=0 as basic test
int result = hdf5_h.H5VLquery_optional(H5fid, 0, 0, flags);
// Result depends on VOL connector support
// We just verify the API works (returns >= 0 for success or -1 for not supported)
assertTrue("H5VLquery_optional should return valid result", result >= -1);
}
}
}
+397
View File
@@ -0,0 +1,397 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for HDF5 Filter (H5Z) operations.
*
* NOTE: These tests focus on built-in HDF5 filters.
* Custom filter registration requires C-level callbacks and is not easily testable from Java FFM.
*/
public class TestH5Zffm {
@Rule
public TestName testname = new TestName();
/**
* Test H5Zfilter_avail for built-in filters
*/
@Test
public void testH5Zfilter_avail_deflate()
{
System.out.print(testname.getMethodName());
// Test DEFLATE (gzip) filter - should always be available
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_DEFLATE());
assertTrue("DEFLATE filter should be available", result > 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for shuffle filter
*/
@Test
public void testH5Zfilter_avail_shuffle()
{
System.out.print(testname.getMethodName());
// Test SHUFFLE filter - should always be available
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_SHUFFLE());
assertTrue("SHUFFLE filter should be available", result > 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for fletcher32 filter
*/
@Test
public void testH5Zfilter_avail_fletcher32()
{
System.out.print(testname.getMethodName());
// Test FLETCHER32 filter - should always be available
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_FLETCHER32());
assertTrue("FLETCHER32 filter should be available", result > 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for szip filter
*/
@Test
public void testH5Zfilter_avail_szip()
{
System.out.print(testname.getMethodName());
// Test SZIP filter - may or may not be available depending on build
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_SZIP());
// Result should be either 1 (available) or 0 (not available), never negative
assertTrue("SZIP filter availability check should not error", result >= 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for nbit filter
*/
@Test
public void testH5Zfilter_avail_nbit()
{
System.out.print(testname.getMethodName());
// Test NBIT filter - should always be available
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_NBIT());
assertTrue("NBIT filter should be available", result > 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for scaleoffset filter
*/
@Test
public void testH5Zfilter_avail_scaleoffset()
{
System.out.print(testname.getMethodName());
// Test SCALEOFFSET filter - should always be available
int result = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_SCALEOFFSET());
assertTrue("SCALEOFFSET filter should be available", result > 0);
System.out.println();
}
/**
* Test H5Zfilter_avail for non-existent filter
*/
@Test
public void testH5Zfilter_avail_invalid()
{
System.out.print(testname.getMethodName());
// Test with invalid filter ID - should return 0 (not available)
int result = hdf5_h.H5Zfilter_avail(9999);
assertEquals("Non-existent filter should not be available", 0, result);
System.out.println();
}
/**
* Test H5Zget_filter_info for deflate filter
*/
@Test
public void testH5Zget_filter_info_deflate()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for DEFLATE
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_DEFLATE(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// Verify encode and decode are enabled
int encodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertTrue("DEFLATE filter should support encoding", encodeEnabled != 0);
assertTrue("DEFLATE filter should support decoding", decodeEnabled != 0);
}
System.out.println();
}
/**
* Test H5Zget_filter_info for shuffle filter
*/
@Test
public void testH5Zget_filter_info_shuffle()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for SHUFFLE
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_SHUFFLE(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// Verify encode and decode are enabled
int encodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertTrue("SHUFFLE filter should support encoding", encodeEnabled != 0);
assertTrue("SHUFFLE filter should support decoding", decodeEnabled != 0);
}
System.out.println();
}
/**
* Test H5Zget_filter_info for fletcher32 filter
*/
@Test
public void testH5Zget_filter_info_fletcher32()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for FLETCHER32
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_FLETCHER32(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// Verify encode and decode are enabled
int encodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertTrue("FLETCHER32 filter should support encoding", encodeEnabled != 0);
assertTrue("FLETCHER32 filter should support decoding", decodeEnabled != 0);
}
System.out.println();
}
/**
* Test H5Zget_filter_info for szip filter (if available)
*/
@Test
public void testH5Zget_filter_info_szip()
{
System.out.print(testname.getMethodName());
// Check if SZIP is available first
int available = hdf5_h.H5Zfilter_avail(hdf5_h.H5Z_FILTER_SZIP());
if (available > 0) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for SZIP
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_SZIP(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// SZIP may support only decoding, only encoding, or both
// Just verify flags are set to something valid
assertTrue("SZIP filter should have some capabilities", flags >= 0);
}
}
System.out.println();
}
/**
* Test H5Zget_filter_info for nbit filter
*/
@Test
public void testH5Zget_filter_info_nbit()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for NBIT
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_NBIT(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// Verify encode and decode are enabled
int encodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertTrue("NBIT filter should support encoding", encodeEnabled != 0);
assertTrue("NBIT filter should support decoding", decodeEnabled != 0);
}
System.out.println();
}
/**
* Test H5Zget_filter_info for scaleoffset filter
*/
@Test
public void testH5Zget_filter_info_scaleoffset()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Get filter info for SCALEOFFSET
int result = hdf5_h.H5Zget_filter_info(hdf5_h.H5Z_FILTER_SCALEOFFSET(), flagsSeg);
assertEquals("H5Zget_filter_info should succeed", 0, result);
int flags = flagsSeg.get(ValueLayout.JAVA_INT, 0);
// Verify encode and decode are enabled
int encodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeEnabled = flags & hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertTrue("SCALEOFFSET filter should support encoding", encodeEnabled != 0);
assertTrue("SCALEOFFSET filter should support decoding", decodeEnabled != 0);
}
System.out.println();
}
/**
* Test H5Zget_filter_info with invalid filter ID
*/
@Test
public void testH5Zget_filter_info_invalid()
{
System.out.print(testname.getMethodName());
try (Arena arena = Arena.ofConfined()) {
MemorySegment flagsSeg = arena.allocate(ValueLayout.JAVA_INT);
// Try to get info for non-existent filter
int result = hdf5_h.H5Zget_filter_info(9999, flagsSeg);
// Should return error (negative value)
assertTrue("Getting info for invalid filter should fail", result < 0);
}
System.out.println();
}
/**
* Test filter ID constants
*/
@Test
public void testH5Z_filter_constants()
{
System.out.print(testname.getMethodName());
// Verify standard filter IDs have expected values
assertEquals("H5Z_FILTER_NONE should be 0", 0, hdf5_h.H5Z_FILTER_NONE());
assertEquals("H5Z_FILTER_DEFLATE should be 1", 1, hdf5_h.H5Z_FILTER_DEFLATE());
assertEquals("H5Z_FILTER_SHUFFLE should be 2", 2, hdf5_h.H5Z_FILTER_SHUFFLE());
assertEquals("H5Z_FILTER_FLETCHER32 should be 3", 3, hdf5_h.H5Z_FILTER_FLETCHER32());
assertEquals("H5Z_FILTER_SZIP should be 4", 4, hdf5_h.H5Z_FILTER_SZIP());
assertEquals("H5Z_FILTER_NBIT should be 5", 5, hdf5_h.H5Z_FILTER_NBIT());
assertEquals("H5Z_FILTER_SCALEOFFSET should be 6", 6, hdf5_h.H5Z_FILTER_SCALEOFFSET());
// Verify reserved value
assertEquals("H5Z_FILTER_RESERVED should be 256", 256, hdf5_h.H5Z_FILTER_RESERVED());
System.out.println();
}
/**
* Test filter config flag constants
*/
@Test
public void testH5Z_filter_config_flags()
{
System.out.print(testname.getMethodName());
// Verify config flag values
int encodeFlag = hdf5_h.H5Z_FILTER_CONFIG_ENCODE_ENABLED();
int decodeFlag = hdf5_h.H5Z_FILTER_CONFIG_DECODE_ENABLED();
assertEquals("H5Z_FILTER_CONFIG_ENCODE_ENABLED should be 0x0001", 0x0001, encodeFlag);
assertEquals("H5Z_FILTER_CONFIG_DECODE_ENABLED should be 0x0002", 0x0002, decodeFlag);
System.out.println();
}
/**
* Test all built-in filters are available
*/
@Test
public void testH5Z_all_builtin_filters()
{
System.out.print(testname.getMethodName());
// Test all built-in filters (except SZIP which may not be available)
int[] requiredFilters = {hdf5_h.H5Z_FILTER_DEFLATE(), hdf5_h.H5Z_FILTER_SHUFFLE(),
hdf5_h.H5Z_FILTER_FLETCHER32(), hdf5_h.H5Z_FILTER_NBIT(),
hdf5_h.H5Z_FILTER_SCALEOFFSET()};
for (int filter : requiredFilters) {
int available = hdf5_h.H5Zfilter_avail(filter);
assertTrue("Filter " + filter + " should be available", available > 0);
}
System.out.println();
}
}
+298
View File
@@ -0,0 +1,298 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package jtest;
import static org.junit.Assert.*;
import static jtest.FfmTestSupport.*;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import org.hdfgroup.javahdf5.hdf5_h;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
/**
* FFM-only tests for general HDF5 library operations (H5public.h APIs).
*
* This test class covers general library initialization, cleanup, version checking,
* memory management, and library configuration APIs.
*/
public class TestH5ffm {
@Rule
public TestName testname = new TestName();
@Before
public void setup()
{
System.out.print(testname.getMethodName());
// Ensure library is initialized
hdf5_h.H5open();
}
@After
public void cleanup()
{
System.out.println();
}
// ================================
// Library Initialization and Cleanup
// ================================
@Test
public void testH5open()
{
// H5open is idempotent - calling multiple times should succeed
int result = hdf5_h.H5open();
assertTrue("H5open should succeed", isSuccess(result));
result = hdf5_h.H5open();
assertTrue("H5open should be idempotent", isSuccess(result));
}
@Test
public void testH5close()
{
// H5close decrements reference count but doesn't actually close if other references exist
// This test just verifies the API is callable
int result = hdf5_h.H5close();
assertTrue("H5close should return valid code", result >= -1);
// Re-open to ensure library is available for other tests
hdf5_h.H5open();
}
@Test
public void testH5garbage_collect()
{
int result = hdf5_h.H5garbage_collect();
assertTrue("H5garbage_collect should succeed", isSuccess(result));
}
@Test
public void testH5dont_atexit()
{
// Note: This affects cleanup behavior, test just verifies API is callable
int result = hdf5_h.H5dont_atexit();
assertTrue("H5dont_atexit should succeed", isSuccess(result));
}
// ================================
// Version Information
// ================================
@Test
public void testH5get_libversion()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment majnum = allocateInt(arena);
MemorySegment minnum = allocateInt(arena);
MemorySegment relnum = allocateInt(arena);
int result = hdf5_h.H5get_libversion(majnum, minnum, relnum);
assertTrue("H5get_libversion failed", isSuccess(result));
int major = getInt(majnum);
int minor = getInt(minnum);
int release = getInt(relnum);
assertTrue("Major version should be >= 1", major >= 1);
assertTrue("Minor version should be >= 0", minor >= 0);
assertTrue("Release version should be >= 0", release >= 0);
System.out.print(" [HDF5 " + major + "." + minor + "." + release + "]");
}
}
@Test
public void testH5check_version()
{
try (Arena arena = Arena.ofConfined()) {
// Get current version
MemorySegment majnum = allocateInt(arena);
MemorySegment minnum = allocateInt(arena);
MemorySegment relnum = allocateInt(arena);
hdf5_h.H5get_libversion(majnum, minnum, relnum);
int major = getInt(majnum);
int minor = getInt(minnum);
int release = getInt(relnum);
// Check against current version should succeed
int result = hdf5_h.H5check_version(major, minor, release);
assertTrue("H5check_version with correct version should succeed", isSuccess(result));
}
}
// ================================
// Library Status Queries
// ================================
@Test
public void testH5is_library_threadsafe()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment isThreadsafe = arena.allocate(ValueLayout.JAVA_BOOLEAN);
int result = hdf5_h.H5is_library_threadsafe(isThreadsafe);
assertTrue("H5is_library_threadsafe failed", isSuccess(result));
boolean threadsafe = isThreadsafe.get(ValueLayout.JAVA_BOOLEAN, 0);
// Value can be true or false - just verify we got a valid result
System.out.print(" [threadsafe=" + threadsafe + "]");
}
}
@Test
public void testH5is_library_terminating()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment isTerminating = arena.allocate(ValueLayout.JAVA_BOOLEAN);
int result = hdf5_h.H5is_library_terminating(isTerminating);
assertTrue("H5is_library_terminating failed", isSuccess(result));
boolean terminating = isTerminating.get(ValueLayout.JAVA_BOOLEAN, 0);
// During normal operation, should not be terminating
assertFalse("Library should not be terminating during tests", terminating);
}
}
// ================================
// Memory Management
// ================================
@Test
public void testH5allocate_memory()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate 1KB of memory
long size = 1024;
MemorySegment mem = hdf5_h.H5allocate_memory(size, false);
assertNotNull("H5allocate_memory should return non-null", mem);
assertFalse("Allocated memory should not be NULL segment", mem.equals(MemorySegment.NULL));
// Free the memory
int result = hdf5_h.H5free_memory(mem);
assertTrue("H5free_memory should succeed", isSuccess(result));
}
}
@Test
public void testH5allocate_memory_cleared()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate 1KB of cleared memory
long size = 1024;
MemorySegment mem = hdf5_h.H5allocate_memory(size, true);
assertNotNull("H5allocate_memory (cleared) should return non-null", mem);
assertFalse("Allocated memory should not be NULL segment", mem.equals(MemorySegment.NULL));
// Verify first few bytes are zero (memory was cleared)
byte first = mem.get(ValueLayout.JAVA_BYTE, 0);
assertEquals("Cleared memory should be zero", 0, first);
// Free the memory
int result = hdf5_h.H5free_memory(mem);
assertTrue("H5free_memory should succeed", isSuccess(result));
}
}
@Test
public void testH5resize_memory()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate initial memory
long initialSize = 1024;
MemorySegment mem = hdf5_h.H5allocate_memory(initialSize, false);
assertNotNull("Initial allocation should succeed", mem);
// Resize to larger size
long newSize = 2048;
MemorySegment resized = hdf5_h.H5resize_memory(mem, newSize);
assertNotNull("H5resize_memory should return non-null", resized);
assertFalse("Resized memory should not be NULL segment", resized.equals(MemorySegment.NULL));
// Free the resized memory
int result = hdf5_h.H5free_memory(resized);
assertTrue("H5free_memory should succeed", isSuccess(result));
}
}
@Test
public void testH5free_memory()
{
try (Arena arena = Arena.ofConfined()) {
// Allocate and immediately free
MemorySegment mem = hdf5_h.H5allocate_memory(512, false);
assertNotNull("Allocation should succeed", mem);
int result = hdf5_h.H5free_memory(mem);
assertTrue("H5free_memory should succeed", isSuccess(result));
}
}
// ================================
// Free List Management
// ================================
@Test
public void testH5set_free_list_limits()
{
// Set conservative limits for free lists
int reg_global_lim = 1; // 1 MB
int reg_list_lim = 1; // 1 MB
int arr_global_lim = 1; // 1 MB
int arr_list_lim = 1; // 1 MB
int blk_global_lim = 1; // 1 MB
int blk_list_lim = 1; // 1 MB
int result = hdf5_h.H5set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim,
blk_global_lim, blk_list_lim);
assertTrue("H5set_free_list_limits should succeed", isSuccess(result));
}
@Test
public void testH5get_free_list_sizes()
{
try (Arena arena = Arena.ofConfined()) {
MemorySegment regSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment arrSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment blkSize = arena.allocate(ValueLayout.JAVA_LONG);
MemorySegment facSize = arena.allocate(ValueLayout.JAVA_LONG);
int result = hdf5_h.H5get_free_list_sizes(regSize, arrSize, blkSize, facSize);
assertTrue("H5get_free_list_sizes failed", isSuccess(result));
long reg = regSize.get(ValueLayout.JAVA_LONG, 0);
long arr = arrSize.get(ValueLayout.JAVA_LONG, 0);
long blk = blkSize.get(ValueLayout.JAVA_LONG, 0);
long fac = facSize.get(ValueLayout.JAVA_LONG, 0);
// Sizes should be non-negative
assertTrue("Regular free list size should be >= 0", reg >= 0);
assertTrue("Array free list size should be >= 0", arr >= 0);
assertTrue("Block free list size should be >= 0", blk >= 0);
assertTrue("Factory free list size should be >= 0", fac >= 0);
System.out.print(" [reg=" + reg + ",arr=" + arr + ",blk=" + blk + ",fac=" + fac + "]");
}
}
}
Binary file not shown.
+40
View File
@@ -0,0 +1,40 @@
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA_SRCJNI C)
#-----------------------------------------------------------------------------
# Include the main src and config directories
#-----------------------------------------------------------------------------
set (HDF5_JAVA_INCLUDE_DIRECTORIES
${JAVA_INCLUDE_PATH}
${JAVA_INCLUDE_PATH2}
)
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${HDF5_JAVA_INCLUDE_DIRECTORIES}")
set (CMAKE_JAVA_INCLUDE_PATH "")
#-----------------------------------------------------------------------------
# Traverse source subdirectory
#-----------------------------------------------------------------------------
message (VERBOSE "Java version is ${Java_VERSION_STRING}")
message (VERBOSE "JAVA: JAVA_HOME=$ENV{JAVA_HOME} JAVA_ROOT=$ENV{JAVA_ROOT}")
find_package (JNI)
message (VERBOSE "JNI_LIBRARIES=${JNI_LIBRARIES}")
message (VERBOSE "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
list (APPEND HDF5_JAVA_INCLUDE_DIRECTORIES
${JNI_INCLUDE_DIRS}
${HDF5_JAVA_SRCJNI_JNI_SRC_DIR}
)
#-----------------------------------------------------------------------------
# Traverse source subdirectory
#-----------------------------------------------------------------------------
add_subdirectory (jni)
add_subdirectory (hdf)
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if (NOT HDF5_EXTERNALLY_CONFIGURED AND BUILD_TESTING)
add_subdirectory (test)
endif ()
+5
View File
@@ -0,0 +1,5 @@
cmake_minimum_required (VERSION 3.26)
project (HDF5_JAVA_SRCJNI_HDF C)
add_subdirectory (hdf5lib)

Some files were not shown because too many files have changed in this diff Show More