/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "StdAfx.h" #include "MemoryBlock.h" #include "Include/ILogFile.h" #include #include ////////////////////////////////////////////////////////////////////////// CMemoryBlock::CMemoryBlock() : m_buffer(0) , m_size(0) , m_uncompressedSize(0) , m_owns(false) { } ////////////////////////////////////////////////////////////////////////// CMemoryBlock::CMemoryBlock(const CMemoryBlock& mem) { *this = mem; } ////////////////////////////////////////////////////////////////////////// CMemoryBlock::~CMemoryBlock() { Free(); } ////////////////////////////////////////////////////////////////////////// CMemoryBlock& CMemoryBlock::operator=(const CMemoryBlock& mem) { if (mem.GetSize() > 0) { // Do not reallocate. if (mem.GetSize() > GetSize()) { if (!Allocate(mem.GetSize())) { return *this; } } Copy(mem.GetBuffer(), mem.GetSize()); } else { m_buffer = 0; m_size = 0; m_owns = false; } m_uncompressedSize = mem.m_uncompressedSize; return *this; } ////////////////////////////////////////////////////////////////////////// bool CMemoryBlock::Allocate(int size, int uncompressedSize) { assert(size > 0); if (m_buffer) { m_buffer = realloc(m_buffer, size); } else { m_buffer = malloc(size); } if (!m_buffer) { QString str; str = QStringLiteral("CMemoryBlock::Allocate failed to allocate %1Mb of Memory").arg(size / (1024 * 1024)); CryLogAlways(str.toUtf8().data()); QMessageBox::critical(QApplication::activeWindow(), QString(), str + QString("\r\nSandbox will try to reduce its working memory set to free memory for this allocation.")); GetIEditor()->ReduceMemory(); if (m_buffer) { m_buffer = realloc(m_buffer, size); } else { m_buffer = malloc(size); } if (!m_buffer) { GetIEditor()->GetLogFile()->Warning("Reducing working memory set failed, Sandbox must quit"); } else { GetIEditor()->GetLogFile()->Warning("Reducing working memory set succeeded\r\nSandbox may become unstable, it is advised to save the level and restart editor."); } } m_owns = true; m_size = size; m_uncompressedSize = uncompressedSize; // Check if allocation failed. if (m_buffer == 0) { return false; } return true; } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Free() { if (m_buffer && m_owns) { free(m_buffer); } m_buffer = 0; m_owns = false; m_size = 0; m_uncompressedSize = 0; } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Copy(void* src, int size) { assert(size <= m_size); memcpy(m_buffer, src, size); } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Attach(void* buffer, int size, int uncompressedSize) { Free(); m_owns = false; m_buffer = buffer; m_size = size; m_uncompressedSize = uncompressedSize; } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Detach() { Free(); } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Compress(CMemoryBlock& toBlock) const { // Cannot compress to itself. assert(this != &toBlock); unsigned long destSize = m_size * 2 + 128; CMemoryBlock temp; temp.Allocate(destSize); compress((unsigned char*)temp.GetBuffer(), &destSize, (unsigned char*)GetBuffer(), m_size); toBlock.Allocate(destSize); toBlock.Copy(temp.GetBuffer(), destSize); toBlock.m_uncompressedSize = GetSize(); } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Uncompress(CMemoryBlock& toBlock) const { assert(this != &toBlock); toBlock.Allocate(m_uncompressedSize); toBlock.m_uncompressedSize = 0; unsigned long destSize = m_uncompressedSize; int result = uncompress((unsigned char*)toBlock.GetBuffer(), &destSize, (unsigned char*)GetBuffer(), GetSize()); assert(result == Z_OK); assert(destSize == m_uncompressedSize); } ////////////////////////////////////////////////////////////////////////// void CMemoryBlock::Serialize(CArchive& ar) { if (ar.IsLoading()) { int size; // Loading. ar >> size; if (size != m_size) { Allocate(size); } m_size = size; ar >> m_uncompressedSize; ar.Read(m_buffer, m_size); } else { // Saving. ar << m_size; ar << m_uncompressedSize; ar.Write(m_buffer, m_size); } }