Files
UnrealEngineUWP/Engine/Source/Developer/Windows/LiveCodingServer/Private/External/LC_ImmutableString.h
Ben Marsh e1fe0cc030 Integrating live coding feature (aka Live++) into UE4.
Allows fast iteration of C++ changes without restarting the application. To use, select the "Live Coding (Experimental)" mode from the drop down menu next to the editor's compile button, or type "LiveCoding" into the console for a monolithic build. Press Ctrl+Alt+F11 to find changes and compile.

Changes vs standalone Live++ version:

* UBT is used to execute builds. This allows standard UE4 adaptive unity mode, allows us to reuse object files when we do regular builds, supports using any build executor allowed by UBT (XGE, SNDBS, etc..).
* Adding new source files is supported.
* Custom visualizer for FNames is supported via a weakly linked symbol in a static library (Engine/Extras/NatvisHelpers).
* Settings are exposed in the editor's project settings dialog.
* Standalone application has been rewritten as a Slate app ("LiveCodingConsole"). There is an additional option to start the program as hidden, where it will not be visible until Ctrl+Alt+F11 is hit. Similarly, closing the window will hide it instead of closing the application.
* Does not require a standalone licensed version of Live++.

Known issues:

* Does not currently support class layout changes / object reinstancing

#rb none
#fyi Marc.Audy, Stefan.Boberg, Nick.Penwarden
#jira

[CL 5304722 by Ben Marsh in 4.22 branch]
2019-03-05 15:54:02 -05:00

191 lines
4.2 KiB
C++

// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#pragma once
#include "CoreTypes.h"
#include "LC_Memory.h"
#include <string>
class ImmutableString;
// conversion utilities between ImmutableString and other string representations
namespace string
{
ImmutableString ToUtf8String(const wchar_t* str);
ImmutableString ToUtf8String(const wchar_t* str, size_t count);
ImmutableString ToUtf8String(const std::wstring& str);
std::string ToAnsiString(const ImmutableString& utf8Str);
std::wstring ToWideString(const ImmutableString& utf8Str);
}
class ImmutableString
{
public:
static const uint32_t NOT_FOUND = 0xFFFFFFFFu;
struct Hasher
{
__forceinline size_t operator()(const ImmutableString& key) const
{
return key.GetHash();
}
};
struct Comparator
{
__forceinline bool operator()(const ImmutableString& lhs, const ImmutableString& rhs) const
{
return (lhs == rhs);
}
};
inline bool operator==(const ImmutableString& rhs) const
{
if (GetHash() != rhs.GetHash())
{
return false;
}
if (GetLength() != rhs.GetLength())
{
return false;
}
// both strings are the same length
const char* lhsStr = c_str();
const char* rhsStr = rhs.c_str();
for (/* nothing */; *lhsStr != '\0'; ++lhsStr, ++rhsStr)
{
if (*lhsStr != *rhsStr)
{
return false;
}
}
// reached the end of the string, must be the same
return true;
}
inline bool operator!=(const ImmutableString& rhs) const
{
return !(*this == rhs);
}
// leaves the string empty, does not allocate anything
ImmutableString(void);
// copy and hash
explicit ImmutableString(const char* str);
// copy and hash
ImmutableString(const char* str, size_t length);
// copy
ImmutableString(const ImmutableString& other);
// move constructor
ImmutableString(ImmutableString&& other);
// disallow assignment operator
ImmutableString& operator=(const ImmutableString& other) = delete;
// move assignment operator
ImmutableString& operator=(ImmutableString&& other);
// destructor
~ImmutableString(void);
uint32_t Find(char character) const;
inline uint32_t GetHash(void) const
{
return m_data.longString.hash;
}
inline uint32_t GetLength(void) const
{
if (IsShortString())
{
// clear the MSB
return static_cast<uint32_t>(m_data.shortString.length & ShortString::MSB_CLEAR_MASK);
}
else
{
return m_data.longString.length;
}
}
inline const char* c_str(void) const
{
if (IsShortString())
{
return m_data.shortString.str;
}
else
{
return m_data.longString.str;
}
}
private:
// short string optimization:
// the layout of the long string is chosen so that we can store extra information in the first byte of length,
// assuming that no string will ever be longer than 2^24-1 characters.
// NOTE: on little-endian architectures, LongString::length conincides with the memory address of ShortString::length
static inline bool FitsIntoShortString(size_t lengthWithoutNullTerminator)
{
return (lengthWithoutNullTerminator < sizeof(ShortString::str));
}
inline bool IsShortString(void) const
{
// short strings have the MSB set
return ((m_data.shortString.length & ShortString::MSB_SET_MASK) != 0u);
}
void Free(void);
// layout of a long string:
// 4/8 bytes pointer to string, 3 byte length, 1 zero byte, 4 byte hash
struct LongString
{
const char* str;
uint32_t length;
uint32_t hash;
};
// layout of a short string:
// the actual string data (including the null terminator), 1 byte storing the length of the short string, 4 byte hash
struct ShortString
{
static const uint8_t MSB_SET_MASK = 0x80u; // mask for setting the MSB
static const uint8_t MSB_CLEAR_MASK = 0x7Fu; // mask for clearing the MSB
char str[sizeof(const char*) + sizeof(uint32_t) - 1];
uint8_t length;
uint32_t hash;
};
static_assert(sizeof(LongString) == sizeof(ShortString), "Broken short string optimization");
union Data
{
LongString longString;
ShortString shortString;
};
Data m_data;
};
namespace string
{
ImmutableString ToUtf8String(const wchar_t* str);
ImmutableString ToUtf8String(const wchar_t* str, size_t count);
ImmutableString ToUtf8String(const std::wstring& str);
std::string ToAnsiString(const ImmutableString& utf8Str);
std::wstring ToWideString(const ImmutableString& utf8Str);
}