Field3D
OGroup.cpp
Go to the documentation of this file.
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 "OGroup.h"
37#include "OArchive.h"
38#include "OData.h"
39#include "OStream.h"
40
41namespace Alembic {
42namespace Ogawa {
43namespace ALEMBIC_VERSION_NS {
44
45typedef std::pair< OGroupPtr, Alembic::Util::uint64_t > ParentPair;
46typedef std::vector< ParentPair > ParentPairVec;
47
48class OGroup::PrivateData
49{
50public:
51 PrivateData() {};
52 ~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
66OGroup::OGroup(OGroupPtr iParent, Alembic::Util::uint64_t iIndex)
67 : mData(new OGroup::PrivateData())
68{
69 mData->stream = iParent->mData->stream;
70 mData->parents.push_back( ParentPair(iParent, iIndex) );
71 mData->pos = INVALID_GROUP;
72}
73
74OGroup::OGroup(OStreamPtr iStream)
75 : mData(new OGroup::PrivateData())
76{
77 mData->stream = iStream;
78 mData->parents.push_back(ParentPair(OGroupPtr(), 0));
79 mData->pos = INVALID_GROUP;
80}
81
82OGroup::~OGroup()
83{
84 freeze();
85}
86
87OGroupPtr OGroup::addGroup()
88{
89 OGroupPtr child;
90 if (!isFrozen())
91 {
92 mData->childVec.push_back(0);
93 child.reset(new OGroup(shared_from_this(), mData->childVec.size() - 1));
94 }
95 return child;
96}
97
98ODataPtr OGroup::createData(Alembic::Util::uint64_t iSize, const void * iData)
99{
100 ODataPtr child;
101 if (isFrozen())
102 {
103 return child;
104 }
105
106 if (iSize == 0)
107 {
108 mData->childVec.push_back(EMPTY_DATA);
109 child.reset(new OData());
110 return child;
111 }
112
113 Alembic::Util::uint64_t pos = mData->stream->getAndSeekEndPos();
114
115 Alembic::Util::uint64_t size = iSize;
116 mData->stream->write(&size, 8);
117 mData->stream->write(iData, iSize);
118
119 child.reset(new OData(mData->stream, pos, iSize));
120
121 return child;
122}
123
124ODataPtr OGroup::addData(Alembic::Util::uint64_t iSize, const void * iData)
125{
126 ODataPtr child = OGroup::createData(iSize, iData);
127 if (child)
128 {
129 // flip top bit for data so we can easily distinguish between it and
130 // a group
131 mData->childVec.push_back(child->getPos() | 0x8000000000000000ULL);
132 }
133 return child;
134}
135
136ODataPtr OGroup::createData(Alembic::Util::uint64_t iNumData,
137 const Alembic::Util::uint64_t * iSizes,
138 const void ** iDatas)
139{
140 ODataPtr child;
141 if (isFrozen())
142 {
143 return child;
144 }
145
146 Alembic::Util::uint64_t totalSize = 0;
147 for (Alembic::Util::uint64_t i = 0; i < iNumData; ++i)
148 {
149 totalSize += iSizes[i];
150 }
151
152 if (totalSize == 0)
153 {
154 mData->childVec.push_back(EMPTY_DATA);
155 child.reset(new OData());
156 return child;
157 }
158
159 Alembic::Util::uint64_t pos = mData->stream->getAndSeekEndPos();
160
161 mData->stream->write(&totalSize, 8);
162 for (Alembic::Util::uint64_t i = 0; i < iNumData; ++i)
163 {
164 Alembic::Util::uint64_t size = iSizes[i];
165 if (size != 0)
166 {
167 mData->stream->write(iDatas[i], size);
168 }
169 }
170
171 child.reset(new OData(mData->stream, pos, totalSize));
172
173 return child;
174}
175
176ODataPtr OGroup::addData(Alembic::Util::uint64_t iNumData,
177 const Alembic::Util::uint64_t * iSizes,
178 const void ** iDatas)
179{
180 ODataPtr child = createData(iNumData, iSizes, iDatas);
181 if (child)
182 {
183 // flip top bit for data so we can easily distinguish between it and
184 // a group
185 mData->childVec.push_back(child->getPos() | 0x8000000000000000ULL);
186 }
187 return child;
188}
189
190void OGroup::addData(ODataPtr iData)
191{
192 if (!isFrozen())
193 {
194 mData->childVec.push_back(iData->getPos() | 0x8000000000000000ULL);
195 }
196}
197
198void OGroup::addGroup(OGroupPtr iGroup)
199{
200 if (!isFrozen())
201 {
202 if (iGroup->isFrozen())
203 {
204 mData->childVec.push_back(iGroup->mData->pos);
205 }
206 else
207 {
208 mData->childVec.push_back(EMPTY_GROUP);
209 iGroup->mData->parents.push_back(
210 ParentPair(shared_from_this(), mData->childVec.size() - 1));
211 }
212 }
213}
214
215void OGroup::addEmptyGroup()
216{
217 if (!isFrozen())
218 {
219 mData->childVec.push_back(EMPTY_GROUP);
220 }
221}
222
223void OGroup::addEmptyData()
224{
225 if (!isFrozen())
226 {
227 mData->childVec.push_back(EMPTY_DATA);
228 }
229}
230
231// no more children can be added, commit to the stream
232void OGroup::freeze()
233{
234 // bail if we've already done this work
235 if (isFrozen())
236 {
237 return;
238 }
239
240 // we ended up not adding any children, so no need to commit this group
241 // to disk, use empty group instead
242 if (mData->childVec.empty())
243 {
244 mData->pos = 0;
245 }
246 else
247 {
248 mData->pos = mData->stream->getAndSeekEndPos();
249 Alembic::Util::uint64_t size = mData->childVec.size();
250 mData->stream->write(&size, 8);
251 mData->stream->write(&mData->childVec.front(), size*8);
252 }
253
254 // go through and update each of the parents
255 ParentPairVec::iterator it;
256 for(it = mData->parents.begin(); it != mData->parents.end(); ++it)
257 {
258 // special group owned by the archive
259 if (!it->first && it->second == 0)
260 {
261 mData->stream->seek(8);
262 mData->stream->write(&mData->pos, 8);
263 continue;
264 }
265 else if (it->first->isFrozen())
266 {
267 mData->stream->seek(it->first->mData->pos + (it->second + 1) * 8);
268 mData->stream->write(&mData->pos, 8);
269 }
270 it->first->mData->childVec[it->second] = mData->pos;
271 }
272
273 mData->parents.clear();
274
275}
276
277bool OGroup::isFrozen()
278{
279 return mData->pos != INVALID_GROUP;
280}
281
282Alembic::Util::uint64_t OGroup::getNumChildren() const
283{
284 return mData->childVec.size();
285}
286
287bool OGroup::isChildGroup(Alembic::Util::uint64_t iIndex) const
288{
289 return (iIndex < mData->childVec.size() &&
290 (mData->childVec[iIndex] & EMPTY_DATA) == 0);
291}
292
293bool OGroup::isChildData(Alembic::Util::uint64_t iIndex) const
294{
295 return (iIndex < mData->childVec.size() &&
296 (mData->childVec[iIndex] & EMPTY_DATA) != 0);
297}
298
299bool OGroup::isChildEmptyGroup(Alembic::Util::uint64_t iIndex) const
300{
301 return (iIndex < mData->childVec.size() &&
302 mData->childVec[iIndex] == EMPTY_GROUP);
303}
304
305bool OGroup::isChildEmptyData(Alembic::Util::uint64_t iIndex) const
306{
307 return (iIndex < mData->childVec.size() &&
308 mData->childVec[iIndex] == EMPTY_DATA);
309}
310
311void OGroup::replaceData(Alembic::Util::uint64_t iIndex, ODataPtr iData)
312{
313 if (!isChildData(iIndex))
314 {
315 return;
316 }
317
318 Alembic::Util::uint64_t pos = iData->getPos() | 0x8000000000000000ULL;
319 if (isFrozen())
320 {
321 mData->stream->seek(mData->pos + (iIndex + 1) * 8);
322 mData->stream->write(&pos, 8);
323 }
324 mData->childVec[iIndex] = pos;
325}
326
327} // End namespace ALEMBIC_VERSION_NS
328} // End namespace Ogawa
329} // End namespace Alembic
std::pair< OGroupPtr, Alembic::Util::uint64_t > ParentPair
Definition OGroup.cpp:45
std::vector< ParentPair > ParentPairVec
Definition OGroup.cpp:46