Coverage Report

Created: 2024-09-08 06:41

/src/alembic/lib/Alembic/Ogawa/OGroup.cpp
Line
Count
Source (jump to first uncovered line)
1
//-*****************************************************************************
2
//
3
// Copyright (c) 2013,
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 Industrial Light & Magic nor the names of
19
// its contributors may be used to endorse or promote products derived
20
// from this software without specific prior written permission.
21
//
22
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
//
34
//-*****************************************************************************
35
36
#include <Alembic/Ogawa/OGroup.h>
37
#include <Alembic/Ogawa/OArchive.h>
38
#include <Alembic/Ogawa/OData.h>
39
#include <Alembic/Ogawa/OStream.h>
40
41
namespace Alembic {
42
namespace Ogawa {
43
namespace ALEMBIC_VERSION_NS {
44
45
typedef std::pair< OGroupPtr, Alembic::Util::uint64_t > ParentPair;
46
typedef std::vector< ParentPair > ParentPairVec;
47
48
class OGroup::PrivateData
49
{
50
public:
51
0
    PrivateData() {};
52
0
    ~PrivateData() {};
53
54
    OStreamPtr stream;
55
56
    // used before freeze
57
    ParentPairVec parents;
58
59
    // used before and after freeze
60
    std::vector<Alembic::Util::uint64_t> childVec;
61
62
    // set after freeze
63
    Alembic::Util::uint64_t pos;
64
};
65
66
OGroup::OGroup(OGroupPtr iParent, Alembic::Util::uint64_t iIndex)
67
    : mData(new OGroup::PrivateData())
68
0
{
69
0
    mData->stream = iParent->mData->stream;
70
0
    mData->parents.push_back( ParentPair(iParent, iIndex) );
71
0
    mData->pos = INVALID_GROUP;
72
0
}
73
74
OGroup::OGroup(OStreamPtr iStream)
75
    : mData(new OGroup::PrivateData())
76
0
{
77
0
    mData->stream = iStream;
78
0
    mData->parents.push_back(ParentPair(OGroupPtr(), 0));
79
0
    mData->pos = INVALID_GROUP;
80
0
}
81
82
OGroup::~OGroup()
83
0
{
84
0
    freeze();
85
0
}
86
87
OGroupPtr OGroup::addGroup()
88
0
{
89
0
    OGroupPtr child;
90
0
    if (!isFrozen())
91
0
    {
92
0
        mData->childVec.push_back(0);
93
0
        child.reset(new OGroup(shared_from_this(), mData->childVec.size() - 1));
94
0
    }
95
0
    return child;
96
0
}
97
98
ODataPtr OGroup::createData(Alembic::Util::uint64_t iSize, const void * iData)
99
0
{
100
0
    ODataPtr child;
101
0
    if (isFrozen())
102
0
    {
103
0
        return child;
104
0
    }
105
106
0
    if (iSize == 0)
107
0
    {
108
0
        mData->childVec.push_back(EMPTY_DATA);
109
0
        child.reset(new OData());
110
0
        return child;
111
0
    }
112
113
0
    Alembic::Util::uint64_t pos = mData->stream->getAndSeekEndPos();
114
115
0
    Alembic::Util::uint64_t size = iSize;
116
0
    mData->stream->write(&size, 8);
117
0
    mData->stream->write(iData, iSize);
118
119
0
    child.reset(new OData(mData->stream, pos, iSize));
120
121
0
    return child;
122
0
}
123
124
ODataPtr OGroup::addData(Alembic::Util::uint64_t iSize, const void * iData)
125
0
{
126
0
    ODataPtr child = OGroup::createData(iSize, iData);
127
0
    if (child)
128
0
    {
129
        // flip top bit for data so we can easily distinguish between it and
130
        // a group
131
0
        mData->childVec.push_back(child->getPos() | 0x8000000000000000ULL);
132
0
    }
133
0
    return child;
134
0
}
135
136
ODataPtr OGroup::createData(Alembic::Util::uint64_t iNumData,
137
                            const Alembic::Util::uint64_t * iSizes,
138
                            const void ** iDatas)
139
0
{
140
0
    ODataPtr child;
141
0
    if (isFrozen())
142
0
    {
143
0
        return child;
144
0
    }
145
146
0
    Alembic::Util::uint64_t totalSize = 0;
147
0
    for (Alembic::Util::uint64_t i = 0; i < iNumData; ++i)
148
0
    {
149
0
        totalSize += iSizes[i];
150
0
    }
151
152
0
    if (totalSize == 0)
153
0
    {
154
0
        mData->childVec.push_back(EMPTY_DATA);
155
0
        child.reset(new OData());
156
0
        return child;
157
0
    }
158
159
0
    Alembic::Util::uint64_t pos = mData->stream->getAndSeekEndPos();
160
161
0
    mData->stream->write(&totalSize, 8);
162
0
    for (Alembic::Util::uint64_t i = 0; i < iNumData; ++i)
163
0
    {
164
0
        Alembic::Util::uint64_t size = iSizes[i];
165
0
        if (size != 0)
166
0
        {
167
0
            mData->stream->write(iDatas[i], size);
168
0
        }
169
0
    }
170
171
0
    child.reset(new OData(mData->stream, pos, totalSize));
172
173
0
    return child;
174
0
}
175
176
ODataPtr OGroup::addData(Alembic::Util::uint64_t iNumData,
177
                         const Alembic::Util::uint64_t * iSizes,
178
                         const void ** iDatas)
179
0
{
180
0
    ODataPtr child = createData(iNumData, iSizes, iDatas);
181
0
    if (child)
182
0
    {
183
        // flip top bit for data so we can easily distinguish between it and
184
        // a group
185
0
        mData->childVec.push_back(child->getPos() | 0x8000000000000000ULL);
186
0
    }
187
0
    return child;
188
0
}
189
190
void OGroup::addData(ODataPtr iData)
191
0
{
192
0
    if (!isFrozen())
193
0
    {
194
0
        mData->childVec.push_back(iData->getPos() | 0x8000000000000000ULL);
195
0
    }
196
0
}
197
198
void OGroup::addGroup(OGroupPtr iGroup)
199
0
{
200
0
    if (!isFrozen())
201
0
    {
202
0
        if (iGroup->isFrozen())
203
0
        {
204
0
            mData->childVec.push_back(iGroup->mData->pos);
205
0
        }
206
0
        else
207
0
        {
208
0
            mData->childVec.push_back(EMPTY_GROUP);
209
0
            iGroup->mData->parents.push_back(
210
0
                ParentPair(shared_from_this(), mData->childVec.size() - 1));
211
0
        }
212
0
    }
213
0
}
214
215
void OGroup::addEmptyGroup()
216
0
{
217
0
    if (!isFrozen())
218
0
    {
219
0
        mData->childVec.push_back(EMPTY_GROUP);
220
0
    }
221
0
}
222
223
void OGroup::addEmptyData()
224
0
{
225
0
    if (!isFrozen())
226
0
    {
227
0
        mData->childVec.push_back(EMPTY_DATA);
228
0
    }
229
0
}
230
231
// no more children can be added, commit to the stream
232
void OGroup::freeze()
233
0
{
234
    // bail if we've already done this work
235
0
    if (isFrozen())
236
0
    {
237
0
        return;
238
0
    }
239
240
    // we ended up not adding any children, so no need to commit this group
241
    // to disk, use empty group instead
242
0
    if (mData->childVec.empty())
243
0
    {
244
0
        mData->pos = 0;
245
0
    }
246
0
    else
247
0
    {
248
0
        mData->pos = mData->stream->getAndSeekEndPos();
249
0
        Alembic::Util::uint64_t size = mData->childVec.size();
250
0
        mData->stream->write(&size, 8);
251
0
        mData->stream->write(&mData->childVec.front(), size*8);
252
0
    }
253
254
    // go through and update each of the parents
255
0
    ParentPairVec::iterator it;
256
0
    for(it = mData->parents.begin(); it != mData->parents.end(); ++it)
257
0
    {
258
        // special group owned by the archive
259
0
        if (!it->first && it->second == 0)
260
0
        {
261
0
            mData->stream->seek(8);
262
0
            mData->stream->write(&mData->pos, 8);
263
0
            continue;
264
0
        }
265
0
        else if (it->first->isFrozen())
266
0
        {
267
0
            mData->stream->seek(it->first->mData->pos + (it->second + 1) * 8);
268
0
            mData->stream->write(&mData->pos, 8);
269
0
        }
270
0
        it->first->mData->childVec[it->second] = mData->pos;
271
0
    }
272
273
0
    mData->parents.clear();
274
275
0
}
276
277
bool OGroup::isFrozen()
278
0
{
279
0
    return mData->pos != INVALID_GROUP;
280
0
}
281
282
Alembic::Util::uint64_t OGroup::getNumChildren() const
283
0
{
284
0
    return mData->childVec.size();
285
0
}
286
287
bool OGroup::isChildGroup(Alembic::Util::uint64_t iIndex) const
288
0
{
289
0
    return (iIndex < mData->childVec.size() &&
290
0
            (mData->childVec[iIndex] & EMPTY_DATA) == 0);
291
0
}
292
293
bool OGroup::isChildData(Alembic::Util::uint64_t iIndex) const
294
0
{
295
0
    return (iIndex < mData->childVec.size() &&
296
0
            (mData->childVec[iIndex] & EMPTY_DATA) != 0);
297
0
}
298
299
bool OGroup::isChildEmptyGroup(Alembic::Util::uint64_t iIndex) const
300
0
{
301
0
    return (iIndex < mData->childVec.size() &&
302
0
            mData->childVec[iIndex] == EMPTY_GROUP);
303
0
}
304
305
bool OGroup::isChildEmptyData(Alembic::Util::uint64_t iIndex) const
306
0
{
307
0
    return (iIndex < mData->childVec.size() &&
308
0
        mData->childVec[iIndex] == EMPTY_DATA);
309
0
}
310
311
void OGroup::replaceData(Alembic::Util::uint64_t iIndex, ODataPtr iData)
312
0
{
313
0
    if (!isChildData(iIndex))
314
0
    {
315
0
        return;
316
0
    }
317
318
0
    Alembic::Util::uint64_t pos = iData->getPos() | 0x8000000000000000ULL;
319
0
    if (isFrozen())
320
0
    {
321
0
        mData->stream->seek(mData->pos + (iIndex + 1) * 8);
322
0
        mData->stream->write(&pos, 8);
323
0
    }
324
0
    mData->childVec[iIndex] = pos;
325
0
}
326
327
} // End namespace ALEMBIC_VERSION_NS
328
} // End namespace Ogawa
329
} // End namespace Alembic