Last active
June 14, 2017 10:39
-
-
Save dpethes/46f08c88bac0822fda05db4152fd00b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public unsafe class Utf8Buffer | |
{ | |
private const int BufferSize = 4 * 1024 * 20; //20k utf8 chars at least | |
private IntPtr _memPtr; | |
private byte* _buffer; | |
private int _usedBytes; | |
public Utf8Buffer() | |
{ | |
Init(); | |
} | |
public void Init() | |
{ | |
if (_buffer != null) | |
return; | |
_memPtr = Marshal.AllocHGlobal(BufferSize); | |
_buffer = (byte*)_memPtr; | |
} | |
//free on ImGui.Shutdown | |
public void Free() | |
{ | |
Marshal.FreeHGlobal(_memPtr); | |
} | |
//reset buffer position and make sure that any pointer into it will result in null-terminated string | |
public void Reset() | |
{ | |
_usedBytes = 0; | |
_buffer[0] = 0; | |
_buffer[BufferSize - 1] = 0; | |
} | |
public byte* FromStr(string str) | |
{ | |
//If the maximum possible string length doesn't fit our buffer, just return an empty string. | |
//Probly some message like <Utf8Buffer: couldn't convert text> would be better, so user knows what happened | |
//If _usedBytes equals 0, we could also re-allocate the buffer | |
var maxBytes = str.Length * 4 + 1; | |
if (BufferSize < maxBytes) | |
{ | |
Reset(); | |
return _buffer; | |
} | |
//Wrap if it's possible that the string won't fit. | |
//This is ok, assuming one ImGui call doesn't use longer strings (sum of their utf8 byte lengths) that would fit into our buffer. | |
if (BufferSize < _usedBytes + maxBytes) | |
{ | |
Reset(); | |
} | |
int bytesLeft = BufferSize - _usedBytes - 1; | |
int byteCount = 0; | |
byte* dest = _buffer + _usedBytes; | |
fixed (char* c = str) | |
{ | |
byteCount = Encoding.UTF8.GetBytes(c, str.Length, dest, bytesLeft); | |
} | |
dest[byteCount] = 0; | |
_usedBytes += byteCount + 1; | |
return dest; | |
} | |
//Assumes that utf8Buffer is properly allocated and the str would fit | |
public byte* FromStr(string str, byte* utf8Buffer) | |
{ | |
var maxBytes = str.Length * 4; | |
int byteCount = 0; | |
fixed (char* c = str) | |
{ | |
byteCount = Encoding.UTF8.GetBytes(c, str.Length, utf8Buffer, maxBytes); | |
} | |
utf8Buffer[byteCount] = 0; | |
return utf8Buffer; | |
} | |
public string ToStr(byte* b) | |
{ | |
if (b == null) | |
return string.Empty; | |
int length = 0; | |
while (b[length] != '\0') | |
length++; | |
//if .Net >= 4.5 | |
//return Encoding.UTF8.GetString(b, length); | |
byte[] buffer = new byte[length]; | |
Marshal.Copy((IntPtr)b, buffer, 0, length); | |
return Encoding.UTF8.GetString(buffer, 0, length); | |
} | |
} | |
//usage: | |
public static class ImGui | |
{ | |
private static Utf8Buffer _utf8 = new Utf8Buffer(); | |
... | |
public static unsafe void Text(string message) | |
{ | |
ImGuiNative.igText(_utf8.FromStr(message)); | |
//or | |
byte* utf8Ptr = stackalloc byte[message.Length * 4 + 1]; | |
ImGuiNative.igText(_utf8.FromStr(message, utf8Ptr)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment