unsigned File::Read(void* dest, unsigned size) { if (!IsOpen()) { // If file not open, do not log the error further here to prevent spamming the stderr stream return 0; } if (mode_ == FILE_WRITE) { ATOMIC_LOGERROR("File not opened for reading"); return 0; } if (size + position_ > size_) size = size_ - position_; if (!size) return 0; #ifdef __ANDROID__ if (assetHandle_ && !compressed_) { // If not using a compressed package file, buffer file reads on Android for better performance if (!readBuffer_) { readBuffer_ = new unsigned char[READ_BUFFER_SIZE]; readBufferOffset_ = 0; readBufferSize_ = 0; } unsigned sizeLeft = size; unsigned char* destPtr = (unsigned char*)dest; while (sizeLeft) { if (readBufferOffset_ >= readBufferSize_) { readBufferSize_ = Min(size_ - position_, READ_BUFFER_SIZE); readBufferOffset_ = 0; ReadInternal(readBuffer_.Get(), readBufferSize_); } unsigned copySize = Min((readBufferSize_ - readBufferOffset_), sizeLeft); memcpy(destPtr, readBuffer_.Get() + readBufferOffset_, copySize); destPtr += copySize; sizeLeft -= copySize; readBufferOffset_ += copySize; position_ += copySize; } return size; } #endif if (compressed_) { unsigned sizeLeft = size; unsigned char* destPtr = (unsigned char*)dest; while (sizeLeft) { if (!readBuffer_ || readBufferOffset_ >= readBufferSize_) { unsigned char blockHeaderBytes[4]; ReadInternal(blockHeaderBytes, sizeof blockHeaderBytes); MemoryBuffer blockHeader(&blockHeaderBytes[0], sizeof blockHeaderBytes); unsigned unpackedSize = blockHeader.ReadUShort(); unsigned packedSize = blockHeader.ReadUShort(); if (!readBuffer_) { readBuffer_ = new unsigned char[unpackedSize]; inputBuffer_ = new unsigned char[LZ4_compressBound(unpackedSize)]; } /// \todo Handle errors ReadInternal(inputBuffer_.Get(), packedSize); LZ4_decompress_fast((const char*)inputBuffer_.Get(), (char*)readBuffer_.Get(), unpackedSize); readBufferSize_ = unpackedSize; readBufferOffset_ = 0; } unsigned copySize = Min((readBufferSize_ - readBufferOffset_), sizeLeft); memcpy(destPtr, readBuffer_.Get() + readBufferOffset_, copySize); destPtr += copySize; sizeLeft -= copySize; readBufferOffset_ += copySize; position_ += copySize; } return size; } // Need to reassign the position due to internal buffering when transitioning from writing to reading if (readSyncNeeded_) { SeekInternal(position_ + offset_); readSyncNeeded_ = false; } if (!ReadInternal(dest, size)) { // Return to the position where the read began SeekInternal(position_ + offset_); ATOMIC_LOGERROR("Error while reading from file " + GetName()); return 0; } writeSyncNeeded_ = true; position_ += size; return size; }
unsigned File::Read(void* dest, unsigned size) { #ifdef ANDROID if (!handle_ && !assetHandle_) #else if (!handle_) #endif { // Do not log the error further here to prevent spamming the stderr stream return 0; } if (mode_ == FILE_WRITE) { LOGERROR("File not opened for reading"); return 0; } if (size + position_ > size_) size = size_ - position_; if (!size) return 0; #ifdef ANDROID if (assetHandle_) { unsigned sizeLeft = size; unsigned char* destPtr = (unsigned char*)dest; while (sizeLeft) { if (readBufferOffset_ >= readBufferSize_) { readBufferSize_ = Min((int)size_ - position_, (int)READ_BUFFER_SIZE); readBufferOffset_ = 0; SDL_RWread(assetHandle_, readBuffer_.Get(), readBufferSize_, 1); } unsigned copySize = Min((int)(readBufferSize_ - readBufferOffset_), (int)sizeLeft); memcpy(destPtr, readBuffer_.Get() + readBufferOffset_, copySize); destPtr += copySize; sizeLeft -= copySize; readBufferOffset_ += copySize; position_ += copySize; } return size; } #endif if (compressed_) { unsigned sizeLeft = size; unsigned char* destPtr = (unsigned char*)dest; while (sizeLeft) { if (!readBuffer_ || readBufferOffset_ >= readBufferSize_) { unsigned char blockHeaderBytes[4]; fread(blockHeaderBytes, sizeof blockHeaderBytes, 1, (FILE*)handle_); MemoryBuffer blockHeader(&blockHeaderBytes[0], sizeof blockHeaderBytes); unsigned unpackedSize = blockHeader.ReadUShort(); unsigned packedSize = blockHeader.ReadUShort(); if (!readBuffer_) { readBuffer_ = new unsigned char[unpackedSize]; inputBuffer_ = new unsigned char[LZ4_compressBound(unpackedSize)]; } /// \todo Handle errors fread(inputBuffer_.Get(), packedSize, 1, (FILE*)handle_); LZ4_decompress_fast((const char*)inputBuffer_.Get(), (char *)readBuffer_.Get(), unpackedSize); readBufferSize_ = unpackedSize; readBufferOffset_ = 0; } unsigned copySize = Min((int)(readBufferSize_ - readBufferOffset_), (int)sizeLeft); memcpy(destPtr, readBuffer_.Get() + readBufferOffset_, copySize); destPtr += copySize; sizeLeft -= copySize; readBufferOffset_ += copySize; position_ += copySize; } return size; } size_t ret = fread(dest, size, 1, (FILE*)handle_); if (ret != 1) { // Return to the position where the read began fseek((FILE*)handle_, position_ + offset_, SEEK_SET); LOGERROR("Error while reading from file " + GetName()); return 0; } position_ += size; return size; }
void CADLayer::addHandle( long handle, CADObject::ObjectType type, long cadinserthandle ) { #ifdef _DEBUG cout << "addHandle: " << handle << " type: " << type << endl; #endif //_DEBUG if( type == CADObject::ATTRIB || type == CADObject::ATTDEF ) { unique_ptr<CADAttdef> attdef( static_cast< CADAttdef *>( pCADFile->GetGeometry( this->getId() - 1, handle ) ) ); attributesNames.insert( attdef->getTag() ); } if( type == CADObject::INSERT ) { // TODO: transform insert to block of objects (do we need to transform // coordinates according to insert point)? unique_ptr<CADObject> insert( pCADFile->GetObject( handle, false ) ); CADInsertObject * pInsert = static_cast<CADInsertObject *>(insert.get()); if( nullptr != pInsert ) { unique_ptr<CADObject> blockHeader( pCADFile->GetObject( pInsert->hBlockHeader.getAsLong(), false ) ); CADBlockHeaderObject * pBlockHeader = static_cast<CADBlockHeaderObject *>(blockHeader.get()); if( nullptr != pBlockHeader ) { #ifdef _DEBUG if( pBlockHeader->bBlkisXRef ) { assert( 0 ); } #endif //_DEBUG auto dCurrentEntHandle = pBlockHeader->hEntities[0].getAsLong(); auto dLastEntHandle = pBlockHeader->hEntities[pBlockHeader->hEntities.size() - 1].getAsLong(); // FIXME: in 2000+ entities probably has no links to each other. if( dCurrentEntHandle == dLastEntHandle ) // Blocks can be empty (contain no objects) return; while( true ) { unique_ptr<CADEntityObject> entity( static_cast< CADEntityObject * >( pCADFile->GetObject( dCurrentEntHandle, true ) ) ); if( dCurrentEntHandle == dLastEntHandle ) { if( entity != nullptr ) { addHandle( dCurrentEntHandle, entity->getType(), handle ); Matrix mat; mat.translate( pInsert->vertInsertionPoint ); mat.scale( pInsert->vertScales ); mat.rotate( pInsert->dfRotation ); transformations[dCurrentEntHandle] = mat; break; } else { assert( 0 ); } } if( entity != nullptr ) { addHandle( dCurrentEntHandle, entity->getType(), handle ); Matrix mat; mat.translate( pInsert->vertInsertionPoint ); mat.scale( pInsert->vertScales ); mat.rotate( pInsert->dfRotation ); transformations[dCurrentEntHandle] = mat; if( entity->stCed.bNoLinks ) ++dCurrentEntHandle; else dCurrentEntHandle = entity->stChed.hNextEntity.getAsLong( entity->stCed.hObjectHandle ); } else { assert ( 0 ); } } } } return; } if( isCommonEntityType( type ) ) { if( type == CADObject::IMAGE ) imageHandles.push_back( handle ); else { if( pCADFile->isReadingUnsupportedGeometries() == false ) { if( isSupportedGeometryType( type ) ) { if( geometryTypes.size() == 0 ) geometryTypes.push_back( type ); if( find( geometryTypes.begin(), geometryTypes.end(), type ) == geometryTypes.end() ) { geometryTypes.push_back( type ); } geometryHandles.push_back( make_pair( handle, cadinserthandle ) ); } } else { if( geometryTypes.size() == 0 ) geometryTypes.push_back( type ); if( find( geometryTypes.begin(), geometryTypes.end(), type ) == geometryTypes.end() ) { geometryTypes.push_back( type ); } geometryHandles.push_back( make_pair( handle, cadinserthandle ) ); } } } }