Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:30:07

0001 /*
0002 ---------------------------------------------------------------------------
0003 Open Asset Import Library (assimp)
0004 ---------------------------------------------------------------------------
0005 
0006 Copyright (c) 2006-2024, assimp team
0007 
0008 All rights reserved.
0009 
0010 Redistribution and use of this software in source and binary forms,
0011 with or without modification, are permitted provided that the following
0012 conditions are met:
0013 
0014 * Redistributions of source code must retain the above
0015   copyright notice, this list of conditions and the
0016   following disclaimer.
0017 
0018 * Redistributions in binary form must reproduce the above
0019   copyright notice, this list of conditions and the
0020   following disclaimer in the documentation and/or other
0021   materials provided with the distribution.
0022 
0023 * Neither the name of the assimp team, nor the names of its
0024   contributors may be used to endorse or promote products
0025   derived from this software without specific prior
0026   written permission of the assimp team.
0027 
0028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0031 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0033 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0034 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0035 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0036 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0038 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0039 ---------------------------------------------------------------------------
0040 */
0041 
0042 /** @file Provides cheat implementations for IOSystem and IOStream to
0043  *  redirect exporter output to a blob chain.*/
0044 
0045 #pragma once
0046 #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
0047 #define AI_BLOBIOSYSTEM_H_INCLUDED
0048 
0049 #ifdef __GNUC__
0050 #pragma GCC system_header
0051 #endif
0052 
0053 #include <assimp/cexport.h>
0054 #include <assimp/DefaultLogger.hpp>
0055 #include <assimp/IOStream.hpp>
0056 #include <assimp/IOSystem.hpp>
0057 #include <cstdint>
0058 #include <set>
0059 #include <vector>
0060 
0061 namespace Assimp {
0062 class BlobIOSystem;
0063 
0064 // --------------------------------------------------------------------------------------------
0065 /** Redirect IOStream to a blob */
0066 // --------------------------------------------------------------------------------------------
0067 class BlobIOStream : public IOStream {
0068 public:
0069     /// @brief The class constructor with all needed parameters
0070     /// @param creator  Pointer to the creator instance
0071     /// @param file     The filename
0072     /// @param initial  The initial size
0073     BlobIOStream(BlobIOSystem *creator, const std::string &file, size_t initial = 4096) :
0074             buffer(),
0075             cur_size(),
0076             file_size(),
0077             cursor(),
0078             initial(initial),
0079             file(file),
0080             creator(creator) {
0081         // empty
0082     }
0083 
0084     /// @brief  The class destructor.
0085     ~BlobIOStream() override;
0086 
0087 public:
0088     // -------------------------------------------------------------------
0089     aiExportDataBlob *GetBlob() {
0090         aiExportDataBlob *blob = new aiExportDataBlob();
0091         blob->size = file_size;
0092         blob->data = buffer;
0093 
0094         buffer = nullptr;
0095 
0096         return blob;
0097     }
0098 
0099     // -------------------------------------------------------------------
0100     size_t Read(void *, size_t, size_t) override {
0101         return 0;
0102     }
0103 
0104     // -------------------------------------------------------------------
0105     size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) override {
0106         pSize *= pCount;
0107         if (cursor + pSize > cur_size) {
0108             Grow(cursor + pSize);
0109         }
0110 
0111         memcpy(buffer + cursor, pvBuffer, pSize);
0112         cursor += pSize;
0113 
0114         file_size = std::max(file_size, cursor);
0115         return pCount;
0116     }
0117 
0118     // -------------------------------------------------------------------
0119     aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override {
0120         switch (pOrigin) {
0121             case aiOrigin_CUR:
0122                 cursor += pOffset;
0123                 break;
0124 
0125             case aiOrigin_END:
0126                 cursor = file_size - pOffset;
0127                 break;
0128 
0129             case aiOrigin_SET:
0130                 cursor = pOffset;
0131                 break;
0132 
0133             default:
0134                 return AI_FAILURE;
0135         }
0136 
0137         if (cursor > file_size) {
0138             Grow(cursor);
0139         }
0140 
0141         file_size = std::max(cursor, file_size);
0142 
0143         return AI_SUCCESS;
0144     }
0145 
0146     // -------------------------------------------------------------------
0147     size_t Tell() const override {
0148         return cursor;
0149     }
0150 
0151     // -------------------------------------------------------------------
0152     size_t FileSize() const override {
0153         return file_size;
0154     }
0155 
0156     // -------------------------------------------------------------------
0157     void Flush() override {
0158         // ignore
0159     }
0160 
0161 private:
0162     // -------------------------------------------------------------------
0163     void Grow(size_t need = 0) {
0164         // 1.5 and phi are very heap-friendly growth factors (the first
0165         // allows for frequent re-use of heap blocks, the second
0166         // forms a fibonacci sequence with similar characteristics -
0167         // since this heavily depends on the heap implementation
0168         // and other factors as well, i'll just go with 1.5 since
0169         // it is quicker to compute).
0170         size_t new_size = std::max(initial, std::max(need, cur_size + (cur_size >> 1)));
0171 
0172         const uint8_t *const old = buffer;
0173         buffer = new uint8_t[new_size];
0174 
0175         if (old) {
0176             memcpy(buffer, old, cur_size);
0177             delete[] old;
0178         }
0179 
0180         cur_size = new_size;
0181     }
0182 
0183 private:
0184     uint8_t *buffer;
0185     size_t cur_size, file_size, cursor, initial;
0186 
0187     const std::string file;
0188     BlobIOSystem *const creator;
0189 };
0190 
0191 #define AI_BLOBIO_MAGIC "$blobfile"
0192 
0193 // --------------------------------------------------------------------------------------------
0194 /** Redirect IOSystem to a blob */
0195 // --------------------------------------------------------------------------------------------
0196 class BlobIOSystem : public IOSystem {
0197 
0198     friend class BlobIOStream;
0199     typedef std::pair<std::string, aiExportDataBlob *> BlobEntry;
0200 
0201 
0202 public:
0203     /// @brief The default class constructor.
0204     BlobIOSystem() :
0205             baseName{AI_BLOBIO_MAGIC} {
0206     }
0207 
0208     /// @brief  The class constructor with the base name.
0209     /// @param baseName     The base name.
0210     BlobIOSystem(const std::string &baseName) :
0211             baseName(baseName) {
0212         // empty
0213     }
0214 
0215     ~BlobIOSystem() override {
0216         for (BlobEntry &blobby : blobs) {
0217             delete blobby.second;
0218         }
0219     }
0220 
0221 public:
0222     // -------------------------------------------------------------------
0223     const char *GetMagicFileName() const {
0224         return baseName.c_str();
0225     }
0226 
0227     // -------------------------------------------------------------------
0228     aiExportDataBlob *GetBlobChain() {
0229         const auto magicName = std::string(this->GetMagicFileName());
0230         const bool hasBaseName = baseName != AI_BLOBIO_MAGIC;
0231 
0232         // one must be the master
0233         aiExportDataBlob *master = nullptr, *cur;
0234 
0235         for (const BlobEntry &blobby : blobs) {
0236             if (blobby.first == magicName) {
0237                 master = blobby.second;
0238                 master->name.Set(hasBaseName ? blobby.first : "");
0239                 break;
0240             }
0241         }
0242 
0243         if (!master) {
0244             ASSIMP_LOG_ERROR("BlobIOSystem: no data written or master file was not closed properly.");
0245             return nullptr;
0246         }
0247 
0248         cur = master;
0249 
0250         for (const BlobEntry &blobby : blobs) {
0251             if (blobby.second == master) {
0252                 continue;
0253             }
0254 
0255             cur->next = blobby.second;
0256             cur = cur->next;
0257 
0258             if (hasBaseName) {
0259                 cur->name.Set(blobby.first);
0260             } else {
0261                 // extract the file extension from the file written
0262                 const std::string::size_type s = blobby.first.find_first_of('.');
0263                 cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s + 1));
0264             }
0265         }
0266 
0267         // give up blob ownership
0268         blobs.clear();
0269         return master;
0270     }
0271 
0272 public:
0273     // -------------------------------------------------------------------
0274     bool Exists(const char *pFile) const override {
0275         return created.find(std::string(pFile)) != created.end();
0276     }
0277 
0278     // -------------------------------------------------------------------
0279     char getOsSeparator() const override {
0280         return '/';
0281     }
0282 
0283     // -------------------------------------------------------------------
0284     IOStream *Open(const char *pFile, const char *pMode) override {
0285         if (pMode[0] != 'w') {
0286             return nullptr;
0287         }
0288 
0289         created.insert(std::string(pFile));
0290         return new BlobIOStream(this, std::string(pFile));
0291     }
0292 
0293     // -------------------------------------------------------------------
0294     void Close(IOStream *pFile) override {
0295         delete pFile;
0296     }
0297 
0298 private:
0299     // -------------------------------------------------------------------
0300     void OnDestruct(const std::string &filename, BlobIOStream *child) {
0301         // we don't know in which the files are closed, so we
0302         // can't reliably say that the first must be the master
0303         // file ...
0304         blobs.emplace_back(filename, child->GetBlob());
0305     }
0306 
0307 private:
0308     std::string baseName;
0309     std::set<std::string> created;
0310     std::vector<BlobEntry> blobs;
0311 };
0312 
0313 // --------------------------------------------------------------------------------------------
0314 BlobIOStream::~BlobIOStream() {
0315     if (nullptr != creator) {
0316         creator->OnDestruct(file, this);
0317     }
0318     delete[] buffer;
0319 }
0320 
0321 } // namespace Assimp
0322 
0323 #endif