rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file Provides cheat implementations for IOSystem and IOStream to
|
nuclear@0
|
43 * redirect exporter output to a blob chain.*/
|
nuclear@0
|
44
|
nuclear@0
|
45 #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
|
nuclear@0
|
46 #define AI_BLOBIOSYSTEM_H_INCLUDED
|
nuclear@0
|
47
|
nuclear@0
|
48 namespace Assimp {
|
nuclear@0
|
49 class BlobIOSystem;
|
nuclear@0
|
50
|
nuclear@0
|
51 // --------------------------------------------------------------------------------------------
|
nuclear@0
|
52 /** Redirect IOStream to a blob */
|
nuclear@0
|
53 // --------------------------------------------------------------------------------------------
|
nuclear@0
|
54 class BlobIOStream : public IOStream
|
nuclear@0
|
55 {
|
nuclear@0
|
56 public:
|
nuclear@0
|
57
|
nuclear@0
|
58 BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
|
nuclear@0
|
59 : buffer()
|
nuclear@0
|
60 , cur_size()
|
nuclear@0
|
61 , file_size()
|
nuclear@0
|
62 , cursor()
|
nuclear@0
|
63 , initial(initial)
|
nuclear@0
|
64 , file(file)
|
nuclear@0
|
65 , creator(creator)
|
nuclear@0
|
66 {
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69
|
nuclear@0
|
70 virtual ~BlobIOStream();
|
nuclear@0
|
71
|
nuclear@0
|
72 public:
|
nuclear@0
|
73
|
nuclear@0
|
74 // -------------------------------------------------------------------
|
nuclear@0
|
75 aiExportDataBlob* GetBlob()
|
nuclear@0
|
76 {
|
nuclear@0
|
77 aiExportDataBlob* blob = new aiExportDataBlob();
|
nuclear@0
|
78 blob->size = file_size;
|
nuclear@0
|
79 blob->data = buffer;
|
nuclear@0
|
80
|
nuclear@0
|
81 buffer = NULL;
|
nuclear@0
|
82
|
nuclear@0
|
83 return blob;
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86
|
nuclear@0
|
87 public:
|
nuclear@0
|
88
|
nuclear@0
|
89
|
nuclear@0
|
90 // -------------------------------------------------------------------
|
nuclear@0
|
91 virtual size_t Read(void* pvBuffer,
|
nuclear@0
|
92 size_t pSize,
|
nuclear@0
|
93 size_t pCount)
|
nuclear@0
|
94 {
|
nuclear@0
|
95 return 0;
|
nuclear@0
|
96 }
|
nuclear@0
|
97
|
nuclear@0
|
98 // -------------------------------------------------------------------
|
nuclear@0
|
99 virtual size_t Write(const void* pvBuffer,
|
nuclear@0
|
100 size_t pSize,
|
nuclear@0
|
101 size_t pCount)
|
nuclear@0
|
102 {
|
nuclear@0
|
103 pSize *= pCount;
|
nuclear@0
|
104 if (cursor + pSize > cur_size) {
|
nuclear@0
|
105 Grow(cursor + pSize);
|
nuclear@0
|
106 }
|
nuclear@0
|
107
|
nuclear@0
|
108 memcpy(buffer+cursor, pvBuffer, pSize);
|
nuclear@0
|
109 cursor += pSize;
|
nuclear@0
|
110
|
nuclear@0
|
111 file_size = std::max(file_size,cursor);
|
nuclear@0
|
112 return pCount;
|
nuclear@0
|
113 }
|
nuclear@0
|
114
|
nuclear@0
|
115 // -------------------------------------------------------------------
|
nuclear@0
|
116 virtual aiReturn Seek(size_t pOffset,
|
nuclear@0
|
117 aiOrigin pOrigin)
|
nuclear@0
|
118 {
|
nuclear@0
|
119 switch(pOrigin)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 case aiOrigin_CUR:
|
nuclear@0
|
122 cursor += pOffset;
|
nuclear@0
|
123
|
nuclear@0
|
124 case aiOrigin_END:
|
nuclear@0
|
125 cursor = file_size - pOffset;
|
nuclear@0
|
126
|
nuclear@0
|
127 case aiOrigin_SET:
|
nuclear@0
|
128 cursor = pOffset;
|
nuclear@0
|
129 break;
|
nuclear@0
|
130
|
nuclear@0
|
131 default:
|
nuclear@0
|
132 return AI_FAILURE;
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 if (cursor > file_size) {
|
nuclear@0
|
136 Grow(cursor);
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@0
|
139 file_size = std::max(cursor,file_size);
|
nuclear@0
|
140 return AI_SUCCESS;
|
nuclear@0
|
141 }
|
nuclear@0
|
142
|
nuclear@0
|
143 // -------------------------------------------------------------------
|
nuclear@0
|
144 virtual size_t Tell() const
|
nuclear@0
|
145 {
|
nuclear@0
|
146 return cursor;
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 // -------------------------------------------------------------------
|
nuclear@0
|
150 virtual size_t FileSize() const
|
nuclear@0
|
151 {
|
nuclear@0
|
152 return file_size;
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 // -------------------------------------------------------------------
|
nuclear@0
|
156 virtual void Flush()
|
nuclear@0
|
157 {
|
nuclear@0
|
158 // ignore
|
nuclear@0
|
159 }
|
nuclear@0
|
160
|
nuclear@0
|
161
|
nuclear@0
|
162
|
nuclear@0
|
163 private:
|
nuclear@0
|
164
|
nuclear@0
|
165 // -------------------------------------------------------------------
|
nuclear@0
|
166 void Grow(size_t need = 0)
|
nuclear@0
|
167 {
|
nuclear@0
|
168 // 1.5 and phi are very heap-friendly growth factors (the first
|
nuclear@0
|
169 // allows for frequent re-use of heap blocks, the second
|
nuclear@0
|
170 // forms a fibonacci sequence with similar characteristics -
|
nuclear@0
|
171 // since this heavily depends on the heap implementation
|
nuclear@0
|
172 // and other factors as well, i'll just go with 1.5 since
|
nuclear@0
|
173 // it is quicker to compute).
|
nuclear@0
|
174 size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
|
nuclear@0
|
175
|
nuclear@0
|
176 const uint8_t* const old = buffer;
|
nuclear@0
|
177 buffer = new uint8_t[new_size];
|
nuclear@0
|
178
|
nuclear@0
|
179 if (old) {
|
nuclear@0
|
180 memcpy(buffer,old,cur_size);
|
nuclear@0
|
181 delete[] old;
|
nuclear@0
|
182 }
|
nuclear@0
|
183
|
nuclear@0
|
184 cur_size = new_size;
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187 private:
|
nuclear@0
|
188
|
nuclear@0
|
189 uint8_t* buffer;
|
nuclear@0
|
190 size_t cur_size,file_size, cursor, initial;
|
nuclear@0
|
191
|
nuclear@0
|
192 const std::string file;
|
nuclear@0
|
193 BlobIOSystem* const creator;
|
nuclear@0
|
194 };
|
nuclear@0
|
195
|
nuclear@0
|
196
|
nuclear@0
|
197 #define AI_BLOBIO_MAGIC "$blobfile"
|
nuclear@0
|
198
|
nuclear@0
|
199 // --------------------------------------------------------------------------------------------
|
nuclear@0
|
200 /** Redirect IOSystem to a blob */
|
nuclear@0
|
201 // --------------------------------------------------------------------------------------------
|
nuclear@0
|
202 class BlobIOSystem : public IOSystem
|
nuclear@0
|
203 {
|
nuclear@0
|
204
|
nuclear@0
|
205 friend class BlobIOStream;
|
nuclear@0
|
206 typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
|
nuclear@0
|
207
|
nuclear@0
|
208 public:
|
nuclear@0
|
209
|
nuclear@0
|
210 BlobIOSystem()
|
nuclear@0
|
211 {
|
nuclear@0
|
212 }
|
nuclear@0
|
213
|
nuclear@0
|
214 virtual ~BlobIOSystem()
|
nuclear@0
|
215 {
|
nuclear@0
|
216 BOOST_FOREACH(BlobEntry& blobby, blobs) {
|
nuclear@0
|
217 delete blobby.second;
|
nuclear@0
|
218 }
|
nuclear@0
|
219 }
|
nuclear@0
|
220
|
nuclear@0
|
221 public:
|
nuclear@0
|
222
|
nuclear@0
|
223 // -------------------------------------------------------------------
|
nuclear@0
|
224 const char* GetMagicFileName() const
|
nuclear@0
|
225 {
|
nuclear@0
|
226 return AI_BLOBIO_MAGIC;
|
nuclear@0
|
227 }
|
nuclear@0
|
228
|
nuclear@0
|
229
|
nuclear@0
|
230 // -------------------------------------------------------------------
|
nuclear@0
|
231 aiExportDataBlob* GetBlobChain()
|
nuclear@0
|
232 {
|
nuclear@0
|
233 // one must be the master
|
nuclear@0
|
234 aiExportDataBlob* master = NULL, *cur;
|
nuclear@0
|
235 BOOST_FOREACH(const BlobEntry& blobby, blobs) {
|
nuclear@0
|
236 if (blobby.first == AI_BLOBIO_MAGIC) {
|
nuclear@0
|
237 master = blobby.second;
|
nuclear@0
|
238 break;
|
nuclear@0
|
239 }
|
nuclear@0
|
240 }
|
nuclear@0
|
241 if (!master) {
|
nuclear@0
|
242 DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
|
nuclear@0
|
243 return NULL;
|
nuclear@0
|
244 }
|
nuclear@0
|
245
|
nuclear@0
|
246 master->name.Set("");
|
nuclear@0
|
247
|
nuclear@0
|
248 cur = master;
|
nuclear@0
|
249 BOOST_FOREACH(const BlobEntry& blobby, blobs) {
|
nuclear@0
|
250 if (blobby.second == master) {
|
nuclear@0
|
251 continue;
|
nuclear@0
|
252 }
|
nuclear@0
|
253
|
nuclear@0
|
254 cur->next = blobby.second;
|
nuclear@0
|
255 cur = cur->next;
|
nuclear@0
|
256
|
nuclear@0
|
257 // extract the file extension from the file written
|
nuclear@0
|
258 const std::string::size_type s = blobby.first.find_first_of('.');
|
nuclear@0
|
259 cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
|
nuclear@0
|
260 }
|
nuclear@0
|
261
|
nuclear@0
|
262 // give up blob ownership
|
nuclear@0
|
263 blobs.clear();
|
nuclear@0
|
264 return master;
|
nuclear@0
|
265 }
|
nuclear@0
|
266
|
nuclear@0
|
267 public:
|
nuclear@0
|
268
|
nuclear@0
|
269 // -------------------------------------------------------------------
|
nuclear@0
|
270 virtual bool Exists( const char* pFile) const {
|
nuclear@0
|
271 return created.find(std::string(pFile)) != created.end();
|
nuclear@0
|
272 }
|
nuclear@0
|
273
|
nuclear@0
|
274
|
nuclear@0
|
275 // -------------------------------------------------------------------
|
nuclear@0
|
276 virtual char getOsSeparator() const {
|
nuclear@0
|
277 return '/';
|
nuclear@0
|
278 }
|
nuclear@0
|
279
|
nuclear@0
|
280
|
nuclear@0
|
281 // -------------------------------------------------------------------
|
nuclear@0
|
282 virtual IOStream* Open(const char* pFile,
|
nuclear@0
|
283 const char* pMode)
|
nuclear@0
|
284 {
|
nuclear@0
|
285 if (pMode[0] != 'w') {
|
nuclear@0
|
286 return NULL;
|
nuclear@0
|
287 }
|
nuclear@0
|
288
|
nuclear@0
|
289 created.insert(std::string(pFile));
|
nuclear@0
|
290 return new BlobIOStream(this,std::string(pFile));
|
nuclear@0
|
291 }
|
nuclear@0
|
292
|
nuclear@0
|
293 // -------------------------------------------------------------------
|
nuclear@0
|
294 virtual void Close( IOStream* pFile)
|
nuclear@0
|
295 {
|
nuclear@0
|
296 delete pFile;
|
nuclear@0
|
297 }
|
nuclear@0
|
298
|
nuclear@0
|
299 private:
|
nuclear@0
|
300
|
nuclear@0
|
301 // -------------------------------------------------------------------
|
nuclear@0
|
302 void OnDestruct(const std::string& filename, BlobIOStream* child)
|
nuclear@0
|
303 {
|
nuclear@0
|
304 // we don't know in which the files are closed, so we
|
nuclear@0
|
305 // can't reliably say that the first must be the master
|
nuclear@0
|
306 // file ...
|
nuclear@0
|
307 blobs.push_back( BlobEntry(filename,child->GetBlob()) );
|
nuclear@0
|
308 }
|
nuclear@0
|
309
|
nuclear@0
|
310 private:
|
nuclear@0
|
311 std::set<std::string> created;
|
nuclear@0
|
312 std::vector< BlobEntry > blobs;
|
nuclear@0
|
313 };
|
nuclear@0
|
314
|
nuclear@0
|
315
|
nuclear@0
|
316 // --------------------------------------------------------------------------------------------
|
nuclear@0
|
317 BlobIOStream :: ~BlobIOStream()
|
nuclear@0
|
318 {
|
nuclear@0
|
319 creator->OnDestruct(file,this);
|
nuclear@0
|
320 delete[] buffer;
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323
|
nuclear@0
|
324 } // end Assimp
|
nuclear@0
|
325
|
nuclear@0
|
326 #endif
|