summaryrefslogtreecommitdiffstats
path: root/source/core/slang-riff.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-10-29 14:50:15 -0400
committerGitHub <noreply@github.com>2019-10-29 14:50:15 -0400
commit066bc37f34ab4f72edef2b71fab50b45c3bb627e (patch)
tree6880c04996a7c2b964983d6a006e77a55a75fcde /source/core/slang-riff.cpp
parentc27b7d91aaf6bc764807a8998a9c885e57c22a1b (diff)
Feature/riff improvements (#1099)
* Added RiffReadHelper * Move type to fourCC in Chunk simplifies some code. * Make MemoryArena able to track external blocks. Allow ownership of Data to vary. Changed IR serialization to use moved allocations to avoid copies. As it turns out all of the array writes could use unowned data, but doing so requires the IRData to stay in scope longer than IRSerialData, which it does at the moment - but perhaps needs better naming or a control for the feature.
Diffstat (limited to 'source/core/slang-riff.cpp')
-rw-r--r--source/core/slang-riff.cpp102
1 files changed, 75 insertions, 27 deletions
diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp
index 9849cfc26..3a3722bb8 100644
--- a/source/core/slang-riff.cpp
+++ b/source/core/slang-riff.cpp
@@ -175,7 +175,7 @@ struct DumpVisitor : public RiffContainer::Visitor
// If it's the root it's 'riff'
_dumpRiffType(list == m_rootChunk ? RiffFourCC::kRiff : RiffFourCC::kList);
m_writer.put(" ");
- _dumpRiffType(list->m_subType);
+ _dumpRiffType(list->getSubType());
m_writer.put("\n");
m_indent++;
return SLANG_OK;
@@ -184,10 +184,9 @@ struct DumpVisitor : public RiffContainer::Visitor
{
_dumpIndent();
// Write out the name
- _dumpRiffType(data->m_type);
+ _dumpRiffType(data->m_fourCC);
m_writer.put(" ");
-
int hash = data->calcHash();
// We don't know in general what the contents is or means... but we can display a hash
@@ -250,7 +249,7 @@ struct DumpVisitor : public RiffContainer::Visitor
listHeader.chunk.type = isRoot ? RiffFourCC::kRiff : RiffFourCC::kList;
listHeader.chunk.size = uint32_t(list->m_payloadSize);
- listHeader.subType = list->m_subType;
+ listHeader.subType = list->getSubType();
try
{
@@ -276,7 +275,7 @@ struct DumpVisitor : public RiffContainer::Visitor
// Must be a regular chunk with data
RiffHeader chunkHeader;
- chunkHeader.type = dataChunk->m_type;
+ chunkHeader.type = dataChunk->m_fourCC;
chunkHeader.size = uint32_t(dataChunk->m_payloadSize);
stream->write(&chunkHeader, sizeof(chunkHeader));
@@ -386,7 +385,9 @@ struct DumpVisitor : public RiffContainer::Visitor
else
{
ScopeChunk scopeChunk(&outContainer, Chunk::Kind::Data, header.chunk.type);
- RiffContainer::Data* data = outContainer.addData(header.chunk.size);
+ RiffContainer::Data* data = outContainer.addData();
+
+ outContainer.setPayload(data, nullptr, header.chunk.size);
size_t readSize;
SLANG_RETURN_ON_FAIL(readPayload(stream, header.chunk.size, data->getPayload(), readSize));
@@ -520,15 +521,12 @@ size_t RiffContainer::ListChunk::calcPayloadSize()
return size;
}
-RiffContainer::Chunk* RiffContainer::ListChunk::findContained(FourCC type) const
+RiffContainer::Chunk* RiffContainer::ListChunk::findContained(FourCC fourCC) const
{
Chunk* chunk = m_containedChunks;
while (chunk)
{
- const FourCC checkType = (chunk->m_kind == Chunk::Kind::Data) ?
- static_cast<RiffContainer::DataChunk*>(chunk)->m_type :
- static_cast<RiffContainer::ListChunk*>(chunk)->m_subType;
- if (checkType == type)
+ if (chunk->m_fourCC == fourCC)
{
return chunk;
}
@@ -568,7 +566,7 @@ static RiffContainer::ListChunk* _findListRec(RiffContainer::ListChunk* list, Fo
if (auto childList = as<RiffContainer::ListChunk>(chunk))
{
// Test if the child is the subtype, if so we are done
- if (childList->m_subType == subType)
+ if (childList->getSubType() == subType)
{
return childList;
}
@@ -585,23 +583,25 @@ static RiffContainer::ListChunk* _findListRec(RiffContainer::ListChunk* list, Fo
/* static */RiffContainer::ListChunk* RiffContainer::ListChunk::findListRec(FourCC subType)
{
- return (m_subType == subType) ? this : _findListRec(this, subType);
+ return (getSubType() == subType) ? this : _findListRec(this, subType);
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!! RiffContainer::DataChunk !!!!!!!!!!!!!!!!!!!!!!
RiffContainer::Data* RiffContainer::DataChunk::getSingleData() const
{
- if (m_kind == Kind::Data)
+ Data* data = m_dataList;
+ return (data && data->m_next == nullptr) ? data : nullptr;
+}
+
+RiffReadHelper RiffContainer::DataChunk::asReadHelper() const
+{
+ Data* data = getSingleData();
+ if (data)
{
- auto dataChunk = static_cast<const DataChunk*>(this);
- Data* data = dataChunk->m_dataList;
- if (data && data->m_next == nullptr)
- {
- return data;
- }
+ return RiffReadHelper((const uint8_t*)data->getPayload(), data->getSize());
}
- return nullptr;
+ return RiffReadHelper(nullptr, 0);
}
int RiffContainer::DataChunk::calcHash() const
@@ -765,19 +765,67 @@ void RiffContainer::endChunk()
SLANG_ASSERT(isChunkOk(chunk));
}
-RiffContainer::Data* RiffContainer::addData(size_t size)
+void RiffContainer::setPayload(Data* data, const void* payload, size_t size)
{
- // We must be in a chunk
+ // We must be in a data chunk
SLANG_ASSERT(m_dataChunk);
+ // The data shouldn't be set up
+ SLANG_ASSERT(data->m_ownership == Ownership::Uninitialized);
// Add current chunks data
m_dataChunk->m_payloadSize += size;
- Data* data = (Data*)m_arena.allocate(sizeof(Data) + size);
+ data->m_ownership = Ownership::Arena;
+ data->m_size = size;
+
+ data->m_payload = m_arena.allocate(size);
+
+ if (payload)
+ {
+ ::memcpy(data->m_payload, payload, size);
+ }
+}
- data->m_next = nullptr;
+void RiffContainer::moveOwned(Data* data, void* payload, size_t size)
+{
+ // We must be in a data chunk
+ SLANG_ASSERT(m_dataChunk);
+ // The data shouldn't be set up
+ SLANG_ASSERT(data->m_ownership == Ownership::Uninitialized);
+
+ // Add current chunks data
+ m_dataChunk->m_payloadSize += size;
+
+ data->m_ownership = Ownership::Owned;
data->m_size = size;
+ // The area will manage this block
+ m_arena.addExternalBlock(payload, size);
+ data->m_payload = payload;
+}
+
+void RiffContainer::setUnowned(Data* data, void* payload, size_t size)
+{
+ // We must be in a data chunk
+ SLANG_ASSERT(m_dataChunk);
+ // The data shouldn't be set up
+ SLANG_ASSERT(data->m_ownership == Ownership::Uninitialized);
+ // Add current chunks data
+ m_dataChunk->m_payloadSize += size;
+
+ data->m_ownership = Ownership::NotOwned;
+ data->m_size = size;
+ data->m_payload = payload;
+}
+
+RiffContainer::Data* RiffContainer::addData()
+{
+ // We must be in a chunk
+ SLANG_ASSERT(m_dataChunk);
+
+ Data* data = (Data*)m_arena.allocate(sizeof(Data));
+ data->init();
+
Data*& next = m_dataChunk->m_endData ? m_dataChunk->m_endData->m_next : m_dataChunk->m_dataList;
SLANG_ASSERT(next == nullptr);
@@ -790,8 +838,8 @@ RiffContainer::Data* RiffContainer::addData(size_t size)
void RiffContainer::write(const void* inData, size_t size)
{
- auto data = addData(size);
- ::memcpy(data->getPayload(), inData, size);
+ auto data = addData();
+ setPayload(data, inData, size);
}
static SlangResult _isChunkOk(RiffContainer::Chunk* chunk, void* data)