summaryrefslogtreecommitdiffstats
path: root/source/core/slang-stream.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-10-23 09:28:58 -0400
committerGitHub <noreply@github.com>2019-10-23 09:28:58 -0400
commit9c2d1766ea33101b551ac521ddc39516b98b6641 (patch)
treefeee466c977575ebcb15b9057a59c2efce5d9ae1 /source/core/slang-stream.cpp
parent6a7f4c9cef766e538a808a8f03411af2f10106e1 (diff)
Expose more repro in API, support output params. (#1087)
* Added spEnableReproCapture to the API. * Added MemoryStreamBase - which can be used to read from without copyin the data. Added the missing Repro API functions - spEnableReproCapture and spExtractRepro. Added support for serializing output filenames. * Improved naming around Stream. Brought Stream and sub types closer to code conventions. * Renamed content -> contents in Stream.
Diffstat (limited to 'source/core/slang-stream.cpp')
-rw-r--r--source/core/slang-stream.cpp478
1 files changed, 245 insertions, 233 deletions
diff --git a/source/core/slang-stream.cpp b/source/core/slang-stream.cpp
index ee194c451..b5eef1d9b 100644
--- a/source/core/slang-stream.cpp
+++ b/source/core/slang-stream.cpp
@@ -6,289 +6,301 @@
namespace Slang
{
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode)
- {
- Init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
- }
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
- {
- Init(fileName, fileMode, access, share);
- }
- void FileStream::Init(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+FileStream::FileStream(const String& fileName, FileMode fileMode)
+{
+ _init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
+}
+
+FileStream::FileStream(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ _init(fileName, fileMode, access, share);
+}
+
+void FileStream::_init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ const wchar_t * mode = L"rt";
+ const char* modeMBCS = "rt";
+ switch (fileMode)
{
- const wchar_t * mode = L"rt";
- const char* modeMBCS = "rt";
- switch (fileMode)
+ case FileMode::Create:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
{
- case Slang::FileMode::Create:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- modeMBCS = "w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Open:
- if (access == FileAccess::Read)
- {
- mode = L"rb";
- modeMBCS = "rb";
- this->fileAccess = FileAccess::Read;
- }
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"r+b";
- modeMBCS = "r+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::CreateNew:
- if (File::exists(fileName))
- {
- throw IOException("Failed opening '" + fileName + "', file already exists.");
- }
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Append:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Append mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"a+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"ab";
- this->fileAccess = FileAccess::Write;
- }
- break;
- default:
- break;
+ mode = L"w+b";
+ modeMBCS = "w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
}
-#ifdef _WIN32
- int shFlag = _SH_DENYRW;
- switch (share)
+ else
{
- case Slang::FileShare::None:
- shFlag = _SH_DENYRW;
- break;
- case Slang::FileShare::ReadOnly:
- shFlag = _SH_DENYWR;
- break;
- case Slang::FileShare::WriteOnly:
- shFlag = _SH_DENYRD;
- break;
- case Slang::FileShare::ReadWrite:
- shFlag = _SH_DENYNO;
- break;
- default:
- throw ArgumentException("Invalid file share mode.");
- break;
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
- if (share == Slang::FileShare::None)
-#pragma warning(suppress:4996)
- handle = _wfopen(fileName.toWString(), mode);
- else
- handle = _wfsopen(fileName.toWString(), mode, shFlag);
-#else
- handle = fopen(fileName.getBuffer(), modeMBCS);
-#endif
- if (!handle)
+ break;
+ case FileMode::Open:
+ if (access == FileAccess::Read)
+ {
+ mode = L"rb";
+ modeMBCS = "rb";
+ this->m_fileAccess = FileAccess::Read;
+ }
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"r+b";
+ modeMBCS = "r+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
{
- throw IOException("Cannot open file '" + fileName + "'");
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
+ break;
+ case FileMode::CreateNew:
+ if (File::exists(fileName))
+ {
+ throw IOException("Failed opening '" + fileName + "', file already exists.");
+ }
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"wb";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ case FileMode::Append:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Append mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"a+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"ab";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ default:
+ break;
}
- FileStream::~FileStream()
+#ifdef _WIN32
+ int shFlag = _SH_DENYRW;
+ switch (share)
{
- Close();
+ case FileShare::None:
+ shFlag = _SH_DENYRW;
+ break;
+ case FileShare::ReadOnly:
+ shFlag = _SH_DENYWR;
+ break;
+ case FileShare::WriteOnly:
+ shFlag = _SH_DENYRD;
+ break;
+ case FileShare::ReadWrite:
+ shFlag = _SH_DENYNO;
+ break;
+ default:
+ throw ArgumentException("Invalid file share mode.");
+ break;
}
- Int64 FileStream::GetPosition()
+ if (share == FileShare::None)
+#pragma warning(suppress:4996)
+ m_handle = _wfopen(fileName.toWString(), mode);
+ else
+ m_handle = _wfsopen(fileName.toWString(), mode, shFlag);
+#else
+ m_handle = fopen(fileName.getBuffer(), modeMBCS);
+#endif
+ if (!m_handle)
{
+ throw IOException("Cannot open file '" + fileName + "'");
+ }
+}
+
+FileStream::~FileStream()
+{
+ close();
+}
+
+Int64 FileStream::getPosition()
+{
#if defined(_WIN32) || defined(__CYGWIN__)
- fpos_t pos;
- fgetpos(handle, &pos);
- return pos;
+ fpos_t pos;
+ fgetpos(m_handle, &pos);
+ return pos;
#elif defined(__APPLE__)
- return ftell(handle);
+ return ftell(m_handle);
#else
- fpos64_t pos;
- fgetpos64(handle, &pos);
- return *(Int64*)(&pos);
+ fpos64_t pos;
+ fgetpos64(m_handle, &pos);
+ return *(Int64*)(&pos);
#endif
- }
- void FileStream::Seek(SeekOrigin origin, Int64 offset)
+}
+void FileStream::seek(SeekOrigin origin, Int64 offset)
+{
+ int _origin;
+ switch (origin)
{
- int _origin;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
- _origin = SEEK_SET;
- endReached = false;
- break;
- case Slang::SeekOrigin::End:
- _origin = SEEK_END;
- // JS TODO: This doesn't seem right, the offset can mean it's not at the end
- endReached = true;
- break;
- case Slang::SeekOrigin::Current:
- _origin = SEEK_CUR;
- endReached = false;
- break;
- default:
- throw NotSupportedException("Unsupported seek origin.");
- break;
- }
+ case SeekOrigin::Start:
+ _origin = SEEK_SET;
+ m_endReached = false;
+ break;
+ case SeekOrigin::End:
+ _origin = SEEK_END;
+ // JS TODO: This doesn't seem right, the offset can mean it's not at the end
+ m_endReached = true;
+ break;
+ case SeekOrigin::Current:
+ _origin = SEEK_CUR;
+ m_endReached = false;
+ break;
+ default:
+ throw NotSupportedException("Unsupported seek origin.");
+ break;
+ }
#ifdef _WIN32
- int rs = _fseeki64(handle, offset, _origin);
+ int rs = _fseeki64(m_handle, offset, _origin);
#else
- int rs = fseek(handle, (int)offset, _origin);
+ int rs = fseek(m_handle, (int)offset, _origin);
#endif
- if (rs != 0)
- {
- throw IOException("FileStream seek failed.");
- }
- }
- Int64 FileStream::Read(void * buffer, Int64 length)
- {
- auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, handle);
- if (bytes == 0 && length > 0)
- {
- if (!feof(handle))
- throw IOException("FileStream read failed.");
- else if (endReached)
- throw EndOfStreamException("End of file is reached.");
- endReached = true;
- }
- return (int)bytes;
- }
- Int64 FileStream::Write(const void * buffer, Int64 length)
- {
- auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, handle);
- if (bytes < length)
- {
- throw IOException("FileStream write failed.");
- }
- return bytes;
- }
- bool FileStream::CanRead()
+ if (rs != 0)
{
- return ((int)fileAccess & (int)FileAccess::Read) != 0;
+ throw IOException("FileStream seek failed.");
}
- bool FileStream::CanWrite()
+}
+Int64 FileStream::read(void* buffer, Int64 length)
+{
+ auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, m_handle);
+ if (bytes == 0 && length > 0)
{
- return ((int)fileAccess & (int)FileAccess::Write) != 0;
+ if (!feof(m_handle))
+ throw IOException("FileStream read failed.");
+ else if (m_endReached)
+ throw EndOfStreamException("End of file is reached.");
+ m_endReached = true;
}
- void FileStream::Close()
+ return (int)bytes;
+}
+Int64 FileStream::write(const void* buffer, Int64 length)
+{
+ auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, m_handle);
+ if (bytes < length)
{
- if (handle)
- {
- fclose(handle);
- handle = 0;
- }
+ throw IOException("FileStream write failed.");
}
- bool FileStream::IsEnd()
+ return bytes;
+}
+bool FileStream::canRead()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Read) != 0;
+}
+bool FileStream::canWrite()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Write) != 0;
+}
+void FileStream::close()
+{
+ if (m_handle)
{
- return endReached;
+ fclose(m_handle);
+ m_handle = 0;
}
+}
+bool FileStream::isEnd()
+{
+ return m_endReached;
+}
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStreamBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- void MemoryStream::Seek(SeekOrigin origin, Int64 offset)
+void MemoryStreamBase::seek(SeekOrigin origin, Int64 offset)
+{
+ Int64 pos = 0;
+ switch (origin)
{
- Int64 pos = 0;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
+ case SeekOrigin::Start:
pos = offset;
break;
- case Slang::SeekOrigin::End:
- pos = Int64(m_contents.getCount()) + offset;
+ case SeekOrigin::End:
+ pos = Int64(m_contentsSize) + offset;
break;
- case Slang::SeekOrigin::Current:
+ case SeekOrigin::Current:
pos = Int64(m_position) + offset;
break;
default:
throw NotSupportedException("Unsupported seek origin.");
break;
- }
+ }
- m_atEnd = false;
+ m_atEnd = false;
- // Clamp to the valid range
- pos = (pos < 0) ? 0 : pos;
- pos = (pos > Int64(m_contents.getCount())) ? Int64(m_contents.getCount()) : pos;
+ // Clamp to the valid range
+ pos = (pos < 0) ? 0 : pos;
+ pos = (pos > Int64(m_contentsSize)) ? Int64(m_contentsSize) : pos;
- m_position = UInt(pos);
+ m_position = UInt(pos);
+}
+
+Int64 MemoryStreamBase::read(void* buffer, Int64 length)
+{
+ if (!canRead())
+ {
+ throw IOException("Cannot read this stream.");
}
- Int64 MemoryStream::Read(void * buffer, Int64 length)
+ const Int64 maxRead = Int64(m_contentsSize - m_position);
+
+ if (maxRead == 0 && length > 0)
{
- if (!CanRead())
- {
- throw IOException("Cannot read this stream.");
- }
+ m_atEnd = true;
+ throw EndOfStreamException("End of file is reached.");
+ }
- const Int64 maxRead = Int64(m_contents.getCount() - m_position);
-
- if (maxRead == 0 && length > 0)
- {
- m_atEnd = true;
- throw EndOfStreamException("End of file is reached.");
- }
+ length = length > maxRead ? maxRead : length;
- length = length > maxRead ? maxRead : length;
+ ::memcpy(buffer, m_contents + m_position, size_t(length));
+ m_position += UInt(length);
+ return maxRead;
+}
- ::memcpy(buffer, m_contents.begin() + m_position, size_t(length));
- m_position += UInt(length);
- return maxRead;
- }
-
- Int64 MemoryStream::Write(const void * buffer, Int64 length)
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! OwnedMemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Int64 OwnedMemoryStream::write(const void * buffer, Int64 length)
+{
+ if (!canWrite())
{
- if (!CanWrite())
- {
- throw IOException("Cannot write this stream.");
- }
+ throw IOException("Cannot write this stream.");
+ }
- if (m_position == m_contents.getCount())
- {
- m_contents.addRange((const uint8_t*)buffer, UInt(length));
- }
- else
- {
- m_contents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
- }
+ if (m_position == m_ownedContents.getCount())
+ {
+ m_ownedContents.addRange((const uint8_t*)buffer, UInt(length));
+ }
+ else
+ {
+ m_ownedContents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
+ }
- m_atEnd = false;
+ m_contents = m_ownedContents.getBuffer();
+ m_contentsSize = ptrdiff_t(m_ownedContents.getCount());
- m_position += UInt(length);
- return length;
- }
+ m_atEnd = false;
+ m_position += ptrdiff_t(length);
+ return length;
}
+
+} // namespace Slang