1 //-*****************************************************************************
2 //
3 // Copyright (c) 2012,
4 // Sony Pictures Imageworks, Inc. and
5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // * Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36
37 #include <algorithm>
38 #include <Alembic/AbcCoreHDF5/HDF5Hierarchy.h>
39 #include <Alembic/AbcCoreHDF5/HDF5Util.h>
40 #include <Alembic/AbcCoreHDF5/ReadUtil.h>
41
42 namespace Alembic {
43 namespace AbcCoreHDF5 {
44 namespace ALEMBIC_VERSION_NS {
45
46 //-*****************************************************************************
47 class ObjectVisitor
48 {
49 public:
ObjectVisitor(HDF5Hierarchy & iParent)50 ObjectVisitor( HDF5Hierarchy &iParent )
51 : m_parent( iParent ) {}
52
53 public:
addObject(hid_t iGroup,const char * iName)54 void addObject( hid_t iGroup, const char *iName )
55 {
56 m_parent.addObject( iGroup, iName );
57 }
58
addAttr(hid_t iGroup,const char * iName)59 void addAttr( hid_t iGroup, const char *iName )
60 {
61 m_parent.addAttr( iGroup, iName );
62 }
63
64 private:
65 HDF5Hierarchy &m_parent;
66 };
67
68 //-*****************************************************************************
VisitAllAttrsCB(hid_t iGroup,const char * iAttrName,const H5A_info_t * iAinfo,void * iOpData)69 static herr_t VisitAllAttrsCB( hid_t iGroup,
70 const char *iAttrName,
71 const H5A_info_t *iAinfo,
72 void *iOpData )
73 {
74 ObjectVisitor *visitor = ( ObjectVisitor * )iOpData;
75 visitor->addAttr( iGroup, iAttrName );
76
77 return 0;
78 }
79
80 //-*****************************************************************************
VisitAllGroupsCB(hid_t iGroup,const char * iName,const H5L_info_t * iOinfo,void * iOpData)81 static herr_t VisitAllGroupsCB( hid_t iGroup,
82 const char *iName,
83 const H5L_info_t *iOinfo,
84 void *iOpData )
85 {
86 ObjectVisitor *visitor = ( ObjectVisitor * )iOpData;
87
88 H5O_info_t Oinfo;
89 H5Oget_info_by_name( iGroup, iName, &Oinfo, H5P_DEFAULT );
90
91 if ( Oinfo.type == H5O_TYPE_GROUP )
92 {
93 H5Literate_by_name( iGroup, iName,
94 H5_INDEX_NAME,
95 H5_ITER_INC,
96 NULL,
97 VisitAllGroupsCB,
98 iOpData,
99 H5P_DEFAULT );
100
101 visitor->addObject( iGroup, iName );
102
103 H5Aiterate_by_name( iGroup, iName,
104 H5_INDEX_NAME,
105 H5_ITER_INC,
106 NULL,
107 VisitAllAttrsCB,
108 iOpData,
109 H5P_DEFAULT );
110
111 }
112 else if (Oinfo.type == H5O_TYPE_DATASET )
113 {
114 visitor->addObject( iGroup, iName );
115
116 H5Aiterate_by_name( iGroup, iName,
117 H5_INDEX_NAME,
118 H5_ITER_INC,
119 NULL,
120 VisitAllAttrsCB,
121 iOpData,
122 H5P_DEFAULT );
123 }
124
125 // Keep iterating!
126 return 0;
127 }
128
129 //-*****************************************************************************
createNode(hid_t iObject)130 H5Node HDF5Hierarchy::createNode( hid_t iObject )
131 {
132 hobj_ref_t ref;
133 H5Rcreate( &ref, iObject, ".", H5R_OBJECT, -1 );
134
135 return H5Node( iObject, ref, isEnabled() ? this : NULL );
136 }
137
138 //-*****************************************************************************
build(hid_t iFile)139 void HDF5Hierarchy::build( hid_t iFile )
140 {
141 clear();
142
143 ObjectVisitor visitor( *this );
144 H5Literate( iFile,
145 H5_INDEX_NAME,
146 H5_ITER_INC,
147 NULL,
148 VisitAllGroupsCB,
149 ( void * )&visitor);
150 }
151
152 //-*****************************************************************************
clear()153 void HDF5Hierarchy::clear()
154 {
155 for( ObjectMap::iterator it = m_objectMap.begin();
156 it != m_objectMap.end(); ++it )
157 {
158 it->second.m_attrs.clear();
159 }
160
161 m_objectMap.clear();
162 }
163
164 //-*****************************************************************************
addObject(hid_t iParent,const char * iName)165 void HDF5Hierarchy::addObject( hid_t iParent, const char *iName )
166 {
167 hobj_ref_t parentRef, childRef;
168 H5Rcreate( &parentRef, iParent, ".", H5R_OBJECT, -1 );
169 H5Rcreate( &childRef, iParent, iName, H5R_OBJECT, -1 );
170
171 m_objectMap[parentRef].m_children.push_back(
172 ChildInfo( iName, childRef ) );
173 }
174
175 namespace {
176 const std::string g_strInfo( ".info" );
177 const std::string g_strMeta( ".meta" );
178 }
179
180 //-*****************************************************************************
addAttr(hid_t iParent,const char * iName)181 void HDF5Hierarchy::addAttr( hid_t iParent, const char *iName )
182 {
183 hobj_ref_t parentRef;
184 H5Rcreate( &parentRef, iParent, ".", H5R_OBJECT, -1 );
185
186 // attribute
187 AttrInfoArray& attrs = m_objectMap[parentRef].m_attrs;
188 attrs.push_back( AttrInfo( iName ) );
189 AttrInfo& info = attrs[attrs.size()-1];
190
191 std::string strName( iName );
192 const size_t len = strName.size();
193 if ( len < 6 ) return;
194
195 // property header mask
196 if ( strName.compare( len-5, 5, g_strInfo ) == 0 )
197 {
198 ABCA_ASSERT( !info.m_mask,
199 "A property header mask alreasy exists." );
200
201 info.m_mask = new MaskInfo;
202 info.m_mask->m_numFields = 0;
203
204 ReadSmallArray( iParent, iName, H5T_STD_U32LE,
205 H5T_NATIVE_UINT32, 5,
206 info.m_mask->m_numFields,
207 ( void * ) info.m_mask->m_data );
208 }
209
210 // meta data string
211 if ( strName.compare( len-5, 5, g_strMeta ) == 0 )
212 {
213 ReadString( iParent, strName, info.m_meta );
214 }
215
216 }
217
218 //-*****************************************************************************
getChildRef(hobj_ref_t iParentRef,const std::string & iName)219 hobj_ref_t HDF5Hierarchy::getChildRef( hobj_ref_t iParentRef,
220 const std::string& iName )
221 {
222 ChildInfo info( iName );
223 ChildInfoArray& children = m_objectMap[iParentRef].m_children;
224 ChildInfoArray::iterator it = std::lower_bound( children.begin(),
225 children.end(),
226 info );
227
228 ABCA_ASSERT ( ( it != children.end() && !( info < *it ) ),
229 "A child object does not exist with name: " << iName );
230
231 return it->m_ref;
232 }
233
234 //-*****************************************************************************
childExists(hobj_ref_t iParentRef,const std::string & iName)235 bool HDF5Hierarchy::childExists( hobj_ref_t iParentRef,
236 const std::string& iName )
237 {
238 ChildInfo info( iName );
239 ChildInfoArray& children = m_objectMap[iParentRef].m_children;
240 ChildInfoArray::iterator it = std::lower_bound( children.begin(),
241 children.end(),
242 info );
243
244 return ( it != children.end() && !( info < *it ) );
245 }
246
247 //-*****************************************************************************
attrExists(hobj_ref_t iParentRef,const std::string & iName)248 bool HDF5Hierarchy::attrExists( hobj_ref_t iParentRef,
249 const std::string& iName )
250 {
251 AttrInfo info( iName );
252 AttrInfoArray& attrs = m_objectMap[iParentRef].m_attrs;
253 AttrInfoArray::iterator it = std::lower_bound( attrs.begin(),
254 attrs.end(),
255 info );
256
257 return ( it != attrs.end() && !( info < *it ) );
258 }
259
260 //-*****************************************************************************
readMetaDataString(hobj_ref_t iParentRef,const std::string & iMetaDataName,std::string & oMetaDataString)261 void HDF5Hierarchy::readMetaDataString( hobj_ref_t iParentRef,
262 const std::string &iMetaDataName,
263 std::string &oMetaDataString )
264 {
265 AttrInfo info( iMetaDataName );
266 AttrInfoArray& attrs = m_objectMap[iParentRef].m_attrs;
267 AttrInfoArray::iterator it = std::lower_bound( attrs.begin(),
268 attrs.end(),
269 info );
270 if (it == attrs.end() || info < *it )
271 return;
272
273 oMetaDataString = it->m_meta;
274 }
275
276 //-*****************************************************************************
readMaskInfo(hobj_ref_t iParentRef,const std::string & iPropName,size_t & oNumFields,void * oData)277 void HDF5Hierarchy::readMaskInfo( hobj_ref_t iParentRef,
278 const std::string &iPropName,
279 size_t& oNumFields,
280 void* oData )
281 {
282 AttrInfo info( iPropName );
283 AttrInfoArray& attrs = m_objectMap[iParentRef].m_attrs;
284 AttrInfoArray::iterator it = std::lower_bound( attrs.begin(),
285 attrs.end(),
286 info );
287
288 ABCA_ASSERT ( it != attrs.end() && !( info < *it),
289 "Can't find a property header info attribute." );
290
291 if ( !it->m_mask )
292 {
293 return;
294 }
295
296 MaskInfo& p = *it->m_mask;
297 oNumFields = p.m_numFields;
298 memcpy( oData, p.m_data, sizeof( uint32_t ) * oNumFields );
299 }
300
301 //-*****************************************************************************
makeCompactObjectHierarchy(std::vector<hobj_ref_t> & oObjectRefs,std::vector<uint32_t> & oChildrenSizes,std::vector<std::string> & oChildrenNames,std::vector<hobj_ref_t> & oChildrenRefs,std::vector<uint32_t> & oAttrSizes,std::vector<std::string> & oAttrNames,std::vector<char> & oHasMask,std::vector<uint32_t> & oMaskBits,std::vector<char> & oHasMeta,std::vector<std::string> & oMetaStrs)302 void HDF5Hierarchy::makeCompactObjectHierarchy(
303 std::vector<hobj_ref_t> &oObjectRefs,
304
305 std::vector<uint32_t> &oChildrenSizes,
306 std::vector<std::string> &oChildrenNames,
307 std::vector<hobj_ref_t> &oChildrenRefs,
308
309 std::vector<uint32_t> &oAttrSizes,
310 std::vector<std::string> &oAttrNames,
311 std::vector<char> &oHasMask,
312 std::vector<uint32_t> &oMaskBits,
313 std::vector<char> &oHasMeta,
314 std::vector<std::string> &oMetaStrs
315 )
316 {
317 oObjectRefs.clear();
318
319 oChildrenSizes.clear();
320 oChildrenNames.clear();
321 oChildrenRefs.clear();
322
323 oAttrSizes.clear();
324 oAttrNames.clear();
325 oHasMask.clear();
326 oMaskBits.clear();
327 oHasMeta.clear();
328 oMetaStrs.clear();
329
330 for( ObjectMap::iterator itp = m_objectMap.begin();
331 itp != m_objectMap.end(); ++itp )
332 {
333 ObjectInfo& info = itp->second;
334
335 {
336 oObjectRefs.push_back( itp->first );
337 }
338
339 // children
340 {
341 ChildInfoArray& array = info.m_children;
342
343 oChildrenSizes.push_back( array.size() );
344
345 for( ChildInfoArray::iterator itc = array.begin();
346 itc != array.end(); ++itc )
347 {
348 oChildrenNames.push_back( itc->m_name );
349 oChildrenRefs.push_back( itc->m_ref );
350 }
351 }
352
353 // attributes, property header masks and meta data string
354 {
355 AttrInfoArray& array = info.m_attrs;
356
357 oAttrSizes.push_back( array.size() );
358
359 for( AttrInfoArray::iterator itc = array.begin();
360 itc != array.end(); ++itc )
361 {
362 // attribute
363 oAttrNames.push_back( itc->m_name );
364
365 // mask
366 if ( itc->m_mask && itc->m_mask->m_numFields > 0 )
367 {
368 MaskInfo& p = *itc->m_mask;
369 oHasMask.push_back( 1 );
370
371 oMaskBits.push_back( p.m_numFields );
372 oMaskBits.push_back( p.m_data[0] );
373 oMaskBits.push_back( p.m_data[1] );
374 oMaskBits.push_back( p.m_data[2] );
375 oMaskBits.push_back( p.m_data[3] );
376 oMaskBits.push_back( p.m_data[4] );
377 }
378 else
379 {
380 oHasMask.push_back( 0 );
381 }
382
383 // meta data
384 if ( itc->m_meta.size() > 0 )
385 {
386 oMetaStrs.push_back( itc->m_meta );
387 oHasMeta.push_back( 1 );
388 }
389 else
390 {
391 oHasMeta.push_back( 0 );
392 }
393 }
394 }
395 }
396 }
397
398 //-*****************************************************************************
extractFromCompactObjectHierarchy(hid_t iFile,std::vector<hobj_ref_t> & iObjectRefs,std::vector<uint32_t> & iChildrenSizes,std::vector<std::string> & iChildrenNames,std::vector<hobj_ref_t> & iChildrenRefs,std::vector<uint32_t> & iAttrSizes,std::vector<std::string> & iAttrNames,std::vector<char> & iHasMask,std::vector<uint32_t> & iMaskBits,std::vector<char> & iHasMeta,std::vector<std::string> & iMetaStrs)399 void HDF5Hierarchy::extractFromCompactObjectHierarchy(
400 hid_t iFile,
401
402 std::vector<hobj_ref_t> &iObjectRefs,
403
404 std::vector<uint32_t> &iChildrenSizes,
405 std::vector<std::string> &iChildrenNames,
406 std::vector<hobj_ref_t> &iChildrenRefs,
407
408 std::vector<uint32_t> &iAttrSizes,
409 std::vector<std::string> &iAttrNames,
410 std::vector<char> &iHasMask,
411 std::vector<uint32_t> &iMaskBits,
412 std::vector<char> &iHasMeta,
413 std::vector<std::string> &iMetaStrs )
414 {
415 clear();
416
417 size_t idxCBegin(0), idxCEnd(0);
418 size_t idxABegin(0), idxAEnd(0);
419 size_t idxMask(0), idxMeta(0);
420
421 for( size_t ip = 0; ip < iObjectRefs.size(); ++ip )
422 {
423 const hobj_ref_t parentRef = iObjectRefs[ip];
424
425 ObjectInfo& object = m_objectMap[parentRef];
426
427 // children
428 idxCEnd = idxCBegin + iChildrenSizes[ip];
429 for( size_t ic = idxCBegin; ic < idxCEnd; ++ic )
430 {
431 const hobj_ref_t ref = iChildrenRefs[ic];
432 const std::string &name = iChildrenNames[ic];
433
434 object.m_children.push_back( ChildInfo( name, ref) );
435 }
436 idxCBegin = idxCEnd;
437
438 // attributes, masks and metadata
439 idxAEnd = idxABegin + iAttrSizes[ip];
440 for( size_t ic = idxABegin; ic < idxAEnd; ++ic )
441 {
442 AttrInfoArray& attrs = object.m_attrs;
443
444 // attribute
445 const std::string &name = iAttrNames[ic];
446 attrs.push_back( AttrInfo( name ) );
447 AttrInfo& info = attrs[attrs.size()- 1];
448
449 // masks
450 if ( iHasMask[ic] )
451 {
452 const size_t length = iMaskBits[idxMask*6];
453 const uint32_t* data = &iMaskBits[idxMask*6+1];
454
455 info.m_mask = new MaskInfo;
456 info.m_mask->m_numFields = length;
457 memcpy( info.m_mask->m_data,
458 data, sizeof(uint32_t) * length );
459
460 idxMask++;
461 }
462
463 // metadata
464 if (iHasMeta[ic] )
465 {
466 info.m_meta = iMetaStrs[idxMeta++];
467 }
468 }
469 idxABegin = idxAEnd;
470 }
471 }
472
473 } // End namespace ALEMBIC_VERSION_NS
474
475 using namespace ALEMBIC_VERSION_NS;
476
477 } // End namespace AbcCoreHDF5
478 } // End namespace Alembic
479
480