void WriteStringsT( hid_t iParent, const std::string &iAttrName, size_t iNumStrings, const StringT *iStrings ) { // Validate ABCA_ASSERT( iNumStrings > 0, "Degenerate num strings in WriteStringsT" ); ABCA_ASSERT( iStrings, "Degenerate strings buffer in WriteStringsT" ); // Compact the strings. std::vector<CharT> charBuffer; CompactStrings( iStrings, iNumStrings, charBuffer ); // Create the dataspace. size_t len = charBuffer.size(); assert( len >= iNumStrings ); Dimensions dims( len ); HDimensions hdims( dims ); hid_t dspaceId = H5Screate_simple( hdims.rank(), hdims.rootPtr(), NULL ); DspaceCloser dspaceCloser( dspaceId ); ABCA_ASSERT( dspaceId >= 0, "WriteStringsT() Failed in dataspace constructor" ); // Create the attribute. WriteDataToAttr( iParent, dspaceId, iAttrName, GetFileDtype<CharT>(), GetNativeDtype<CharT>(), ( const void * )&charBuffer.front() ); // That's it! }
//-***************************************************************************** // Get the dimensions directly off of the dataspace on the dataset // This isn't suitable for string and wstring void ReadDataSetDimensions( hid_t iParent, const std::string &iName, hsize_t iExtent, Dimensions &oDims ) { // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { // Get the dimensions int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == 1, "H5Sget_simple_extent_ndims() must be 1." ); hsize_t hdim = 0; rank = H5Sget_simple_extent_dims( dspaceId, &hdim, NULL ); oDims.setRank(1); oDims[0] = hdim / iExtent; } else { oDims.setRank(1); oDims[0] = 0; } }
//-***************************************************************************** void WriteScalar( hid_t iParent, const std::string &iAttrName, hid_t iFileType, hid_t iNativeType, const void *iData ) { hid_t dspaceId = H5Screate( H5S_SCALAR ); DspaceCloser dspaceCloser( dspaceId ); WriteDataToAttr( iParent, dspaceId, iAttrName, iFileType, iNativeType, iData ); }
void ReadStringsT( hid_t iParent, const std::string &iAttrName, size_t iNumStrings, StringT *oStrings ) { ABCA_ASSERT( iParent >= 0, "Invalid parent in ReadStringsT" ); // Open the attribute. hid_t attrId = H5Aopen( iParent, iAttrName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( attrId >= 0, "Couldn't open attribute named: " << iAttrName ); AttrCloser attrCloser( attrId ); // Checking code. { hid_t attrFtype = H5Aget_type( attrId ); DtypeCloser dtypeCloser( attrFtype ); hid_t nativeDtype = GetNativeDtype<CharT>(); ABCA_ASSERT( H5Tget_class( attrFtype ) == H5Tget_class( nativeDtype ) && H5Tget_sign( attrFtype ) == H5Tget_sign( nativeDtype ), "Invalid datatype for stringT" ); } hid_t attrSpace = H5Aget_space( attrId ); ABCA_ASSERT( attrSpace >= 0, "Couldn't get dataspace for attribute: " << iAttrName ); DspaceCloser dspaceCloser( attrSpace ); hssize_t numPoints = H5Sget_simple_extent_npoints( attrSpace ); ABCA_ASSERT( numPoints > 0, "Degenerate string dimensions in ReadStringsT" ); // Create temporary char storage buffer. std::vector<CharT> charStorage( ( size_t )( 1 + numPoints ), ( CharT )0 ); // Read into it. herr_t status = H5Aread( attrId, GetNativeDtype<CharT>(), ( void * )&charStorage.front() ); ABCA_ASSERT( status >= 0, "Couldn't read from attribute: " << iAttrName ); // Extract 'em. ExtractStrings( oStrings, ( const CharT * )&charStorage.front(), 1 + numPoints, iNumStrings ); }
//-***************************************************************************** void ReadTimeSamples( hid_t iParent, std::vector < AbcA::TimeSamplingPtr > & oTimeSamples ) { oTimeSamples.clear(); // add the intrinsic default sampling AbcA::TimeSamplingPtr ts( new AbcA::TimeSampling() ); oTimeSamples.push_back( ts ); uint32_t i = 1; AbcA::TimeSamplingType tst; std::string tstname = "1"; // keep trying to read till we can't find anymore while ( ReadTimeSamplingType( iParent, tstname, tst ) ) { // try to open the time samples attribute std::string timeName = tstname + ".time"; hid_t aid = H5Aopen( iParent, timeName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( aid >= 0, "Couldn't open time samples named: " << timeName ); AttrCloser attrCloser( aid ); // figure out how big it is hid_t sid = H5Aget_space( aid ); ABCA_ASSERT( sid >= 0, "Couldn't get dataspace for time samples: " << timeName ); DspaceCloser dspaceCloser( sid ); hssize_t numPoints = H5Sget_simple_extent_npoints( sid ); ABCA_ASSERT( numPoints > 0, "No time samples data: " << timeName ); std::vector < chrono_t > times(numPoints); // do the read herr_t status = H5Aread( aid, H5T_NATIVE_DOUBLE, &(times.front()) ); ABCA_ASSERT( status >= 0, "Can't read time samples: " << timeName ); // create the TimeSampling and add it to our vector ts.reset( new AbcA::TimeSampling(tst, times) ); oTimeSamples.push_back( ts ); // increment to try and read the next one i++; std::stringstream strm; strm << i; tstname = strm.str(); } }
void ReadStringT<std::string,char>( hid_t iParent, const std::string &iAttrName, std::string &oString ) { ABCA_ASSERT( iParent >= 0, "Invalid parent in ReadStringT" ); // Open the attribute. hid_t attrId = H5Aopen( iParent, iAttrName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( attrId >= 0, "Couldn't open attribute named: " << iAttrName ); AttrCloser attrCloser( attrId ); // Checking code. hid_t attrFtype = H5Aget_type( attrId ); DtypeCloser dtypeCloser( attrFtype ); ssize_t numChars = H5Tget_size( attrFtype ); ABCA_ASSERT( numChars >= 0, "ReadStringT() H5Aget_size() failed" ); // Read and check space { hid_t attrSpace = H5Aget_space( attrId ); ABCA_ASSERT( attrSpace >= 0, "Couldn't get dataspace for attribute: " << iAttrName ); DspaceCloser dspaceCloser( attrSpace ); H5S_class_t attrSpaceClass = H5Sget_simple_extent_type( attrSpace ); ABCA_ASSERT( attrSpaceClass == H5S_SCALAR, "Tried to read non-scalar attribute: " << iAttrName << " as scalar" ); } // Create temporary char storage buffer. std::vector<char> charStorage( ( size_t )( 1 + numChars ), ( char )0 ); // Read into it. herr_t status = H5Aread( attrId, attrFtype, ( void * )&charStorage.front() ); ABCA_ASSERT( status >= 0, "Couldn't read from attribute: " << iAttrName ); // Return it. oString = ( const char * )&charStorage.front(); }
//-***************************************************************************** void WriteSmallArray( hid_t iParent, const std::string &iAttrName, hid_t iFileType, hid_t iNativeType, size_t iNumVals, const void *iData ) { Dimensions dims( iNumVals ); HDimensions hdims( dims ); size_t npoints = hdims.numPoints(); ABCA_ASSERT( npoints > 0, "Cannot create degenerate dataspace" ); hid_t dspaceId = H5Screate_simple( hdims.rank(), hdims.rootPtr(), NULL ); DspaceCloser dspaceCloser( dspaceId ); WriteDataToAttr( iParent, dspaceId, iAttrName, iFileType, iNativeType, iData ); }
//-***************************************************************************** void WriteReferences( hid_t iParent, const std::string& iRefName, size_t iNumRefs, const void *iRefs ) { hsize_t dims[1]; dims[0] = iNumRefs; hid_t dspaceId = H5Screate_simple( 1, dims, NULL ); DspaceCloser dspaceCloser( dspaceId ); hid_t dsetId = H5Dcreate2( iParent, iRefName.c_str(), H5T_STD_REF_OBJ, dspaceId, H5P_DEFAULT, H5P_DEFAULT,H5P_DEFAULT); DsetCloser dsetCloser( dsetId ); herr_t status = H5Dwrite( dsetId, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, iRefs); ABCA_ASSERT( status >= 0, "Couldn't write reference: " << iRefName ); }
void WriteStringT<std::string,char>( hid_t iParent, const std::string &iAttrName, const std::string &iString ) { // Verify that no NULL characters have been hidden in the string. const char NullChar = ( char )0; ABCA_ASSERT( iString.find( NullChar ) == std::string::npos, "Illegal NULL character found in string in WriteStringT" ); size_t len = iString.length(); if ( len < 1 ) { len = 1; } hid_t dtypeId = H5Tcopy( H5T_C_S1 ); DtypeCloser dtypeCloser( dtypeId ); H5Tset_size( dtypeId, len ); hid_t dspaceId = H5Screate( H5S_SCALAR ); DspaceCloser dspaceCloser( dspaceId ); WriteDataToAttr( iParent, dspaceId, iAttrName, dtypeId, dtypeId, ( const void * )iString.c_str() ); }
void WriteStringT( hid_t iParent, const std::string &iAttrName, const StringT &iString ) { // Verify that no NULL characters have been hidden in the string. CharT NullChar = ( CharT )0; ABCA_ASSERT( iString.find( NullChar ) == StringT::npos, "Illegal NULL character found in string in WriteStringT" ); // Create the dataspace. size_t len = iString.length(); Dimensions dims( len + 1 ); HDimensions hdims( dims ); size_t npoints = hdims.numPoints(); ABCA_ASSERT( npoints > 0, "Cannot create degenerate dataspace" ); hid_t dspaceId = H5Screate_simple( hdims.rank(), hdims.rootPtr(), NULL ); DspaceCloser dspaceCloser( dspaceId ); // Get the data. const CharT *data; if ( len == 0 ) { data = &NullChar; } else { data = iString.c_str(); } // Write into it. WriteDataToAttr( iParent, dspaceId, iAttrName, GetFileDtype<CharT>(), GetNativeDtype<CharT>(), ( const void * )data ); }
WrittenArraySampleIDPtr WriteStringArrayT( WrittenArraySampleMap &iMap, hid_t iGroup, const std::string &iName, const AbcA::ArraySample &iSamp, const AbcA::ArraySample::Key &iKey, int iCompressionLevel ) { // because strings are packed together, always write out the dimensions Dimensions dims = iSamp.getDimensions(); ABCA_ASSERT( dims.rank() > 0, "String type can not have a rank-0 array sample" ); std::string dimsName = iName + ".dims"; WriteDimensions( iGroup, dimsName, dims ); // See whether or not we've already stored this. WrittenArraySampleIDPtr writeID = iMap.find( iKey ); if ( writeID ) { CopyWrittenArray( iGroup, iName, writeID ); return writeID; } // Okay, need to actually store it. // It will be a dataset with an internal attribute for storing // the hash id. bool hasData = dims.numPoints() > 0; hid_t dspaceId = -1; Dimensions wdims; // Used to store the "fake" dimensions. std::vector<CharT> charBuffer; // Get the dimensions, validate sample size. if ( hasData ) { size_t extent = iSamp.getDataType().getExtent(); size_t numStrings = dims.numPoints() * extent; ABCA_ASSERT( dims.rank() > 0 && numStrings > 0, "Degenerate array sample in WriteStringArrayT" ); // Get the data out of the array sample. const StringT *strings = reinterpret_cast<const StringT *>( iSamp.getData() ); ABCA_ASSERT( strings, "Degenerate strings in WriteStringArrayT" ); // Compact the strings in the string array. CompactStrings( strings, numStrings, charBuffer ); // Create the dataspace. size_t len = charBuffer.size(); assert( len >= numStrings ); wdims = Dimensions( len ); HDimensions hdims( wdims ); dspaceId = H5Screate_simple( hdims.rank(), hdims.rootPtr(), NULL ); } else { dspaceId = H5Screate( H5S_NULL ); } ABCA_ASSERT( dspaceId >= 0, "WriteStringsT() Failed in dataspace constructor" ); DspaceCloser dspaceCloser( dspaceId ); hid_t dsetId = -1; if ( iCompressionLevel >= 0 && hasData ) { // Make a compression plist hid_t zipPlist = DsetGzipCreatePlist( wdims, iCompressionLevel > 9 ? 9 : iCompressionLevel ); PlistCloser plistCloser( zipPlist ); //std::cout << "Creating compressed data set named: " // << iName << " in group named: " << iGroup.name() // << std::endl; // Make the dataset. dsetId = H5Dcreate2( iGroup, iName.c_str(), GetFileDtype<CharT>(), dspaceId, H5P_DEFAULT, zipPlist, H5P_DEFAULT ); } else { //std::cout << "Creating uncompressed data set named: " // << iName << " in group named: " << iGroup.name() // << std::endl; dsetId = H5Dcreate2( iGroup, iName.c_str(), GetFileDtype<CharT>(), dspaceId, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ); } DsetCloser dsetCloser(dsetId); ABCA_ASSERT( dsetId >= 0, "WriteArray() Failed in dataset constructor" ); // Write the data. if ( hasData ) { H5Dwrite( dsetId, GetNativeDtype<CharT>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, &charBuffer.front() ); } // Write the key WriteKey( dsetId, "key", iKey ); writeID.reset( new WrittenArraySampleID( iKey, dsetId ) ); iMap.store( writeID ); // Return the reference. return writeID; }
//-***************************************************************************** WrittenArraySampleIDPtr WriteArray( WrittenArraySampleMap &iMap, hid_t iGroup, const std::string &iName, const AbcA::ArraySample &iSamp, const AbcA::ArraySample::Key &iKey, hid_t iFileType, hid_t iNativeType, int iCompressionLevel ) { // Dispatch to string writing utils. const AbcA::DataType &dataType = iSamp.getDataType(); if ( dataType.getPod() == kStringPOD ) { return WriteStringArray( iMap, iGroup, iName, iSamp, iKey, iCompressionLevel ); } else if ( dataType.getPod() == kWstringPOD ) { return WriteWstringArray( iMap, iGroup, iName, iSamp, iKey, iCompressionLevel ); } // write the dimensions as necessary Dimensions dims = iSamp.getDimensions(); size_t rank = dims.rank(); ABCA_ASSERT( rank > 0, "Cannot have a rank-0 array sample" ); // rank 1 is the most common case, and we can easily infer it's size // from the dataspace for non-strings, so don't bother writing it out if (rank > 1) { std::string dimsName = iName + ".dims"; WriteDimensions( iGroup, dimsName, dims ); } // See whether or not we've already stored this. WrittenArraySampleIDPtr writeID = iMap.find( iKey ); if ( writeID ) { CopyWrittenArray( iGroup, iName, writeID ); return writeID; } // Okay, need to actually store it. // It will be a dataset with an internal attribute for storing // the hash id. bool hasData = dims.numPoints() > 0; hid_t dspaceId = -1; if ( hasData ) { hsize_t hdim = dims.numPoints() * dataType.getExtent(); dspaceId = H5Screate_simple( 1, &hdim, NULL ); } else { dspaceId = H5Screate( H5S_NULL ); } ABCA_ASSERT( dspaceId >= 0, "WriteArray() Failed in dataspace construction" ); DspaceCloser dspaceCloser( dspaceId ); hid_t dsetId = -1; if ( iCompressionLevel >= 0 && hasData ) { // Make a compression plist hid_t zipPlist = DsetGzipCreatePlist( dims, iCompressionLevel > 9 ? 9 : iCompressionLevel ); PlistCloser plistCloser( zipPlist ); // Make the dataset. dsetId = H5Dcreate2( iGroup, iName.c_str(), iFileType, dspaceId, H5P_DEFAULT, zipPlist, H5P_DEFAULT ); } else { dsetId = H5Dcreate2( iGroup, iName.c_str(), iFileType, dspaceId, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ); } DsetCloser dsetCloser(dsetId); ABCA_ASSERT( dsetId >= 0, "WriteArray() Failed in dataset constructor" ); // Write the data. if ( hasData ) { H5Dwrite( dsetId, iNativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, iSamp.getData() ); } // Write the array sample key. WriteKey( dsetId, "key", iKey ); writeID.reset( new WrittenArraySampleID( iKey, dsetId ) ); iMap.store( writeID ); // Return the reference. return writeID; }
static AbcA::ArraySamplePtr ReadStringArrayT( AbcA::ReadArraySampleCachePtr iCache, hid_t iParent, const std::string &iName, const AbcA::DataType &iDataType ) { assert( iDataType.getExtent() > 0 ); // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the digest, if there's a cache. AbcA::ArraySample::Key key; bool foundDigest = ReadKey( dsetId, "key", key ); // If we found a digest and there's a cache, see // if we're in there, and return it if so. if ( foundDigest && iCache ) { AbcA::ReadArraySampleID found = iCache->find( key ); if ( found ) { AbcA::ArraySamplePtr ret = found.getSample(); assert( ret ); if ( ret->getDataType() != iDataType ) { ABCA_THROW( "ERROR: Read data type for dset: " << iName << ": " << ret->getDataType() << " does not match expected data type: " << iDataType ); } // Got it! return ret; } } // Okay, we haven't found it in a cache. // Read the data type. // Checking code. { hid_t dsetFtype = H5Dget_type( dsetId ); DtypeCloser dtypeCloser( dsetFtype ); hid_t nativeDtype = GetNativeDtype<CharT>(); ABCA_ASSERT( H5Tget_class( dsetFtype ) == H5Tget_class( nativeDtype ) && H5Tget_sign( dsetFtype ) == H5Tget_sign( nativeDtype ) // CJH They can now be different // sizes, because wchar_t is sometimes 16-bit, // but we always store 32 bit. // && H5Tget_size( dsetFtype ) == //H5Tget_size( nativeDtype ), , "Invalid datatype for stringT" ); } // String array datatypes require a "dimensions" to be stored // externally, since the strings themselves are stored in a compacted // array of rank 1. // This is an attribute called "dims" that lives in the dset itself. Dimensions realDims; ReadDimensions( dsetId, "dims", realDims ); ABCA_ASSERT( realDims.rank() > 0, "Degenerate rank in Dataset read" ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); AbcA::ArraySamplePtr ret; H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { ABCA_ASSERT( realDims.numPoints() > 0, "Degenerate dims in Dataset read" ); size_t totalNumStrings = realDims.numPoints() * iDataType.getExtent(); // Get the dimensions Dimensions dims; int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == realDims.rank(), "H5Sget_simple_extent_ndims() failed." ); HDimensions hdims; hdims.setRank( rank ); rank = H5Sget_simple_extent_dims( dspaceId, hdims.rootPtr(), NULL ); ABCA_ASSERT( rank == hdims.rank(), "H5Sget_simple_extent_dims() " "found inconsistent ranks." << std::endl << "Expecting rank: " << hdims.rank() << " instead was: " << rank ); dims = hdims; ABCA_ASSERT( dims.numPoints() > 0, "Degenerate dims in Dataset read" ); // Create temporary char storage buffer. size_t totalNumChars = dims.numPoints() + 1; std::vector<CharT> charStorage( totalNumChars, ( CharT )0 ); // Read into it. herr_t status = H5Dread( dsetId, GetNativeDtype<CharT>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, ( void * )&charStorage.front() ); ABCA_ASSERT( status >= 0, "Could not read string array from data set. Weird." ); // Make an appropriately dimensionalized (and manageable) // array of strings using the ArraySamples. ret = AbcA::AllocateArraySample( iDataType, realDims ); StringT *strings = reinterpret_cast<StringT*>( const_cast<void*>( ret->getData() ) ); assert( strings != NULL ); // This part is hard. We have to go through the one dimensional // array extracting each string. ExtractStrings<StringT,CharT>( strings, ( const CharT * )&charStorage.front(), totalNumChars, totalNumStrings ); } else if ( dspaceClass == H5S_NULL ) { // Num points should be zero here. ABCA_ASSERT( realDims.numPoints() == 0, "Expecting zero points in dimensions" ); ret = AbcA::AllocateArraySample( iDataType, realDims ); } else { ABCA_THROW( "Unexpected scalar dataspace encountered." ); } // Store if there is a cache. if ( foundDigest && iCache ) { AbcA::ReadArraySampleID stored = iCache->store( key, ret ); if ( stored ) { return stored.getSample(); } } // Otherwise, just leave! ArraySamplePtr returned by AllocateArraySample // already has fancy-dan deleter built in. // I REALLY LOVE SMART PTRS. return ret; }
//-***************************************************************************** void ReadArray( void * iIntoLocation, hid_t iParent, const std::string &iName, const AbcA::DataType &iDataType, hid_t iType ) { // Dispatch string stuff. if ( iDataType.getPod() == kStringPOD ) { return ReadStringArray( iIntoLocation, iParent, iName, iDataType ); } else if ( iDataType.getPod() == kWstringPOD ) { return ReadWstringArray( iIntoLocation, iParent, iName, iDataType ); } assert( iDataType.getPod() != kStringPOD && iDataType.getPod() != kWstringPOD ); // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); // Read the data type. hid_t dtypeId = H5Dget_type( dsetId ); ABCA_ASSERT( dtypeId >= 0, "Could not get datatype for dataSet: " << iName ); DtypeCloser dtypeCloser( dtypeId ); H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { // Get the dimensions int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == 1, "H5Sget_simple_extent_ndims() must be 1." ); hsize_t hdim = 0; rank = H5Sget_simple_extent_dims( dspaceId, &hdim, NULL ); ABCA_ASSERT( hdim > 0, "Degenerate dims in Dataset read" ); // And... read into it. herr_t status = H5Dread( dsetId, iType, H5S_ALL, H5S_ALL, H5P_DEFAULT, iIntoLocation ); ABCA_ASSERT( status >= 0, "H5Dread() failed." ); } else if ( dspaceClass != H5S_NULL ) { ABCA_THROW( "Unexpected scalar dataspace encountered." ); } }
//-***************************************************************************** AbcA::ArraySamplePtr ReadArray( AbcA::ReadArraySampleCachePtr iCache, hid_t iParent, const std::string &iName, const AbcA::DataType &iDataType, hid_t iFileType, hid_t iNativeType ) { // Dispatch string stuff. if ( iDataType.getPod() == kStringPOD ) { return ReadStringArray( iCache, iParent, iName, iDataType ); } else if ( iDataType.getPod() == kWstringPOD ) { return ReadWstringArray( iCache, iParent, iName, iDataType ); } assert( iDataType.getPod() != kStringPOD && iDataType.getPod() != kWstringPOD ); // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); AbcA::ArraySample::Key key; bool foundDigest = false; // if we are caching, get the key and see if it is being used if ( iCache ) { key.origPOD = iDataType.getPod(); key.readPOD = key.origPOD; key.numBytes = Util::PODNumBytes( key.readPOD ) * H5Sget_simple_extent_npoints( dspaceId ); foundDigest = ReadKey( dsetId, "key", key ); AbcA::ReadArraySampleID found = iCache->find( key ); if ( found ) { AbcA::ArraySamplePtr ret = found.getSample(); assert( ret ); if ( ret->getDataType().getPod() != iDataType.getPod() ) { ABCA_THROW( "ERROR: Read data type for dset: " << iName << ": " << ret->getDataType() << " does not match expected data type: " << iDataType ); } // Got it! return ret; } } // Okay, we haven't found it in a cache. // Read the data type. hid_t dtypeId = H5Dget_type( dsetId ); ABCA_ASSERT( dtypeId >= 0, "Could not get datatype for dataSet: " << iName ); DtypeCloser dtypeCloser( dtypeId ); ABCA_ASSERT( EquivalentDatatypes( iFileType, dtypeId ), "File DataType clash for array dataset: " << iName ); AbcA::ArraySamplePtr ret; H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { // Get the dimensions int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == 1, "H5Sget_simple_extent_ndims() must be 1." ); hsize_t hdim = 0; rank = H5Sget_simple_extent_dims( dspaceId, &hdim, NULL ); Dimensions dims; std::string dimName = iName + ".dims"; if ( H5Aexists( iParent, dimName.c_str() ) ) { ReadDimensions( iParent, dimName, dims ); } else { dims.setRank(1); dims[0] = hdim / iDataType.getExtent(); } ABCA_ASSERT( dims.numPoints() > 0, "Degenerate dims in Dataset read" ); // Create a buffer into which we shall read. ret = AbcA::AllocateArraySample( iDataType, dims ); assert( ret->getData() ); // And... read into it. herr_t status = H5Dread( dsetId, iNativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, const_cast<void*>( ret->getData() ) ); ABCA_ASSERT( status >= 0, "H5Dread() failed." ); } else if ( dspaceClass == H5S_NULL ) { Dimensions dims; std::string dimName = iName + ".dims"; if ( H5Aexists( iParent, dimName.c_str() ) ) { ReadDimensions( iParent, dimName, dims ); ABCA_ASSERT( dims.rank() > 0, "Degenerate rank in Dataset read" ); // Num points should be zero here. ABCA_ASSERT( dims.numPoints() == 0, "Expecting zero points in dimensions" ); } else { dims.setRank(1); dims[0] = 0; } ret = AbcA::AllocateArraySample( iDataType, dims ); } else { ABCA_THROW( "Unexpected scalar dataspace encountered." ); } // Store if there is a cache. if ( foundDigest && iCache ) { AbcA::ReadArraySampleID stored = iCache->store( key, ret ); if ( stored ) { return stored.getSample(); } } // Otherwise, just leave! ArraySamplePtr returned by AllocateArraySample // already has fancy-dan deleter built in. // I REALLY LOVE SMART PTRS. return ret; }
//-***************************************************************************** ArImpl::ArImpl( const std::string &iFileName, AbcA::ReadArraySampleCachePtr iCache, const bool iCacheHierarchy ) : m_fileName( iFileName ) , m_file( -1 ) , m_readArraySampleCache( iCache ) { // OPEN THE FILE! htri_t exi = H5Fis_hdf5( m_fileName.c_str() ); ABCA_ASSERT( exi == 1, "Nonexistent or not an Alembic file: " << m_fileName ); m_file = H5Fopen( m_fileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT ); ABCA_ASSERT( m_file >= 0, "Could not open file: " << m_fileName ); // get the version using HDF5 native calls int version = -INT_MAX; if (H5Aexists(m_file, "abc_version")) { size_t numRead = 0; ReadSmallArray(m_file, "abc_version", H5T_STD_I32LE, H5T_NATIVE_INT32, 1, numRead, &version); } ABCA_ASSERT(version >= -8 && version <= ALEMBIC_HDF5_FILE_VERSION, "Unsupported file version detected: " << version); // if it isn't there, it's pre 1.0 int fileVersion = 9999; if (H5Aexists( m_file, "abc_release_version" )) { size_t numRead = 0; ReadSmallArray( m_file, "abc_release_version", H5T_STD_I32LE, H5T_NATIVE_INT32, 1, numRead, &fileVersion ); } m_archiveVersion = fileVersion; HDF5HierarchyReader reader( m_file, m_H5H, iCacheHierarchy ); H5Node node = m_H5H.createNode( m_file ); H5Node abcRoot = OpenGroup( node, "ABC" ); AbcA::MetaData metaData; ReadMetaData( abcRoot, ".prop.meta", metaData ); m_header.reset( new AbcA::ObjectHeader( "ABC", "/", metaData ) ); m_data.reset( new OrData( m_header, node, m_archiveVersion ) ); CloseObject( abcRoot ); ReadTimeSamples( m_file, m_timeSamples ); if ( H5Aexists( m_file, "abc_max_samples" ) ) { hid_t aid = H5Aopen( m_file, "abc_max_samples", H5P_DEFAULT ); if ( aid < 0 ) { return; } AttrCloser attrCloser( aid ); // figure out how big it is hid_t sid = H5Aget_space( aid ); if ( sid < 0 ) { return; } DspaceCloser dspaceCloser( sid ); hssize_t numPoints = H5Sget_simple_extent_npoints( sid ); if ( numPoints < 1 ) { return; } m_maxSamples.resize( numPoints ); // do the read H5Aread( aid, H5T_NATIVE_LLONG, &( m_maxSamples.front() ) ); } }