Finished first version of shader compiler. HLSL -> DXIL.
Submitting vertex and frag shader needed to display a triangle.
This commit is contained in:
@@ -20,7 +20,7 @@ using size_t = std::size_t;
|
||||
|
||||
struct ByteBuffer
|
||||
{
|
||||
const Byte* Data;
|
||||
Byte* Data;
|
||||
size_t Size;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
|
||||
@@ -24,8 +25,6 @@ namespace Juliet
|
||||
|
||||
extern void JULIET_API JulietAssert(const char* expression);
|
||||
|
||||
#define DEFER(cleanup) for (bool done_ = 0; !done_; (cleanup), done_ = 1)
|
||||
|
||||
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
||||
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
||||
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
||||
@@ -38,8 +37,44 @@ namespace Juliet
|
||||
}
|
||||
}
|
||||
|
||||
#define MemCopy memcpy
|
||||
template <class Function>
|
||||
class DeferredFunction
|
||||
{
|
||||
public:
|
||||
explicit DeferredFunction(const Function& otherFct) noexcept
|
||||
: Callback(otherFct)
|
||||
{
|
||||
}
|
||||
explicit DeferredFunction(Function&& otherFct) noexcept
|
||||
: Callback(std::move(otherFct))
|
||||
{
|
||||
}
|
||||
|
||||
~DeferredFunction() noexcept { Callback(); }
|
||||
|
||||
DeferredFunction(const DeferredFunction&) = delete;
|
||||
DeferredFunction(const DeferredFunction&&) = delete;
|
||||
void operator=(const DeferredFunction&) = delete;
|
||||
void operator=(DeferredFunction&&) = delete;
|
||||
|
||||
private:
|
||||
Function Callback;
|
||||
};
|
||||
|
||||
template <class Function>
|
||||
auto Defer(Function&& fct) noexcept
|
||||
{
|
||||
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
|
||||
}
|
||||
|
||||
inline bool IsValid(ByteBuffer buffer)
|
||||
{
|
||||
return buffer.Size > 0 && buffer.Data;
|
||||
}
|
||||
|
||||
extern JULIET_API void Free(ByteBuffer& buffer);
|
||||
|
||||
// TODO move to math utils
|
||||
template <typename Type>
|
||||
constexpr Type Min(Type lhs, Type rhs)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,13 @@ namespace Juliet
|
||||
size_t Size;
|
||||
};
|
||||
|
||||
struct StringBuffer : String
|
||||
{
|
||||
size_t Capacity;
|
||||
};
|
||||
|
||||
constexpr uint32 kInvalidUTF8 = 0xFFFD;
|
||||
|
||||
inline size_t StringLength(String str)
|
||||
{
|
||||
return str.Size;
|
||||
@@ -56,7 +63,7 @@ namespace Juliet
|
||||
return length;
|
||||
}
|
||||
|
||||
inline bool StringIsValid(String str)
|
||||
inline bool IsValid(String str)
|
||||
{
|
||||
return str.Size > 0 && str.Data != nullptr && *str.Data;
|
||||
}
|
||||
@@ -89,7 +96,7 @@ namespace Juliet
|
||||
|
||||
inline bool ContainsChar(String str, char c)
|
||||
{
|
||||
return StringIsValid(FindChar(str, c));
|
||||
return IsValid(FindChar(str, c));
|
||||
}
|
||||
|
||||
// Return:
|
||||
@@ -117,6 +124,9 @@ namespace Juliet
|
||||
return result;
|
||||
}
|
||||
|
||||
JULIET_API uint32 StepUTF8(String& inStr);
|
||||
JULIET_API String FindString(String strLeft, String strRight);
|
||||
|
||||
// Case insensitive compare. Supports ASCII only
|
||||
// TODO: Support UNICODE
|
||||
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
||||
@@ -127,10 +137,8 @@ namespace Juliet
|
||||
// src and dst will be casted based on the encoding.
|
||||
// size will correspond to the number of characters
|
||||
// Will convert \0 character if present.
|
||||
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, const char* src, size_t srcLen,
|
||||
char*& dst, size_t& dstLen, size_t dstCapacity);
|
||||
extern JULIET_API bool ConvertString(String from, String to, const char* src, size_t srcLen, char*& dst,
|
||||
size_t& dstLen, size_t dstCapacity);
|
||||
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst);
|
||||
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst);
|
||||
|
||||
} // namespace Juliet
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Juliet
|
||||
|
||||
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
|
||||
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
|
||||
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, const void* inBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
|
||||
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
|
||||
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
|
||||
|
||||
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
|
||||
@@ -54,7 +54,7 @@ namespace Juliet
|
||||
|
||||
// Write formatted string into the stream.
|
||||
extern JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
|
||||
extern JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, const void* ptr, size_t size);
|
||||
extern JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
|
||||
|
||||
extern JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
|
||||
extern JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
|
||||
@@ -62,8 +62,8 @@ namespace Juliet
|
||||
extern JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
|
||||
|
||||
// TODO : Use memory arena because that Allocates
|
||||
extern JULIET_API uint8* LoadFile(String filename, size_t& outByteRead);
|
||||
extern JULIET_API uint8* LoadFile(NonNullPtr<IOStream> stream, size_t& outByteRead, bool closeStreamWhenDone);
|
||||
extern JULIET_API ByteBuffer LoadFile(String filename);
|
||||
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
|
||||
|
||||
extern JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Juliet
|
||||
std::deque<Entry> Entries;
|
||||
bool IsInitialized : 1;
|
||||
|
||||
friend void Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
||||
friend void Log(LogLevel level, LogCategory category, const char* fmt, va_list args);
|
||||
void AddEntry(Entry&& entry);
|
||||
static void OutputLog(Entry& entry);
|
||||
};
|
||||
@@ -43,4 +43,7 @@ namespace Juliet
|
||||
extern void JULIET_API InitializeLogManager();
|
||||
extern void JULIET_API ShutdownLogManager();
|
||||
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
|
||||
extern void JULIET_API LogMessage(LogCategory category, const char* fmt, ...);
|
||||
extern void JULIET_API LogWarning(LogCategory category, const char* fmt, ...);
|
||||
extern void JULIET_API LogError(LogCategory category, const char* fmt, ...);
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Juliet
|
||||
Graphics = 1,
|
||||
Networking = 2,
|
||||
Engine = 3,
|
||||
Editor = 4,
|
||||
Tool = 4,
|
||||
Game = 5,
|
||||
};
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Juliet.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
@@ -15,7 +17,7 @@ namespace Juliet
|
||||
void Free(Type* memory)
|
||||
{
|
||||
Assert(memory);
|
||||
free(memory);
|
||||
::free(memory);
|
||||
}
|
||||
// Free and Set the ptr to nullptr
|
||||
template <typename Type>
|
||||
@@ -23,7 +25,7 @@ namespace Juliet
|
||||
{
|
||||
if (memory)
|
||||
{
|
||||
free(memory);
|
||||
::free(memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,4 +19,5 @@ namespace Juliet
|
||||
}
|
||||
|
||||
#define MemSet memset
|
||||
#define MemCopy memcpy
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Juliet
|
||||
|
||||
// Pack
|
||||
NetworkPacket& operator<<(uint32 value);
|
||||
NetworkPacket& operator<<(const char* data);
|
||||
NetworkPacket& operator<<(char* data);
|
||||
|
||||
protected:
|
||||
void Append(ByteBuffer buffer);
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
#include <pch.h>
|
||||
|
||||
#include <Core/Memory/Allocator.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
void JulietAssert(const char* expression)
|
||||
{
|
||||
Juliet::Log(Juliet::LogLevel::Error, Juliet::LogCategory::Core, expression);
|
||||
Log(LogLevel::Error, LogCategory::Core, expression);
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
void Free(ByteBuffer& buffer)
|
||||
{
|
||||
if (buffer.Data)
|
||||
{
|
||||
Free(buffer.Data);
|
||||
}
|
||||
buffer = {};
|
||||
}
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace Juliet
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr char kUnknown_ASCII = '?';
|
||||
constexpr int32 kUnknown_UNICODE = 0xFFFD;
|
||||
|
||||
struct
|
||||
@@ -57,52 +56,162 @@ namespace Juliet
|
||||
*to = from;
|
||||
return 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Step(String& inStr, size_t byteToStep)
|
||||
uint32 StepUTF8(String& inStr)
|
||||
{
|
||||
// From rfc3629, the UTF-8 spec:
|
||||
// https://www.ietf.org/rfc/rfc3629.txt
|
||||
//
|
||||
// Char. number range | UTF-8 octet sequence
|
||||
// (hexadecimal) | (binary)
|
||||
// --------------------+---------------------------------------------
|
||||
// 0000 0000-0000 007F | 0xxxxxxx
|
||||
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
//
|
||||
// The function checks character validity and overlong (using too many bytes to encode the character) and return invalid utf8 char if detected.
|
||||
|
||||
// If string is empty then it's done.
|
||||
if (inStr.Size == 0)
|
||||
{
|
||||
Assert(inStr.Size >= byteToStep);
|
||||
|
||||
inStr.Data += byteToStep;
|
||||
inStr.Size -= byteToStep;
|
||||
}
|
||||
|
||||
uint32 StepUTF8(String& inStr, size_t byteToRead)
|
||||
{
|
||||
/*
|
||||
* From rfc3629, the UTF-8 spec:
|
||||
* https://www.ietf.org/rfc/rfc3629.txt
|
||||
*
|
||||
* Char. number range | UTF-8 octet sequence
|
||||
* (hexadecimal) | (binary)
|
||||
* --------------------+---------------------------------------------
|
||||
* 0000 0000-0000 007F | 0xxxxxxx
|
||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
|
||||
// If string is empty then it's done.
|
||||
if (inStr.Size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto str = reinterpret_cast<const uint8*>(CStr(inStr));
|
||||
const uint32 octet = byteToRead ? *str : 0;
|
||||
|
||||
if (octet == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((octet & 0x80) == 0x0) // One byte code point
|
||||
{
|
||||
Step(inStr, 1);
|
||||
return octet;
|
||||
}
|
||||
Assert(false && "StepUTF8 only supports one byte codepoints for now");
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
auto str = reinterpret_cast<const uint8*>(CStr(inStr));
|
||||
const uint32 octet = *str;
|
||||
bool isOverlong = false;
|
||||
bool isInvalid = false;
|
||||
bool isUTF16Surrogate = false;
|
||||
if (octet == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx
|
||||
{
|
||||
inStr.Data += 1;
|
||||
inStr.Size -= 1;
|
||||
return octet;
|
||||
}
|
||||
else if ((octet & 0xE0) == 0xC0) // Two bytes code point: 110xxxxx 10xxxxxx
|
||||
{
|
||||
const uint8 secondByte = str[1];
|
||||
if ((secondByte & 0xC0) == 0x80) // Make sure the trailing byte is correct
|
||||
{
|
||||
const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F);
|
||||
if (result >= 0x80) // If the result is smaller than 0x80 its an overlong!
|
||||
{
|
||||
inStr.Data += 2;
|
||||
inStr.Size -= 1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
isOverlong = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isInvalid = true;
|
||||
}
|
||||
}
|
||||
else if (((octet & 0xF0) == 0xE0)) // Three bytes code point: 1110xxxx 10xxxxxx 10xxxxxx
|
||||
{
|
||||
const uint8 secondByte = str[1];
|
||||
const uint8 thirdByte = str[2];
|
||||
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80)) // Make sure the trailing bytes are correct
|
||||
{
|
||||
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x3F) << 6;
|
||||
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F);
|
||||
const uint32 result = ((octet & 0x0F) << 12) | secondOctet | thirdOctet;
|
||||
if (result >= 0x0800) // if the result is smaller its an overlong.
|
||||
{
|
||||
if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate
|
||||
{
|
||||
inStr.Data += 3;
|
||||
inStr.Size -= 1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
isUTF16Surrogate = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isOverlong = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isInvalid = true;
|
||||
}
|
||||
}
|
||||
else if (((octet & 0xF8) == 0xF0))
|
||||
{ // Four bytes code point: 11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
const uint8 secondByte = str[1];
|
||||
const uint8 thirdByte = str[2];
|
||||
const uint8 fourthByte = str[3];
|
||||
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80) &&
|
||||
((fourthByte & 0xC0) == 0x80)) // // Make sure the trailing bytes are correct
|
||||
{
|
||||
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x1F) << 12;
|
||||
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F) << 6;
|
||||
const uint32 fourthOctet = static_cast<uint32>(fourthByte & 0x3F);
|
||||
const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet;
|
||||
if (result >= 0x10000) // If smaller its an overlong
|
||||
{
|
||||
inStr.Data += 4;
|
||||
inStr.Size -= 1;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
isOverlong = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isInvalid = true;
|
||||
}
|
||||
}
|
||||
LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s",
|
||||
isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false");
|
||||
inStr.Data += 1;
|
||||
return kInvalidUTF8;
|
||||
}
|
||||
|
||||
String FindString(String haystack, String needle)
|
||||
{
|
||||
if (!IsValid(needle))
|
||||
{
|
||||
return haystack;
|
||||
}
|
||||
|
||||
for (; IsValid(haystack); StepUTF8(haystack))
|
||||
{
|
||||
String tempHaystack = haystack;
|
||||
String testNeedle = needle;
|
||||
|
||||
while (IsValid(tempHaystack) && IsValid(testNeedle))
|
||||
{
|
||||
uint32 codepointHaystack = StepUTF8(tempHaystack);
|
||||
uint32 codepointNeedle = StepUTF8(testNeedle);
|
||||
if (codepointHaystack != codepointNeedle)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsValid(testNeedle))
|
||||
{
|
||||
return haystack;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int8 StringCompareCaseInsensitive(String str1, String str2)
|
||||
{
|
||||
@@ -113,13 +222,13 @@ namespace Juliet
|
||||
{
|
||||
{
|
||||
uint32 leftFolded[3];
|
||||
int8 num_folded = CaseFoldUnicode(StepUTF8(str1, 4), leftFolded);
|
||||
int8 num_folded = CaseFoldUnicode(StepUTF8(str1), leftFolded);
|
||||
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
|
||||
left = leftFolded[0];
|
||||
}
|
||||
{
|
||||
uint32 rightFolded[3];
|
||||
int8 num_folded = CaseFoldUnicode(StepUTF8(str2, 4), rightFolded);
|
||||
int8 num_folded = CaseFoldUnicode(StepUTF8(str2), rightFolded);
|
||||
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
|
||||
right = rightFolded[0];
|
||||
}
|
||||
@@ -139,15 +248,16 @@ namespace Juliet
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ConvertString(StringEncoding from, StringEncoding to, const char* src, size_t srcLen, char*& dst, size_t& dstLen, size_t dstCapacity)
|
||||
bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst)
|
||||
{
|
||||
Assert(src && *src);
|
||||
Assert(IsValid(src));
|
||||
|
||||
const char* srcStr = src;
|
||||
char* dstStr = dst;
|
||||
const char* srcStr = src.Data;
|
||||
char* dstStr = dst.Data;
|
||||
size_t remainingCapacity = dst.Capacity;
|
||||
|
||||
uint32 character = 0;
|
||||
while (srcLen > 0)
|
||||
while (src.Size > 0)
|
||||
{
|
||||
// Decode in character
|
||||
switch (from)
|
||||
@@ -165,7 +275,7 @@ namespace Juliet
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p[0] == 0xF0 && srcLen > 1 && (p[1] & 0xF0) == 0x80)
|
||||
if (p[0] == 0xF0 && src.Size > 1 && (p[1] & 0xF0) == 0x80)
|
||||
{
|
||||
overlong = true;
|
||||
}
|
||||
@@ -181,7 +291,7 @@ namespace Juliet
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p[0] == 0xE0 && srcLen > 1 && (p[1] & 0xE0) == 0x80)
|
||||
if (p[0] == 0xE0 && src.Size > 1 && (p[1] & 0xE0) == 0x80)
|
||||
{
|
||||
overlong = true;
|
||||
}
|
||||
@@ -217,8 +327,8 @@ namespace Juliet
|
||||
}
|
||||
}
|
||||
++srcStr;
|
||||
--srcLen;
|
||||
if (srcLen < left)
|
||||
--src.Size;
|
||||
if (src.Size < left)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Failed to convert string. Incomplete input sequence");
|
||||
return false;
|
||||
@@ -234,7 +344,7 @@ namespace Juliet
|
||||
character <<= 6;
|
||||
character |= (p[0] & 0x3F);
|
||||
++srcStr;
|
||||
--srcLen;
|
||||
--src.Size;
|
||||
}
|
||||
if (overlong)
|
||||
{
|
||||
@@ -268,7 +378,7 @@ namespace Juliet
|
||||
}
|
||||
if (character < 0x10000)
|
||||
{
|
||||
if (dstCapacity < 2)
|
||||
if (remainingCapacity < 2)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
||||
return false;
|
||||
@@ -277,12 +387,12 @@ namespace Juliet
|
||||
p[0] = static_cast<uint8>(character);
|
||||
|
||||
dstStr += 2;
|
||||
dstLen += 1;
|
||||
dstCapacity -= 2;
|
||||
dst.Size += 1;
|
||||
remainingCapacity -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dstCapacity < 4)
|
||||
if (remainingCapacity < 4)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
||||
return false;
|
||||
@@ -296,8 +406,8 @@ namespace Juliet
|
||||
p[2] = static_cast<uint8>(word2);
|
||||
|
||||
dstStr += 4;
|
||||
dstLen += 1;
|
||||
dstCapacity -= 4;
|
||||
dst.Size += 1;
|
||||
remainingCapacity -= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -313,10 +423,10 @@ namespace Juliet
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConvertString(String from, String to, const char* src, size_t srcSize, char*& dst, size_t& dstSize, size_t dstCapacity)
|
||||
bool ConvertString(String from, String to, String src, StringBuffer& dst)
|
||||
{
|
||||
Assert(StringIsValid(from));
|
||||
Assert(StringIsValid(to));
|
||||
Assert(IsValid(from));
|
||||
Assert(IsValid(to));
|
||||
|
||||
// First find the encoding of the strings
|
||||
auto sourceFormat = StringEncoding::Unknown;
|
||||
@@ -346,6 +456,6 @@ namespace Juliet
|
||||
return false;
|
||||
}
|
||||
|
||||
return ConvertString(sourceFormat, destFormat, src, srcSize, dst, dstSize, dstCapacity);
|
||||
return ConvertString(sourceFormat, destFormat, src, dst);
|
||||
}
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Juliet
|
||||
|
||||
String GetBasePath()
|
||||
{
|
||||
if (!StringIsValid(CachedBasePath))
|
||||
if (!IsValid(CachedBasePath))
|
||||
{
|
||||
CachedBasePath = Platform::GetBasePath();
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace Juliet
|
||||
|
||||
void ShutdownFilesystem()
|
||||
{
|
||||
if (StringIsValid(CachedBasePath))
|
||||
if (IsValid(CachedBasePath))
|
||||
{
|
||||
CachedBasePath.Size = 0;
|
||||
SafeFree(CachedBasePath.Data);
|
||||
|
||||
@@ -11,12 +11,12 @@ namespace Juliet
|
||||
{
|
||||
IOStream* IOFromFile(String filename, String mode)
|
||||
{
|
||||
if (!StringIsValid(filename))
|
||||
if (!IsValid(filename))
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream on invalid filename");
|
||||
return nullptr;
|
||||
}
|
||||
if (!StringIsValid(mode))
|
||||
if (!IsValid(mode))
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream with invalid mode");
|
||||
return nullptr;
|
||||
@@ -54,10 +54,11 @@ namespace Juliet
|
||||
|
||||
Assert(writtenSize >= 0);
|
||||
|
||||
return IOWrite(stream, formattedBuffer, static_cast<size_t>(writtenSize));
|
||||
ByteBuffer buffer = {.Data = reinterpret_cast<Byte*>(formattedBuffer), .Size = static_cast<size_t>(writtenSize) };
|
||||
return IOWrite(stream, buffer);
|
||||
}
|
||||
|
||||
size_t IOWrite(NonNullPtr<IOStream> stream, const void* ptr, size_t size)
|
||||
size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer)
|
||||
{
|
||||
if (!stream->Interface.Write)
|
||||
{
|
||||
@@ -68,12 +69,12 @@ namespace Juliet
|
||||
|
||||
stream->Status = IOStreamStatus::Ready;
|
||||
|
||||
if (size == 0)
|
||||
if (!IsValid(inBuffer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t writtenBytes = stream->Interface.Write(stream->Data, ptr, size, &stream->Status);
|
||||
size_t writtenBytes = stream->Interface.Write(stream->Data, inBuffer, &stream->Status);
|
||||
if ((writtenBytes == 0) && (stream->Status == IOStreamStatus::Ready))
|
||||
{
|
||||
stream->Status = IOStreamStatus::Error;
|
||||
@@ -131,23 +132,32 @@ namespace Juliet
|
||||
return stream->Interface.Size(stream->Data);
|
||||
}
|
||||
|
||||
uint8* LoadFile(String filename, size_t& outByteRead)
|
||||
ByteBuffer LoadFile(String filename)
|
||||
{
|
||||
IOStream* stream = IOFromFile(filename, ConstString("rb"));
|
||||
IOStream* stream = IOFromFile(filename, WrapString("rb"));
|
||||
if (!stream)
|
||||
{
|
||||
outByteRead = 0;
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
return LoadFile(stream, outByteRead, true);
|
||||
return LoadFile(stream, true);
|
||||
}
|
||||
|
||||
uint8* LoadFile(NonNullPtr<IOStream> stream, size_t& outByteRead, bool closeStreamWhenDone)
|
||||
ByteBuffer LoadFile(NonNullPtr<IOStream> stream, bool closeStreamWhenDone)
|
||||
{
|
||||
constexpr size_t kFileChunkSize = 1024;
|
||||
uint8* data = nullptr;
|
||||
uint8* newData = nullptr;
|
||||
size_t totalSize = 0;
|
||||
ByteBuffer resultBuffer = {};
|
||||
|
||||
auto deferred = Defer(
|
||||
[&]()
|
||||
{
|
||||
if (closeStreamWhenDone)
|
||||
{
|
||||
IOClose(stream);
|
||||
}
|
||||
});
|
||||
|
||||
// Try reading the size from the stream, if failing we'll try to read it chunk by chunk
|
||||
bool loadChunks = false;
|
||||
@@ -160,7 +170,7 @@ namespace Juliet
|
||||
data = static_cast<uint8*>(Malloc(static_cast<size_t>(size + 1)));
|
||||
if (!data)
|
||||
{
|
||||
goto done;
|
||||
return {};
|
||||
}
|
||||
|
||||
while (true)
|
||||
@@ -174,8 +184,7 @@ namespace Juliet
|
||||
if (!newData)
|
||||
{
|
||||
Free(data);
|
||||
data = nullptr;
|
||||
goto done;
|
||||
return {};
|
||||
}
|
||||
data = newData;
|
||||
}
|
||||
@@ -201,14 +210,10 @@ namespace Juliet
|
||||
// Adding null terminator
|
||||
data[totalSize] = '\0';
|
||||
|
||||
done:
|
||||
outByteRead = totalSize;
|
||||
resultBuffer.Data = reinterpret_cast<Byte*>(data);
|
||||
resultBuffer.Size = totalSize;
|
||||
|
||||
if (closeStreamWhenDone)
|
||||
{
|
||||
IOClose(stream);
|
||||
}
|
||||
return data;
|
||||
return resultBuffer;
|
||||
}
|
||||
|
||||
bool IOClose(NonNullPtr<IOStream> stream)
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace Juliet::Internal
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, const void* inBuffer, size_t size, NonNullPtr<IOStreamStatus> status)
|
||||
size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status)
|
||||
{
|
||||
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
|
||||
DWORD bytes;
|
||||
@@ -158,12 +158,12 @@ namespace Juliet::Internal
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteFile(win32Payload->Handle, inBuffer, static_cast<DWORD>(size), &bytes, nullptr))
|
||||
if (!WriteFile(win32Payload->Handle, inBuffer.Data, static_cast<DWORD>(inBuffer.Size), &bytes, nullptr))
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "IoStream:FileWrite:Error writing to datastream: %d", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
if (bytes == 0 && size > 0)
|
||||
if (bytes == 0 && inBuffer.Size > 0)
|
||||
{
|
||||
*status = IOStreamStatus::NotReady;
|
||||
}
|
||||
@@ -199,18 +199,17 @@ namespace Juliet::Internal
|
||||
|
||||
#if _DEBUG
|
||||
// Making sure the mode is valid
|
||||
String modeView = mode;
|
||||
size_t modeLength = StringLength(modeView);
|
||||
size_t modeLength = StringLength(mode);
|
||||
Assert((modeLength <= 2) &&
|
||||
"Mode should have at most 2 characters, one being either r,w or a and the other can only be +");
|
||||
if (modeLength == 1)
|
||||
{
|
||||
Assert((modeView.Data[0] == 'r' || modeView.Data[0] == 'w' || modeView.Data[0] == 'a') &&
|
||||
Assert((mode.Data[0] == 'r' || mode.Data[0] == 'w' || mode.Data[0] == 'a') &&
|
||||
"Invalid Mode. First char is not r,w or a");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert((modeView.Data[1] == '+' || modeView.Data[1] == 'b') && "Invalid Mode. Second char is not +");
|
||||
Assert((mode.Data[1] == '+' || mode.Data[1] == 'b') && "Invalid Mode. Second char is not +");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -229,11 +228,12 @@ namespace Juliet::Internal
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: Detect when folder is missing and create it if in w or a mode.
|
||||
HANDLE hFile = CreateFileA(CStr(filename), (canWrite | canRead), (canWrite) ? 0 : FILE_SHARE_READ, nullptr,
|
||||
(openExisting | createAlways | openAlways), FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: couldn't open %s", CStr(filename));
|
||||
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: couldn't open %s. Error: %d", CStr(filename), GetLastError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,15 +87,12 @@ namespace Juliet
|
||||
LogManagerSingleton.Shutdown();
|
||||
}
|
||||
|
||||
void Log(LogLevel level, LogCategory category, const char* fmt, ...)
|
||||
void Log(LogLevel level, LogCategory category, const char* fmt, va_list args)
|
||||
{
|
||||
// TODO : Revisit, copy from https://github.com/Eclmist/Ether/blob/develop/src/common/logging/loggingmanager.cpp
|
||||
char formattedBuffer[4096];
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
(void)vsprintf_s(formattedBuffer, fmt, args); // Cast to void to ignore the return type. TODO : Juliet format function
|
||||
va_end(args);
|
||||
|
||||
std::string formattedText(formattedBuffer);
|
||||
|
||||
@@ -114,4 +111,35 @@ namespace Juliet
|
||||
}
|
||||
}
|
||||
|
||||
void Log(LogLevel level, LogCategory category, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Log(level, category, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogMessage(LogCategory category, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Log(LogLevel::Message, category, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogWarning(LogCategory category, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Log(LogLevel::Warning, category, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogError(LogCategory category, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Log(LogLevel::Error, category, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <Core/Networking/NetworkPacket.h>
|
||||
#include <Core/Networking/SocketPlatformImpl.h>
|
||||
|
||||
#define TO_BUFFER(ptr) reinterpret_cast<const Byte*>(ptr)
|
||||
#define TO_BUFFER(ptr) reinterpret_cast<Byte*>(ptr)
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
@@ -29,12 +29,12 @@ namespace Juliet
|
||||
// Begin - Pack
|
||||
NetworkPacket& NetworkPacket::operator<<(uint32 value)
|
||||
{
|
||||
const uint32 toWrite = htonl(value);
|
||||
uint32 toWrite = htonl(value);
|
||||
Append({ TO_BUFFER(&toWrite), sizeof(toWrite) });
|
||||
return *this;
|
||||
}
|
||||
|
||||
NetworkPacket& NetworkPacket::operator<<(const char* data)
|
||||
NetworkPacket& NetworkPacket::operator<<(char* data)
|
||||
{
|
||||
Assert(data && "NetworkPacket::operator<< Data must not be null");
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include <pch.h>
|
||||
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
#include <Graphics/D3D12/D3D12Common.h>
|
||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/DX12Includes.h>
|
||||
|
||||
Reference in New Issue
Block a user