Coverage Report

Created: 2023-03-26 07:07

/src/alembic/lib/Alembic/Abc/IObject.cpp
Line
Count
Source (jump to first uncovered line)
1
//-*****************************************************************************
2
//
3
// Copyright (c) 2009-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 <Alembic/Abc/IObject.h>
38
#include <Alembic/Abc/IArchive.h>
39
#include <Alembic/Abc/ICompoundProperty.h>
40
#include <Alembic/Abc/ITypedScalarProperty.h>
41
42
namespace Alembic {
43
namespace Abc {
44
namespace ALEMBIC_VERSION_NS {
45
46
//-*****************************************************************************
47
// Nothing at the moment, this is just here as a debug entry point for
48
// tracking down problems with reference counting.
49
IObject::~IObject()
50
33
{
51
    // Nothing for now.
52
    // Mostly here in case we need to add reference-counting debug code.
53
    //std::cout << "IObject::~IObject() name: "
54
    //          << m_object->getName()
55
    //          << std::endl
56
    //          << "\tUse count of writer ptr: "
57
    //          << m_object.use_count() << std::endl;
58
33
}
59
60
namespace {
61
62
const AbcA::ObjectHeader g_ohd;
63
64
}
65
66
//-*****************************************************************************
67
const AbcA::ObjectHeader &IObject::getHeader() const
68
33
{
69
66
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getHeader()" );
70
71
66
    if ( m_object )
72
33
    {
73
33
        return m_object->getHeader();
74
33
    }
75
76
66
    ALEMBIC_ABC_SAFE_CALL_END();
77
78
    // Not all error handlers throw, so have a default behavior.
79
0
    return g_ohd;
80
33
};
81
82
//-*****************************************************************************
83
const std::string &IObject::getName() const
84
0
{
85
    // Get the name of the original object
86
0
    if ( m_instanceObject )
87
0
    {
88
0
        return m_instanceObject->getHeader().getName();
89
0
    }
90
91
0
    return m_object->getHeader().getName();
92
0
}
93
94
//-*****************************************************************************
95
const std::string &IObject::getFullName() const
96
0
{
97
0
    if ( !m_instancedFullName.empty() )
98
0
    {
99
0
        return m_instancedFullName;
100
0
    }
101
102
0
    return getHeader().getFullName();
103
0
}
104
105
//-*****************************************************************************
106
IArchive IObject::getArchive() const
107
0
{
108
109
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getArchive()" );
110
111
    // proxies and targets are currently required to be in the
112
    // same archive. Just use the m_object archive.
113
0
    if ( m_object )
114
0
    {
115
0
        return IArchive( m_object->getArchive(),
116
0
                         getErrorHandlerPolicy() );
117
0
    }
118
119
0
    ALEMBIC_ABC_SAFE_CALL_END();
120
121
    // Not all error handlers throw. Have a default.
122
0
    return IArchive();
123
0
}
124
125
namespace { // anonymous
126
127
static inline
128
std::string readInstanceSource( AbcA::CompoundPropertyReaderPtr iProp )
129
0
{
130
0
    if ( !iProp || !iProp->getPropertyHeader(".instanceSource") )
131
0
    {
132
0
        return std::string();
133
0
    }
134
135
0
    IStringProperty instanceSourceProp( iProp, ".instanceSource" );
136
0
    if ( !instanceSourceProp )
137
0
        return std::string();
138
139
0
    return instanceSourceProp.getValue();
140
0
}
141
142
static inline
143
AbcA::ObjectReaderPtr objectReaderByName( AbcA::ObjectReaderPtr iObj,
144
                                          const std::string & iInstanceSource );
145
146
static inline
147
AbcA::ObjectReaderPtr recurse( AbcA::ObjectReaderPtr iObj,
148
                               const std::string & iInstanceSource,
149
                               std::size_t iCurPos )
150
0
{
151
0
    std::size_t nextSlash = iInstanceSource.find( '/', iCurPos );
152
0
    std::string childName;
153
0
    if ( nextSlash == std::string::npos )
154
0
    {
155
0
        childName = iInstanceSource.substr( iCurPos );
156
0
    }
157
0
    else
158
0
    {
159
0
        childName = iInstanceSource.substr( iCurPos, nextSlash - iCurPos );
160
0
    }
161
162
0
    AbcA::ObjectReaderPtr child = iObj->getChild( childName );
163
164
0
    if ( child && nextSlash != std::string::npos )
165
0
    {
166
        // we hit an instance so we have to evaluate down to the correct spot
167
0
        if ( child->getMetaData().get("isInstance") == "1" )
168
0
        {
169
            // get and recursively walk down this other path
170
0
            AbcA::CompoundPropertyReaderPtr prop = child->getProperties();
171
0
            std::string instanceSource = readInstanceSource( prop );
172
0
            child = objectReaderByName( child, instanceSource);
173
0
        }
174
0
        return recurse( child, iInstanceSource, nextSlash + 1 );
175
0
    }
176
177
    // child not found, or we are on our last child
178
0
    return child;
179
0
}
180
181
//-*****************************************************************************
182
static inline
183
AbcA::ObjectReaderPtr objectReaderByName( AbcA::ObjectReaderPtr iObj,
184
                                          const std::string & iInstanceSource )
185
0
{
186
0
    if ( iInstanceSource.empty() || ! iObj )
187
0
        return AbcA::ObjectReaderPtr();
188
189
0
    std::size_t curPos = 0;
190
0
    if ( iInstanceSource[0] == '/' )
191
0
    {
192
0
        curPos = 1;
193
0
    }
194
195
0
    AbcA::ObjectReaderPtr obj = iObj->getArchive()->getTop();
196
0
    return recurse( obj, iInstanceSource, curPos );
197
0
}
198
199
//-*****************************************************************************
200
static inline
201
std::string getParentFullName( const std::string& iChildFullName )
202
0
{
203
0
    size_t pos = iChildFullName.rfind('/');
204
205
0
    if ( pos == std::string::npos || pos == 0 )
206
0
    {
207
0
        return std::string();
208
0
    }
209
210
0
    return iChildFullName.substr(0, pos);
211
0
}
212
213
}  // end anonymous namespace
214
215
//-*****************************************************************************
216
IObject IObject::getParent() const
217
0
{
218
219
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getParent()" );
220
221
0
    if ( !m_instancedFullName.empty() )
222
0
    {
223
0
        std::string parentFullName = getParentFullName( m_instancedFullName );
224
225
0
        AbcA::ObjectReaderPtr parentPtr = m_object->getParent();
226
0
        bool setFullName = false;
227
228
        // if the instanced full name doesn't match the parents full name
229
        // then we have an instanced situation where we need to carefully
230
        // walk the hierarchy to make sure we end up with the correct parent
231
232
        // If the names do match, then the parent isn't a part of the instance
233
        // and so we don't need to set that full name
234
0
        if ( parentPtr && !parentFullName.empty() &&
235
0
             parentFullName != parentPtr->getFullName() )
236
0
        {
237
0
            parentPtr = objectReaderByName( parentPtr, parentFullName );
238
0
            setFullName = true;
239
0
        }
240
241
0
        IObject obj( parentPtr,
242
0
                     getErrorHandlerPolicy() );
243
244
0
        if ( setFullName )
245
0
        {
246
0
            obj.setInstancedFullName( parentFullName );
247
0
        }
248
249
0
        return obj;
250
0
    }
251
0
    else if ( m_object )
252
0
    {
253
0
        return IObject( m_object->getParent(),
254
0
                        getErrorHandlerPolicy() );
255
0
    }
256
257
0
    ALEMBIC_ABC_SAFE_CALL_END();
258
259
    // Not all error handlers throw. Have a default.
260
0
    return IObject();
261
0
}
262
263
//-*****************************************************************************
264
size_t IObject::getNumChildren() const
265
33
{
266
267
66
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getNumChildren()" );
268
269
66
    if ( m_object )
270
33
    {
271
33
        return m_object->getNumChildren();
272
33
    }
273
274
66
    ALEMBIC_ABC_SAFE_CALL_END();
275
276
    // Not all error handlers throw, have a default.
277
0
    return 0;
278
33
}
279
280
//-*****************************************************************************
281
const AbcA::ObjectHeader &IObject::getChildHeader( size_t iIdx ) const
282
0
{
283
284
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getChildHeader()" );
285
286
0
    if ( m_object )
287
0
    {
288
0
        return m_object->getChildHeader( iIdx );
289
0
    }
290
291
0
    ALEMBIC_ABC_SAFE_CALL_END();
292
293
    // Not all error handlers throw, have a default.
294
0
    static const AbcA::ObjectHeader hd;
295
0
    return hd;
296
0
}
297
298
//-*****************************************************************************
299
const AbcA::ObjectHeader *
300
IObject::getChildHeader( const std::string &iName ) const
301
0
{
302
303
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getChildHeader( name )" );
304
305
0
    if ( m_object )
306
0
    {
307
0
        return m_object->getChildHeader( iName );
308
0
    }
309
310
0
    ALEMBIC_ABC_SAFE_CALL_END();
311
312
    // Not all error handlers throw, have a default.
313
0
    return NULL;
314
0
}
315
316
//-*****************************************************************************
317
IObject IObject::getChild( size_t iChildIndex ) const
318
0
{
319
320
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getChild()" );
321
322
0
    if ( m_object )
323
0
    {
324
0
        IObject obj( m_object->getChild( iChildIndex ),
325
0
                     getErrorHandlerPolicy() );
326
327
0
        if ( !m_instancedFullName.empty() )
328
0
        {
329
0
            obj.setInstancedFullName(
330
0
                m_instancedFullName + std::string("/") + obj.getName() );
331
0
        }
332
333
0
        return obj;
334
0
    }
335
336
0
    ALEMBIC_ABC_SAFE_CALL_END();
337
338
    // Not all error handlers throw, return something in case.
339
0
    return IObject();
340
0
}
341
342
//-*****************************************************************************
343
IObject IObject::getChild( const std::string &iChildName ) const
344
0
{
345
346
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getChild()" );
347
348
0
    if ( m_object )
349
0
    {
350
0
        IObject obj( m_object->getChild( iChildName ),
351
0
                     getErrorHandlerPolicy() );
352
353
0
        if ( !m_instancedFullName.empty() )
354
0
        {
355
0
            obj.setInstancedFullName(
356
0
                m_instancedFullName + std::string("/") + obj.getName() );
357
0
        }
358
359
0
        return obj;
360
0
    }
361
362
0
    ALEMBIC_ABC_SAFE_CALL_END();
363
364
    // Not all error handlers throw, return something in case.
365
0
    return IObject();
366
0
}
367
368
//-*****************************************************************************
369
void IObject::reset()
370
0
{
371
0
    m_instanceObject.reset();
372
0
    m_instancedFullName.clear();
373
374
0
    m_object.reset();
375
0
    Base::reset();
376
0
}
377
378
//-*****************************************************************************
379
ICompoundProperty IObject::getProperties() const
380
0
{
381
382
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getProperties()" );
383
384
0
    if ( m_object )
385
0
    {
386
0
        return ICompoundProperty( m_object->getProperties() );
387
0
    }
388
389
0
    ALEMBIC_ABC_SAFE_CALL_END();
390
391
    // Not all error handlers throw, have a default.
392
0
    return ICompoundProperty();
393
0
}
394
395
//-*****************************************************************************
396
bool IObject::getPropertiesHash( Util::Digest & oDigest )
397
0
{
398
0
   ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getPropertiesHash()" );
399
400
0
    if ( m_object )
401
0
    {
402
0
        return m_object->getPropertiesHash( oDigest );
403
0
    }
404
405
0
    ALEMBIC_ABC_SAFE_CALL_END();
406
407
    // Not all error handlers throw, have a default.
408
0
    return false;
409
0
}
410
411
412
//-*****************************************************************************
413
bool IObject::getChildrenHash( Util::Digest & oDigest )
414
0
{
415
0
   ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::getChildrenHash()" );
416
417
0
    if ( m_object )
418
0
    {
419
0
        return m_object->getChildrenHash( oDigest );
420
0
    }
421
422
0
    ALEMBIC_ABC_SAFE_CALL_END();
423
424
    // Not all error handlers throw, have a default.
425
0
    return false;
426
0
}
427
428
//-*****************************************************************************
429
bool IObject::isInstanceRoot() const
430
0
{
431
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::isInstanceRoot()" );
432
433
0
    if ( m_instanceObject )
434
0
    {
435
0
        return true;
436
0
    }
437
438
0
    ALEMBIC_ABC_SAFE_CALL_END();
439
440
0
    return false;
441
0
}
442
443
//-*****************************************************************************
444
bool IObject::isInstanceDescendant() const
445
0
{
446
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::isInstanceDescendant()" );
447
448
0
    if ( !m_instancedFullName.empty() )
449
0
    {
450
0
        return true;
451
0
    }
452
453
0
    ALEMBIC_ABC_SAFE_CALL_END();
454
455
0
    return false;
456
0
}
457
458
//-*****************************************************************************
459
std::string IObject::instanceSourcePath() const
460
0
{
461
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::instanceSourcePath()" );
462
463
0
    if ( !m_instanceObject )
464
0
    {
465
0
        return std::string();
466
0
    }
467
468
0
    AbcA::CompoundPropertyReaderPtr props = m_instanceObject->getProperties();
469
0
    return readInstanceSource( props );
470
471
0
    ALEMBIC_ABC_SAFE_CALL_END();
472
473
0
    return std::string();
474
0
}
475
476
//-*****************************************************************************
477
void IObject::setInstancedFullName( const std::string& parentPath ) const
478
0
{
479
0
    m_instancedFullName = parentPath;
480
0
}
481
482
//-*****************************************************************************
483
bool IObject::isChildInstance( size_t iChildIndex ) const
484
0
{
485
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN(
486
0
        "IObject::isChildInstanced(size_t iChildIndex)" );
487
488
0
    IObject child = getChild( iChildIndex );
489
490
0
    if ( child.valid() )
491
0
    {
492
0
        return child.isInstanceRoot();
493
0
    }
494
495
0
    ALEMBIC_ABC_SAFE_CALL_END();
496
497
0
    return false;
498
0
}
499
500
//-*****************************************************************************
501
bool IObject::isChildInstance( const std::string &iChildName ) const
502
0
{
503
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN(
504
0
        "IObject::isChildInstance(const std::string &iChildName)" );
505
506
0
    IObject child = getChild( iChildName );
507
508
0
    if ( child.valid() )
509
0
    {
510
0
        return child.isInstanceRoot();
511
0
    }
512
513
0
    ALEMBIC_ABC_SAFE_CALL_END();
514
515
0
    return false;
516
0
}
517
518
//-*****************************************************************************
519
void IObject::init( IArchive & iArchive, const Argument &iArg0 )
520
0
{
521
    // Set the error handling policy
522
0
    getErrorHandler().setPolicy(
523
0
        GetErrorHandlerPolicy( iArchive, iArg0 ) );
524
525
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::init( IArchive )" );
526
527
0
    m_object = iArchive.getTop().getPtr();
528
529
0
    ALEMBIC_ABC_SAFE_CALL_END_RESET();
530
0
}
531
532
//-*****************************************************************************
533
void IObject::init( AbcA::ObjectReaderPtr iParent,
534
                    const std::string &iName,
535
                    ErrorHandler::Policy iPolicy )
536
0
{
537
0
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IObject::init()" );
538
539
0
    getErrorHandler().setPolicy( iPolicy );
540
541
0
    m_object = iParent->getChild( iName );
542
543
0
    ALEMBIC_ABC_SAFE_CALL_END();
544
0
}
545
546
//-*****************************************************************************
547
void IObject::initInstance()
548
33
{
549
550
    // not an instance so m_instanceObject will stay empty
551
33
    if ( !m_object || m_object->getMetaData().get("isInstance") != "1")
552
33
    {
553
33
        return;
554
33
    }
555
556
0
    AbcA::CompoundPropertyReaderPtr propsPtr = m_object->getProperties();
557
0
    std::string instanceSource = readInstanceSource( propsPtr );
558
0
    AbcA::ObjectReaderPtr targetObject =
559
0
        objectReaderByName( m_object, instanceSource );
560
561
0
    m_instanceObject = m_object;
562
0
    m_object = targetObject;
563
564
    // initialize the full name to the instance full name
565
0
    if ( m_instanceObject != 0 )
566
0
    {
567
0
        m_instancedFullName = m_instanceObject->getFullName();
568
0
    }
569
0
}
570
571
} // End namespace ALEMBIC_VERSION_NS
572
} // End namespace Abc
573
} // End namespace Alembic