yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Julius IkkalaFix build on GCC 15 (#6971)6104a5554

master
5.6 KiB227 linesraw
1#define _CRT_SECURE_NO_WARNINGS
2
3#include "slang-writer.h"
4
5#include "slang-platform.h"
6#include "slang-string-util.h"
7
8// Includes to allow us to control console
9// output when writing assembly dumps.
10#include <fcntl.h>
11#ifdef _WIN32
12#include <io.h>
13#else
14#include <unistd.h>
15#endif
16
17#include <stdarg.h>
18
19namespace Slang
20{
21
22/* !!!!!!!!!!!!!!!!!!!!!!!!! WriterHelper !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
23
24SlangResult WriterHelper::print(const char* format, ...)
25{
26    va_list args;
27    va_start(args, format);
28
29    SlangResult res = SLANG_OK;
30
31    // numChars is the amount of characters needed *not* including terminating 0
32    size_t numChars;
33    {
34        // Create a copy of args, as will be consumed by calcFormattedSize
35        va_list argsCopy;
36        va_copy(argsCopy, args);
37        numChars = StringUtil::calcFormattedSize(format, argsCopy);
38        va_end(argsCopy);
39    }
40
41    if (numChars > 0)
42    {
43        // We need to add 1 here, because calcFormatted, *requires* space for terminating 0
44        char* appendBuffer = m_writer->beginAppendBuffer(numChars + 1);
45        StringUtil::calcFormatted(format, args, numChars, appendBuffer);
46        res = m_writer->endAppendBuffer(appendBuffer, numChars);
47    }
48
49    va_end(args);
50    return res;
51}
52
53SlangResult WriterHelper::put(const char* text)
54{
55    return m_writer->write(text, ::strlen(text));
56}
57
58SlangResult WriterHelper::put(const UnownedStringSlice& text)
59{
60    return m_writer->write(text.begin(), text.getLength());
61}
62
63/* !!!!!!!!!!!!!!!!!!!!!!!!! BaseWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
64
65ISlangUnknown* BaseWriter::getInterface(const Guid& guid)
66{
67    return (guid == ISlangUnknown::getTypeGuid() || guid == ISlangWriter::getTypeGuid())
68               ? static_cast<ISlangWriter*>(this)
69               : nullptr;
70}
71
72/* !!!!!!!!!!!!!!!!!!!!!!!!! AppendBufferWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
73
74SLANG_NO_THROW char* SLANG_MCALL AppendBufferWriter::beginAppendBuffer(size_t maxNumChars)
75{
76    mutex.lock();
77    m_appendBuffer.setCount(maxNumChars);
78    return m_appendBuffer.getBuffer();
79}
80
81SLANG_NO_THROW SlangResult SLANG_MCALL
82AppendBufferWriter::endAppendBuffer(char* buffer, size_t numChars)
83{
84    SLANG_ASSERT(m_appendBuffer.getBuffer() == buffer && buffer + numChars <= m_appendBuffer.end());
85    // Do the actual write
86    SlangResult res = write(buffer, numChars);
87    // Clear so that buffer can't be written from again without assert
88    m_appendBuffer.clear();
89    mutex.unlock();
90    return res;
91}
92
93/* !!!!!!!!!!!!!!!!!!!!!!!!! CallbackWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
94
95SLANG_NO_THROW char* SLANG_MCALL CallbackWriter::beginAppendBuffer(size_t maxNumChars)
96{
97    // Add one so there is always space for end termination, we need for the callback.
98    m_appendBuffer.setCount(maxNumChars + 1);
99    return m_appendBuffer.getBuffer();
100}
101
102SlangResult CallbackWriter::write(const char* chars, size_t numChars)
103{
104    if (numChars > 0)
105    {
106        char* appendBuffer = m_appendBuffer.getBuffer();
107        // See if it's from an append buffer
108        if (chars >= appendBuffer &&
109            (chars + numChars) < (appendBuffer + m_appendBuffer.getCount()))
110        {
111            // Set terminating 0
112            appendBuffer[(chars + numChars) - appendBuffer] = 0;
113
114            m_callback(chars, (void*)m_data);
115        }
116        else
117        {
118            // Use the append buffer to add the terminating 0
119            m_appendBuffer.setCount(numChars + 1);
120            ::memcpy(m_appendBuffer.getBuffer(), chars, numChars);
121            m_appendBuffer[numChars] = 0;
122
123            m_callback(m_appendBuffer.getBuffer(), (void*)m_data);
124        }
125    }
126
127    return SLANG_OK;
128}
129
130/* !!!!!!!!!!!!!!!!!!!!!!!!! FileWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
131
132FileWriter::~FileWriter()
133{
134    if (m_file)
135    {
136        ::fflush(m_file);
137
138        if ((m_flags & WriterFlag::IsUnowned) == 0)
139        {
140            ::fclose(m_file);
141        }
142    }
143}
144
145SlangResult FileWriter::write(const char* text, size_t numChars)
146{
147    const size_t numWritten = ::fwrite(text, sizeof(char), numChars, m_file);
148    if (m_flags & WriterFlag::AutoFlush)
149    {
150        ::fflush(m_file);
151    }
152    return numChars == numWritten ? SLANG_OK : SLANG_FAIL;
153}
154
155void FileWriter::flush()
156{
157    ::fflush(m_file);
158}
159
160/* static */ bool FileWriter::isFileConsole(FILE* file)
161{
162    const int stdoutFileDesc = _fileno(file);
163    return _isatty(stdoutFileDesc) != 0;
164}
165
166SlangResult FileWriter::setMode(SlangWriterMode mode)
167{
168    switch (mode)
169    {
170    case SLANG_WRITER_MODE_BINARY:
171        {
172#ifdef _WIN32
173            int stdoutFileDesc = _fileno(m_file);
174            _setmode(stdoutFileDesc, _O_BINARY);
175            return SLANG_OK;
176#else
177            break;
178#endif
179        }
180    default:
181        break;
182    }
183    return SLANG_FAIL;
184}
185
186/* static */ SlangResult FileWriter::create(
187    const char* filePath,
188    const char* writeOptions,
189    WriterFlags flags,
190    ComPtr<ISlangWriter>& outWriter)
191{
192    flags &= ~WriterFlag::IsUnowned;
193
194    FILE* file = fopen(filePath, writeOptions);
195    if (!file)
196    {
197        return SLANG_E_CANNOT_OPEN;
198    }
199
200    outWriter = new FileWriter(file, flags);
201    return SLANG_OK;
202}
203
204
205/* !!!!!!!!!!!!!!!!!!!!!!!!! StringWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
206
207SLANG_NO_THROW char* SLANG_MCALL StringWriter::beginAppendBuffer(size_t maxNumChars)
208{
209    return m_builder->prepareForAppend(maxNumChars);
210}
211
212SLANG_NO_THROW SlangResult SLANG_MCALL StringWriter::endAppendBuffer(char* buffer, size_t numChars)
213{
214    m_builder->appendInPlace(buffer, numChars);
215    return SLANG_OK;
216}
217
218SlangResult StringWriter::write(const char* chars, size_t numChars)
219{
220    if (numChars > 0)
221    {
222        m_builder->append(chars, numChars);
223    }
224    return SLANG_OK;
225}
226
227} // namespace Slang