diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-10-21 15:32:13 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-21 15:32:13 -0400 |
| commit | 5ca446888656da91165b7bf90b7b2195d1e1afac (patch) | |
| tree | 893a03930bc706089f28c156032ffe883ea0d2a1 /source/core/slang-relative-container.cpp | |
| parent | a854bf2fde6e466aa698f4132971faadc827913a (diff) | |
`Repro` functionality (#1085)
* WIP on serialize/save state.
* Relative string encoding.
* Added RelativeContainer unit test.
Split out RelativeContainer into core.
* Fix bug in RelativeString encoding.
* More work around relative container.
* Fix checks.
* Use RelativeBase for safe access.
Use malloc/free/realloc instead of List.
* Add natvis support for relative types.
* Setting up of state (not includes) writing of repro state.
* Capture after spCompile.
* Writing SourceFile and file system files.
Added -dump-repo
* First pass at loading state.
* First pass at reading repro.
* Small optimization around Safe32Ptr
* Refactor how repro data is stored - to make saving off the files more simple, by having all all backed by 'files'.
Make file loading always set up PathInfo so we get uniqueIdentifier info.
* Generate unique file names.
* Added RelativeFileSystem
Added saveFile to ISlangFileSystemExt and implemented for interfaces
Added mechanism to save of files (and manifest)
* Added ability to replace files in repo with directory holding their contents.
* Add support for entry points.
* Fix problem compiling on linux.
* Added SIMPLE_EX option, where everything on command line must be specified.
* Fix typo in unit test for relative container.
* Fix another typo in unit test for RelativeContainer.
* Fix small bugs.
* Fix release unused variable issue in slang-state-serialize.cpp
* Fix checking for SIMPLE_EX in testing, else broke COMMAND_LINE_SIMPLE.
* Fix warnings on 32 bit debug build.
* Added import-subdir-search-path-repro.slang test. Although disabled for now as writes to root of slang project.
* Remove wrong version of import-subdir-search-path-repro.slang
* Added import-subdir-search-path-repro.slang
Diffstat (limited to 'source/core/slang-relative-container.cpp')
| -rw-r--r-- | source/core/slang-relative-container.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/source/core/slang-relative-container.cpp b/source/core/slang-relative-container.cpp new file mode 100644 index 000000000..0b52f4268 --- /dev/null +++ b/source/core/slang-relative-container.cpp @@ -0,0 +1,215 @@ +// slang-relative-containere.cpp +#include "slang-relative-container.h" + +namespace Slang { + + +/* static */RelativeBase RelativeBase::g_null = { nullptr }; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RelativeString !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +size_t RelativeString::calcEncodedSize(size_t size, uint8_t encode[kMaxSizeEncodeSize]) +{ + SLANG_ASSERT(size <= 0xffffffff); + if (size <= kSizeBase) + { + encode[0] = uint8_t(size); + return 1; + } + // Encode + int num = 0; + while (size) + { + encode[num + 1] = uint8_t(size); + size >>= 8; + num++; + } + + // It might be one byte past the front, if its < 0x100 but greater than kSizeBase + SLANG_ASSERT(num >= 1); + + encode[0] = uint8_t(kSizeBase + num); + return num + 1; +} + +/* static */const char* RelativeString::decodeSize(const char* in, size_t& outSize) +{ + const uint8_t* cur = (const uint8_t*)in; + if (*cur <= kSizeBase) + { + outSize = *cur; + return in + 1; + } + + int numBytes = *cur - kSizeBase; + switch (numBytes) + { + case 1: + { + outSize = cur[1]; + return in + 2; + } + case 2: + { + outSize = cur[1] | (uint32_t(cur[2]) << 8); + return in + 3; + } + case 3: + { + outSize = cur[1] | (uint32_t(cur[2]) << 8) | (uint32_t(cur[3]) << 16); + return in + 4; + } + case 4: + { + outSize = cur[1] | (uint32_t(cur[2]) << 8) | (uint32_t(cur[3]) << 16) | (uint32_t(cur[4]) << 24); + return in + 5; + } + default: + { + outSize = 0; + return nullptr; + } + } +} + +/* static */size_t RelativeString::calcAllocationSize(size_t stringSize) +{ + uint8_t encode[kMaxSizeEncodeSize]; + size_t encodeSize = calcEncodedSize(stringSize, encode); + // Add 1 for terminating 0 + return encodeSize + stringSize + 1; +} + +/* static */size_t RelativeString::calcAllocationSize(const UnownedStringSlice& slice) +{ + return calcAllocationSize(slice.size()); +} + +UnownedStringSlice RelativeString::getSlice() const +{ + size_t size; + const char* chars = decodeSize(m_sizeThenContents, size); + + return UnownedStringSlice(chars, size); +} + +const char* RelativeString::getCstr() const +{ + return getSlice().begin(); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RelativeContainer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +RelativeContainer::RelativeContainer() +{ + m_current = 0; + m_capacity = 0; + m_base.m_data = nullptr; +} + +RelativeContainer::~RelativeContainer() +{ + if (m_base.m_data) + { + ::free(m_base.m_data); + } +} + +void* RelativeContainer::allocate(size_t size) +{ + return allocate(size, 1); +} + +void RelativeContainer::fixAlignment(size_t alignment) +{ + allocate(0, alignment); +} + +void* RelativeContainer::allocate(size_t size, size_t alignment) +{ + size_t offset = (m_current + alignment - 1) & ~(alignment - 1); + + if (offset + size > m_capacity) + { + const size_t minSize = offset + size; + + size_t calcSize = m_capacity; + if (calcSize < 2048) + { + calcSize = 2048; + } + else + { + // Expand geometrically, but lets not double in size... + calcSize = calcSize + (calcSize / 2); + } + + // We must be at least minSize + size_t newSize = (calcSize < minSize) ? minSize : calcSize; + + // Reallocate space + m_base.m_data = (uint8_t*)::realloc(m_base.m_data, newSize); + m_capacity = newSize; + } + + SLANG_ASSERT(offset + size <= m_capacity); + + m_current = offset + size; + return m_base.m_data + offset; +} + +void* RelativeContainer::allocateAndZero(size_t size, size_t alignment) +{ + void* data = allocate(size, alignment); + memset(data, 0, size); + return data; +} + +Safe32Ptr<RelativeString> RelativeContainer::newString(const UnownedStringSlice& slice) +{ + size_t stringSize = slice.size(); + + uint8_t head[RelativeString::kMaxSizeEncodeSize]; + size_t headSize = RelativeString::calcEncodedSize(stringSize, head); + + size_t allocSize = headSize + stringSize + 1; + uint8_t* bytes = (uint8_t*)allocate(allocSize); + + ::memcpy(bytes, head, headSize); + ::memcpy(bytes + headSize, slice.begin(), stringSize); + + // 0 terminate + bytes[headSize + stringSize] = 0; + + return Safe32Ptr<RelativeString>(getOffset(bytes), &m_base); +} + +Safe32Ptr<RelativeString> RelativeContainer::newString(const char* contents) +{ + Safe32Ptr<RelativeString> relString; + if (contents) + { + relString = newString(UnownedStringSlice(contents)); + } + return relString; +} + +void RelativeContainer::set(void* data, size_t size) +{ + if (m_base.m_data) + { + ::free(m_base.m_data); + m_base.m_data = nullptr; + } + + if (size > 0) + { + m_base.m_data = (uint8_t*)::malloc(size); + ::memcpy(m_base.m_data, data, size); + } + + m_current = size; + m_capacity = size; +} + +} // namespace Slang |
