Add a 2048-byte limit to stack allocation for strings.

internals
Eric Mellino 6 years ago
parent 37e468dbe5
commit 7ac01b7689
  1. 27
      src/CodeGenerator/Program.cs
  2. 21
      src/ImGui.NET/Generated/GlyphRangesBuilder.gen.cs
  3. 126
      src/ImGui.NET/Generated/ImFontAtlas.gen.cs
  4. 8946
      src/ImGui.NET/Generated/ImGui.gen.cs
  5. 21
      src/ImGui.NET/Generated/ImGuiIO.gen.cs
  6. 21
      src/ImGui.NET/Generated/ImGuiInputTextCallbackData.gen.cs
  7. 21
      src/ImGui.NET/Generated/ImGuiPayload.gen.cs
  8. 21
      src/ImGui.NET/Generated/ImGuiTextBuffer.gen.cs
  9. 84
      src/ImGui.NET/Generated/ImGuiTextFilter.gen.cs
  10. 194
      src/ImGui.NET/ImGui.Manual.cs
  11. 22
      src/ImGui.NET/Util.cs

@ -618,24 +618,35 @@ namespace CodeGenerator
else else
{ {
preCallLines.Add($"byte* {nativeArgName};"); preCallLines.Add($"byte* {nativeArgName};");
preCallLines.Add($"int {correctedIdentifier}_byteCount = 0;");
if (!hasDefault) if (!hasDefault)
{ {
preCallLines.Add($"if ({textToEncode} != null)"); preCallLines.Add($"if ({textToEncode} != null)");
preCallLines.Add("{"); preCallLines.Add("{");
} }
preCallLines.Add($" int {correctedIdentifier}_byteCount = Encoding.UTF8.GetByteCount({textToEncode});"); preCallLines.Add($" {correctedIdentifier}_byteCount = Encoding.UTF8.GetByteCount({textToEncode});");
preCallLines.Add($" byte* {nativeArgName}_stackBytes = stackalloc byte[{correctedIdentifier}_byteCount + 1];"); preCallLines.Add($" if ({correctedIdentifier}_byteCount > Util.StackAllocationSizeLimit)");
preCallLines.Add($" {nativeArgName} = {nativeArgName}_stackBytes;"); preCallLines.Add($" {{");
preCallLines.Add($" fixed (char* {correctedIdentifier}_ptr = {textToEncode})"); preCallLines.Add($" {nativeArgName} = Util.Allocate({correctedIdentifier}_byteCount + 1);");
preCallLines.Add(" {"); preCallLines.Add($" }}");
preCallLines.Add($" int {nativeArgName}_offset = Encoding.UTF8.GetBytes({correctedIdentifier}_ptr, {textToEncode}.Length, {nativeArgName}, {correctedIdentifier}_byteCount);"); preCallLines.Add($" else");
preCallLines.Add($" {nativeArgName}[{nativeArgName}_offset] = 0;"); preCallLines.Add($" {{");
preCallLines.Add(" }"); preCallLines.Add($" byte* {nativeArgName}_stackBytes = stackalloc byte[{correctedIdentifier}_byteCount + 1];");
preCallLines.Add($" {nativeArgName} = {nativeArgName}_stackBytes;");
preCallLines.Add($" }}");
preCallLines.Add($" int {nativeArgName}_offset = Util.GetUtf8({textToEncode}, {nativeArgName}, {correctedIdentifier}_byteCount);");
preCallLines.Add($" {nativeArgName}[{nativeArgName}_offset] = 0;");
if (!hasDefault) if (!hasDefault)
{ {
preCallLines.Add("}"); preCallLines.Add("}");
preCallLines.Add($"else {{ {nativeArgName} = null; }}"); preCallLines.Add($"else {{ {nativeArgName} = null; }}");
} }
postCallLines.Add($"if ({correctedIdentifier}_byteCount > Util.StackAllocationSizeLimit)");
postCallLines.Add($"{{");
postCallLines.Add($" Util.Free({nativeArgName});");
postCallLines.Add($"}}");
} }
} }
else if (tr.Type == "char* []") else if (tr.Type == "char* []")

@ -30,20 +30,29 @@ namespace ImGuiNET
public void AddText(string text) public void AddText(string text)
{ {
byte* native_text; byte* native_text;
int text_byteCount = 0;
if (text != null) if (text != null)
{ {
int text_byteCount = Encoding.UTF8.GetByteCount(text); text_byteCount = Encoding.UTF8.GetByteCount(text);
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1]; if (text_byteCount > Util.StackAllocationSizeLimit)
native_text = native_text_stackBytes;
fixed (char* text_ptr = text)
{ {
int native_text_offset = Encoding.UTF8.GetBytes(text_ptr, text.Length, native_text, text_byteCount); native_text = Util.Allocate(text_byteCount + 1);
native_text[native_text_offset] = 0;
} }
else
{
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1];
native_text = native_text_stackBytes;
}
int native_text_offset = Util.GetUtf8(text, native_text, text_byteCount);
native_text[native_text_offset] = 0;
} }
else { native_text = null; } else { native_text = null; }
byte* native_text_end = null; byte* native_text_end = null;
ImGuiNative.GlyphRangesBuilder_AddText(NativePtr, native_text, native_text_end); ImGuiNative.GlyphRangesBuilder_AddText(NativePtr, native_text, native_text_end);
if (text_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_text);
}
} }
public void BuildRanges(out ImVector out_ranges) public void BuildRanges(out ImVector out_ranges)
{ {

@ -85,121 +85,175 @@ namespace ImGuiNET
public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels) public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels)
{ {
byte* native_filename; byte* native_filename;
int filename_byteCount = 0;
if (filename != null) if (filename != null)
{ {
int filename_byteCount = Encoding.UTF8.GetByteCount(filename); filename_byteCount = Encoding.UTF8.GetByteCount(filename);
byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1]; if (filename_byteCount > Util.StackAllocationSizeLimit)
native_filename = native_filename_stackBytes;
fixed (char* filename_ptr = filename)
{ {
int native_filename_offset = Encoding.UTF8.GetBytes(filename_ptr, filename.Length, native_filename, filename_byteCount); native_filename = Util.Allocate(filename_byteCount + 1);
native_filename[native_filename_offset] = 0;
} }
else
{
byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1];
native_filename = native_filename_stackBytes;
}
int native_filename_offset = Util.GetUtf8(filename, native_filename, filename_byteCount);
native_filename[native_filename_offset] = 0;
} }
else { native_filename = null; } else { native_filename = null; }
ImFontConfig* font_cfg = null; ImFontConfig* font_cfg = null;
ushort* glyph_ranges = null; ushort* glyph_ranges = null;
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, font_cfg, glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, font_cfg, glyph_ranges);
if (filename_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_filename);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels, ImFontConfigPtr font_cfg) public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels, ImFontConfigPtr font_cfg)
{ {
byte* native_filename; byte* native_filename;
int filename_byteCount = 0;
if (filename != null) if (filename != null)
{ {
int filename_byteCount = Encoding.UTF8.GetByteCount(filename); filename_byteCount = Encoding.UTF8.GetByteCount(filename);
byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1]; if (filename_byteCount > Util.StackAllocationSizeLimit)
native_filename = native_filename_stackBytes; {
fixed (char* filename_ptr = filename) native_filename = Util.Allocate(filename_byteCount + 1);
}
else
{ {
int native_filename_offset = Encoding.UTF8.GetBytes(filename_ptr, filename.Length, native_filename, filename_byteCount); byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1];
native_filename[native_filename_offset] = 0; native_filename = native_filename_stackBytes;
} }
int native_filename_offset = Util.GetUtf8(filename, native_filename, filename_byteCount);
native_filename[native_filename_offset] = 0;
} }
else { native_filename = null; } else { native_filename = null; }
ImFontConfig* native_font_cfg = font_cfg.NativePtr; ImFontConfig* native_font_cfg = font_cfg.NativePtr;
ushort* glyph_ranges = null; ushort* glyph_ranges = null;
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, native_font_cfg, glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, native_font_cfg, glyph_ranges);
if (filename_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_filename);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels, ImFontConfigPtr font_cfg, IntPtr glyph_ranges) public ImFontPtr AddFontFromFileTTF(string filename, float size_pixels, ImFontConfigPtr font_cfg, IntPtr glyph_ranges)
{ {
byte* native_filename; byte* native_filename;
int filename_byteCount = 0;
if (filename != null) if (filename != null)
{ {
int filename_byteCount = Encoding.UTF8.GetByteCount(filename); filename_byteCount = Encoding.UTF8.GetByteCount(filename);
byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1]; if (filename_byteCount > Util.StackAllocationSizeLimit)
native_filename = native_filename_stackBytes; {
fixed (char* filename_ptr = filename) native_filename = Util.Allocate(filename_byteCount + 1);
}
else
{ {
int native_filename_offset = Encoding.UTF8.GetBytes(filename_ptr, filename.Length, native_filename, filename_byteCount); byte* native_filename_stackBytes = stackalloc byte[filename_byteCount + 1];
native_filename[native_filename_offset] = 0; native_filename = native_filename_stackBytes;
} }
int native_filename_offset = Util.GetUtf8(filename, native_filename, filename_byteCount);
native_filename[native_filename_offset] = 0;
} }
else { native_filename = null; } else { native_filename = null; }
ImFontConfig* native_font_cfg = font_cfg.NativePtr; ImFontConfig* native_font_cfg = font_cfg.NativePtr;
ushort* native_glyph_ranges = (ushort*)glyph_ranges.ToPointer(); ushort* native_glyph_ranges = (ushort*)glyph_ranges.ToPointer();
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, native_font_cfg, native_glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromFileTTF(NativePtr, native_filename, size_pixels, native_font_cfg, native_glyph_ranges);
if (filename_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_filename);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels) public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels)
{ {
byte* native_compressed_font_data_base85; byte* native_compressed_font_data_base85;
int compressed_font_data_base85_byteCount = 0;
if (compressed_font_data_base85 != null) if (compressed_font_data_base85 != null)
{ {
int compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85); compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85);
byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1]; if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes;
fixed (char* compressed_font_data_base85_ptr = compressed_font_data_base85)
{ {
int native_compressed_font_data_base85_offset = Encoding.UTF8.GetBytes(compressed_font_data_base85_ptr, compressed_font_data_base85.Length, native_compressed_font_data_base85, compressed_font_data_base85_byteCount); native_compressed_font_data_base85 = Util.Allocate(compressed_font_data_base85_byteCount + 1);
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0;
} }
else
{
byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1];
native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes;
}
int native_compressed_font_data_base85_offset = Util.GetUtf8(compressed_font_data_base85, native_compressed_font_data_base85, compressed_font_data_base85_byteCount);
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0;
} }
else { native_compressed_font_data_base85 = null; } else { native_compressed_font_data_base85 = null; }
ImFontConfig* font_cfg = null; ImFontConfig* font_cfg = null;
ushort* glyph_ranges = null; ushort* glyph_ranges = null;
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, font_cfg, glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, font_cfg, glyph_ranges);
if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_compressed_font_data_base85);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels, ImFontConfigPtr font_cfg) public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels, ImFontConfigPtr font_cfg)
{ {
byte* native_compressed_font_data_base85; byte* native_compressed_font_data_base85;
int compressed_font_data_base85_byteCount = 0;
if (compressed_font_data_base85 != null) if (compressed_font_data_base85 != null)
{ {
int compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85); compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85);
byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1]; if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes; {
fixed (char* compressed_font_data_base85_ptr = compressed_font_data_base85) native_compressed_font_data_base85 = Util.Allocate(compressed_font_data_base85_byteCount + 1);
}
else
{ {
int native_compressed_font_data_base85_offset = Encoding.UTF8.GetBytes(compressed_font_data_base85_ptr, compressed_font_data_base85.Length, native_compressed_font_data_base85, compressed_font_data_base85_byteCount); byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1];
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0; native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes;
} }
int native_compressed_font_data_base85_offset = Util.GetUtf8(compressed_font_data_base85, native_compressed_font_data_base85, compressed_font_data_base85_byteCount);
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0;
} }
else { native_compressed_font_data_base85 = null; } else { native_compressed_font_data_base85 = null; }
ImFontConfig* native_font_cfg = font_cfg.NativePtr; ImFontConfig* native_font_cfg = font_cfg.NativePtr;
ushort* glyph_ranges = null; ushort* glyph_ranges = null;
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, native_font_cfg, glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, native_font_cfg, glyph_ranges);
if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_compressed_font_data_base85);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels, ImFontConfigPtr font_cfg, IntPtr glyph_ranges) public ImFontPtr AddFontFromMemoryCompressedBase85TTF(string compressed_font_data_base85, float size_pixels, ImFontConfigPtr font_cfg, IntPtr glyph_ranges)
{ {
byte* native_compressed_font_data_base85; byte* native_compressed_font_data_base85;
int compressed_font_data_base85_byteCount = 0;
if (compressed_font_data_base85 != null) if (compressed_font_data_base85 != null)
{ {
int compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85); compressed_font_data_base85_byteCount = Encoding.UTF8.GetByteCount(compressed_font_data_base85);
byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1]; if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes; {
fixed (char* compressed_font_data_base85_ptr = compressed_font_data_base85) native_compressed_font_data_base85 = Util.Allocate(compressed_font_data_base85_byteCount + 1);
}
else
{ {
int native_compressed_font_data_base85_offset = Encoding.UTF8.GetBytes(compressed_font_data_base85_ptr, compressed_font_data_base85.Length, native_compressed_font_data_base85, compressed_font_data_base85_byteCount); byte* native_compressed_font_data_base85_stackBytes = stackalloc byte[compressed_font_data_base85_byteCount + 1];
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0; native_compressed_font_data_base85 = native_compressed_font_data_base85_stackBytes;
} }
int native_compressed_font_data_base85_offset = Util.GetUtf8(compressed_font_data_base85, native_compressed_font_data_base85, compressed_font_data_base85_byteCount);
native_compressed_font_data_base85[native_compressed_font_data_base85_offset] = 0;
} }
else { native_compressed_font_data_base85 = null; } else { native_compressed_font_data_base85 = null; }
ImFontConfig* native_font_cfg = font_cfg.NativePtr; ImFontConfig* native_font_cfg = font_cfg.NativePtr;
ushort* native_glyph_ranges = (ushort*)glyph_ranges.ToPointer(); ushort* native_glyph_ranges = (ushort*)glyph_ranges.ToPointer();
ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, native_font_cfg, native_glyph_ranges); ImFont* ret = ImGuiNative.ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(NativePtr, native_compressed_font_data_base85, size_pixels, native_font_cfg, native_glyph_ranges);
if (compressed_font_data_base85_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_compressed_font_data_base85);
}
return new ImFontPtr(ret); return new ImFontPtr(ret);
} }
public ImFontPtr AddFontFromMemoryCompressedTTF(IntPtr compressed_font_data, int compressed_font_size, float size_pixels) public ImFontPtr AddFontFromMemoryCompressedTTF(IntPtr compressed_font_data, int compressed_font_size, float size_pixels)

File diff suppressed because it is too large Load Diff

@ -173,19 +173,28 @@ namespace ImGuiNET
public void AddInputCharactersUTF8(string utf8_chars) public void AddInputCharactersUTF8(string utf8_chars)
{ {
byte* native_utf8_chars; byte* native_utf8_chars;
int utf8_chars_byteCount = 0;
if (utf8_chars != null) if (utf8_chars != null)
{ {
int utf8_chars_byteCount = Encoding.UTF8.GetByteCount(utf8_chars); utf8_chars_byteCount = Encoding.UTF8.GetByteCount(utf8_chars);
byte* native_utf8_chars_stackBytes = stackalloc byte[utf8_chars_byteCount + 1]; if (utf8_chars_byteCount > Util.StackAllocationSizeLimit)
native_utf8_chars = native_utf8_chars_stackBytes;
fixed (char* utf8_chars_ptr = utf8_chars)
{ {
int native_utf8_chars_offset = Encoding.UTF8.GetBytes(utf8_chars_ptr, utf8_chars.Length, native_utf8_chars, utf8_chars_byteCount); native_utf8_chars = Util.Allocate(utf8_chars_byteCount + 1);
native_utf8_chars[native_utf8_chars_offset] = 0;
} }
else
{
byte* native_utf8_chars_stackBytes = stackalloc byte[utf8_chars_byteCount + 1];
native_utf8_chars = native_utf8_chars_stackBytes;
}
int native_utf8_chars_offset = Util.GetUtf8(utf8_chars, native_utf8_chars, utf8_chars_byteCount);
native_utf8_chars[native_utf8_chars_offset] = 0;
} }
else { native_utf8_chars = null; } else { native_utf8_chars = null; }
ImGuiNative.ImGuiIO_AddInputCharactersUTF8(NativePtr, native_utf8_chars); ImGuiNative.ImGuiIO_AddInputCharactersUTF8(NativePtr, native_utf8_chars);
if (utf8_chars_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_utf8_chars);
}
} }
public void ClearInputCharacters() public void ClearInputCharacters()
{ {

@ -52,20 +52,29 @@ namespace ImGuiNET
public void InsertChars(int pos, string text) public void InsertChars(int pos, string text)
{ {
byte* native_text; byte* native_text;
int text_byteCount = 0;
if (text != null) if (text != null)
{ {
int text_byteCount = Encoding.UTF8.GetByteCount(text); text_byteCount = Encoding.UTF8.GetByteCount(text);
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1]; if (text_byteCount > Util.StackAllocationSizeLimit)
native_text = native_text_stackBytes;
fixed (char* text_ptr = text)
{ {
int native_text_offset = Encoding.UTF8.GetBytes(text_ptr, text.Length, native_text, text_byteCount); native_text = Util.Allocate(text_byteCount + 1);
native_text[native_text_offset] = 0;
} }
else
{
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1];
native_text = native_text_stackBytes;
}
int native_text_offset = Util.GetUtf8(text, native_text, text_byteCount);
native_text[native_text_offset] = 0;
} }
else { native_text = null; } else { native_text = null; }
byte* native_text_end = null; byte* native_text_end = null;
ImGuiNative.ImGuiInputTextCallbackData_InsertChars(NativePtr, pos, native_text, native_text_end); ImGuiNative.ImGuiInputTextCallbackData_InsertChars(NativePtr, pos, native_text, native_text_end);
if (text_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_text);
}
} }
} }
} }

@ -39,19 +39,28 @@ namespace ImGuiNET
public bool IsDataType(string type) public bool IsDataType(string type)
{ {
byte* native_type; byte* native_type;
int type_byteCount = 0;
if (type != null) if (type != null)
{ {
int type_byteCount = Encoding.UTF8.GetByteCount(type); type_byteCount = Encoding.UTF8.GetByteCount(type);
byte* native_type_stackBytes = stackalloc byte[type_byteCount + 1]; if (type_byteCount > Util.StackAllocationSizeLimit)
native_type = native_type_stackBytes;
fixed (char* type_ptr = type)
{ {
int native_type_offset = Encoding.UTF8.GetBytes(type_ptr, type.Length, native_type, type_byteCount); native_type = Util.Allocate(type_byteCount + 1);
native_type[native_type_offset] = 0;
} }
else
{
byte* native_type_stackBytes = stackalloc byte[type_byteCount + 1];
native_type = native_type_stackBytes;
}
int native_type_offset = Util.GetUtf8(type, native_type, type_byteCount);
native_type[native_type_offset] = 0;
} }
else { native_type = null; } else { native_type = null; }
byte ret = ImGuiNative.ImGuiPayload_IsDataType(NativePtr, native_type); byte ret = ImGuiNative.ImGuiPayload_IsDataType(NativePtr, native_type);
if (type_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_type);
}
return ret != 0; return ret != 0;
} }
public bool IsDelivery() public bool IsDelivery()

@ -21,19 +21,28 @@ namespace ImGuiNET
public void appendf(string fmt) public void appendf(string fmt)
{ {
byte* native_fmt; byte* native_fmt;
int fmt_byteCount = 0;
if (fmt != null) if (fmt != null)
{ {
int fmt_byteCount = Encoding.UTF8.GetByteCount(fmt); fmt_byteCount = Encoding.UTF8.GetByteCount(fmt);
byte* native_fmt_stackBytes = stackalloc byte[fmt_byteCount + 1]; if (fmt_byteCount > Util.StackAllocationSizeLimit)
native_fmt = native_fmt_stackBytes;
fixed (char* fmt_ptr = fmt)
{ {
int native_fmt_offset = Encoding.UTF8.GetBytes(fmt_ptr, fmt.Length, native_fmt, fmt_byteCount); native_fmt = Util.Allocate(fmt_byteCount + 1);
native_fmt[native_fmt_offset] = 0;
} }
else
{
byte* native_fmt_stackBytes = stackalloc byte[fmt_byteCount + 1];
native_fmt = native_fmt_stackBytes;
}
int native_fmt_offset = Util.GetUtf8(fmt, native_fmt, fmt_byteCount);
native_fmt[native_fmt_offset] = 0;
} }
else { native_fmt = null; } else { native_fmt = null; }
ImGuiNative.ImGuiTextBuffer_appendf(NativePtr, native_fmt); ImGuiNative.ImGuiTextBuffer_appendf(NativePtr, native_fmt);
if (fmt_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_fmt);
}
} }
public string begin() public string begin()
{ {

@ -33,53 +33,80 @@ namespace ImGuiNET
public bool Draw() public bool Draw()
{ {
byte* native_label; byte* native_label;
int label_byteCount = Encoding.UTF8.GetByteCount("Filter(inc,-exc)"); int label_byteCount = 0;
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1]; label_byteCount = Encoding.UTF8.GetByteCount("Filter(inc,-exc)");
native_label = native_label_stackBytes; if (label_byteCount > Util.StackAllocationSizeLimit)
fixed (char* label_ptr = "Filter(inc,-exc)")
{ {
int native_label_offset = Encoding.UTF8.GetBytes(label_ptr, "Filter(inc,-exc)".Length, native_label, label_byteCount); native_label = Util.Allocate(label_byteCount + 1);
native_label[native_label_offset] = 0;
} }
else
{
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1];
native_label = native_label_stackBytes;
}
int native_label_offset = Util.GetUtf8("Filter(inc,-exc)", native_label, label_byteCount);
native_label[native_label_offset] = 0;
float width = 0.0f; float width = 0.0f;
byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width); byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width);
if (label_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_label);
}
return ret != 0; return ret != 0;
} }
public bool Draw(string label) public bool Draw(string label)
{ {
byte* native_label; byte* native_label;
int label_byteCount = 0;
if (label != null) if (label != null)
{ {
int label_byteCount = Encoding.UTF8.GetByteCount(label); label_byteCount = Encoding.UTF8.GetByteCount(label);
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1]; if (label_byteCount > Util.StackAllocationSizeLimit)
native_label = native_label_stackBytes;
fixed (char* label_ptr = label)
{ {
int native_label_offset = Encoding.UTF8.GetBytes(label_ptr, label.Length, native_label, label_byteCount); native_label = Util.Allocate(label_byteCount + 1);
native_label[native_label_offset] = 0;
} }
else
{
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1];
native_label = native_label_stackBytes;
}
int native_label_offset = Util.GetUtf8(label, native_label, label_byteCount);
native_label[native_label_offset] = 0;
} }
else { native_label = null; } else { native_label = null; }
float width = 0.0f; float width = 0.0f;
byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width); byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width);
if (label_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_label);
}
return ret != 0; return ret != 0;
} }
public bool Draw(string label, float width) public bool Draw(string label, float width)
{ {
byte* native_label; byte* native_label;
int label_byteCount = 0;
if (label != null) if (label != null)
{ {
int label_byteCount = Encoding.UTF8.GetByteCount(label); label_byteCount = Encoding.UTF8.GetByteCount(label);
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1]; if (label_byteCount > Util.StackAllocationSizeLimit)
native_label = native_label_stackBytes;
fixed (char* label_ptr = label)
{ {
int native_label_offset = Encoding.UTF8.GetBytes(label_ptr, label.Length, native_label, label_byteCount); native_label = Util.Allocate(label_byteCount + 1);
native_label[native_label_offset] = 0;
} }
else
{
byte* native_label_stackBytes = stackalloc byte[label_byteCount + 1];
native_label = native_label_stackBytes;
}
int native_label_offset = Util.GetUtf8(label, native_label, label_byteCount);
native_label[native_label_offset] = 0;
} }
else { native_label = null; } else { native_label = null; }
byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width); byte ret = ImGuiNative.ImGuiTextFilter_Draw(NativePtr, native_label, width);
if (label_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_label);
}
return ret != 0; return ret != 0;
} }
public bool IsActive() public bool IsActive()
@ -90,20 +117,29 @@ namespace ImGuiNET
public bool PassFilter(string text) public bool PassFilter(string text)
{ {
byte* native_text; byte* native_text;
int text_byteCount = 0;
if (text != null) if (text != null)
{ {
int text_byteCount = Encoding.UTF8.GetByteCount(text); text_byteCount = Encoding.UTF8.GetByteCount(text);
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1]; if (text_byteCount > Util.StackAllocationSizeLimit)
native_text = native_text_stackBytes;
fixed (char* text_ptr = text)
{ {
int native_text_offset = Encoding.UTF8.GetBytes(text_ptr, text.Length, native_text, text_byteCount); native_text = Util.Allocate(text_byteCount + 1);
native_text[native_text_offset] = 0;
} }
else
{
byte* native_text_stackBytes = stackalloc byte[text_byteCount + 1];
native_text = native_text_stackBytes;
}
int native_text_offset = Util.GetUtf8(text, native_text, text_byteCount);
native_text[native_text_offset] = 0;
} }
else { native_text = null; } else { native_text = null; }
byte* native_text_end = null; byte* native_text_end = null;
byte ret = ImGuiNative.ImGuiTextFilter_PassFilter(NativePtr, native_text, native_text_end); byte ret = ImGuiNative.ImGuiTextFilter_PassFilter(NativePtr, native_text, native_text_end);
if (text_byteCount > Util.StackAllocationSizeLimit)
{
Util.Free(native_text);
}
return ret != 0; return ret != 0;
} }
} }

@ -1,6 +1,7 @@
using System; using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace ImGuiNET namespace ImGuiNET
@ -42,18 +43,31 @@ namespace ImGuiNET
ImGuiInputTextCallback callback, ImGuiInputTextCallback callback,
IntPtr user_data) IntPtr user_data)
{ {
int utf8LabelByteCount = Encoding.UTF8.GetByteCount(label);
int labelByteCount = Encoding.UTF8.GetByteCount(label); byte* utf8LabelBytes;
byte* labelBytes = stackalloc byte[labelByteCount + 1]; if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
fixed (char* labelPtr = label) {
utf8LabelBytes = Util.Allocate(utf8LabelByteCount + 1);
}
else
{ {
Encoding.UTF8.GetBytes(labelPtr, label.Length, labelBytes, labelByteCount); byte* stackPtr = stackalloc byte[utf8LabelByteCount + 1];
utf8LabelBytes = stackPtr;
} }
Util.GetUtf8(label, utf8LabelBytes, utf8LabelByteCount);
bool ret;
fixed (byte* bufPtr = buf) fixed (byte* bufPtr = buf)
{ {
return ImGuiNative.igInputText(labelBytes, bufPtr, buf_size, flags, callback, user_data.ToPointer()) != 0; ret = ImGuiNative.igInputText(utf8LabelBytes, bufPtr, buf_size, flags, callback, user_data.ToPointer()) != 0;
}
if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{
Util.Free(utf8LabelBytes);
} }
return ret;
} }
public static bool InputText( public static bool InputText(
@ -82,34 +96,61 @@ namespace ImGuiNET
ImGuiInputTextCallback callback, ImGuiInputTextCallback callback,
IntPtr user_data) IntPtr user_data)
{ {
int labelByteCount = Encoding.UTF8.GetByteCount(label); int utf8LabelByteCount = Encoding.UTF8.GetByteCount(label);
byte* labelBytes = stackalloc byte[labelByteCount + 1]; byte* utf8LabelBytes;
fixed (char* labelPtr = label) if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{ {
Encoding.UTF8.GetBytes(labelPtr, label.Length, labelBytes, labelByteCount); utf8LabelBytes = Util.Allocate(utf8LabelByteCount + 1);
} }
else
int originalByteCount = Encoding.UTF8.GetByteCount(input);
int stackBufSize = Math.Max((int)maxLength, originalByteCount);
byte* bufBytes = stackalloc byte[stackBufSize];
fixed (char* u16Ptr = input)
{ {
Encoding.UTF8.GetBytes(u16Ptr, input.Length, bufBytes, stackBufSize); byte* stackPtr = stackalloc byte[utf8LabelByteCount + 1];
utf8LabelBytes = stackPtr;
} }
Util.GetUtf8(label, utf8LabelBytes, utf8LabelByteCount);
byte* originalBufBytes = stackalloc byte[originalByteCount]; int utf8InputByteCount = Encoding.UTF8.GetByteCount(input);
Unsafe.CopyBlock(originalBufBytes, bufBytes, (uint)originalByteCount); int inputBufSize = Math.Max((int)maxLength + 1, utf8InputByteCount + 1);
byte* utf8InputBytes;
byte* originalUtf8InputBytes;
if (inputBufSize > Util.StackAllocationSizeLimit)
{
utf8InputBytes = Util.Allocate(inputBufSize);
originalUtf8InputBytes = Util.Allocate(inputBufSize);
}
else
{
byte* inputStackBytes = stackalloc byte[inputBufSize];
utf8InputBytes = inputStackBytes;
byte* originalInputStackBytes = stackalloc byte[inputBufSize];
originalUtf8InputBytes = originalInputStackBytes;
}
Util.GetUtf8(input, utf8InputBytes, inputBufSize);
uint clearBytesCount = (uint)(inputBufSize - utf8InputByteCount);
Unsafe.InitBlockUnaligned(utf8InputBytes + utf8InputByteCount + 1, 0, clearBytesCount);
Unsafe.CopyBlock(originalUtf8InputBytes, utf8InputBytes, (uint)inputBufSize);
byte result = ImGuiNative.igInputText( byte result = ImGuiNative.igInputText(
labelBytes, utf8LabelBytes,
bufBytes, utf8InputBytes,
(uint)stackBufSize, (uint)inputBufSize,
flags, flags,
callback, callback,
user_data.ToPointer()); user_data.ToPointer());
if (!Util.AreStringsEqual(originalBufBytes, originalByteCount, bufBytes)) if (!Util.AreStringsEqual(originalUtf8InputBytes, inputBufSize, utf8InputBytes))
{
input = Util.StringFromPtr(utf8InputBytes);
}
if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{ {
input = Util.StringFromPtr(bufBytes); Util.Free(utf8LabelBytes);
}
if (inputBufSize > Util.StackAllocationSizeLimit)
{
Util.Free(utf8InputBytes);
Util.Free(originalUtf8InputBytes);
} }
return result != 0; return result != 0;
@ -145,35 +186,62 @@ namespace ImGuiNET
ImGuiInputTextCallback callback, ImGuiInputTextCallback callback,
IntPtr user_data) IntPtr user_data)
{ {
int labelByteCount = Encoding.UTF8.GetByteCount(label); int utf8LabelByteCount = Encoding.UTF8.GetByteCount(label);
byte* labelBytes = stackalloc byte[labelByteCount + 1]; byte* utf8LabelBytes;
fixed (char* labelPtr = label) if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{ {
Encoding.UTF8.GetBytes(labelPtr, label.Length, labelBytes, labelByteCount); utf8LabelBytes = Util.Allocate(utf8LabelByteCount + 1);
} }
else
int originalByteCount = Encoding.UTF8.GetByteCount(input);
int stackBufSize = Math.Max((int)maxLength, originalByteCount);
byte* bufBytes = stackalloc byte[stackBufSize];
fixed (char* u16Ptr = input)
{ {
Encoding.UTF8.GetBytes(u16Ptr, input.Length, bufBytes, stackBufSize); byte* stackPtr = stackalloc byte[utf8LabelByteCount + 1];
utf8LabelBytes = stackPtr;
} }
Util.GetUtf8(label, utf8LabelBytes, utf8LabelByteCount);
byte* originalBufBytes = stackalloc byte[originalByteCount]; int utf8InputByteCount = Encoding.UTF8.GetByteCount(input);
Unsafe.CopyBlock(originalBufBytes, bufBytes, (uint)originalByteCount); int inputBufSize = Math.Max((int)maxLength + 1, utf8InputByteCount + 1);
byte* utf8InputBytes;
byte* originalUtf8InputBytes;
if (inputBufSize > Util.StackAllocationSizeLimit)
{
utf8InputBytes = Util.Allocate(inputBufSize);
originalUtf8InputBytes = Util.Allocate(inputBufSize);
}
else
{
byte* inputStackBytes = stackalloc byte[inputBufSize];
utf8InputBytes = inputStackBytes;
byte* originalInputStackBytes = stackalloc byte[inputBufSize];
originalUtf8InputBytes = originalInputStackBytes;
}
Util.GetUtf8(input, utf8InputBytes, inputBufSize);
uint clearBytesCount = (uint)(inputBufSize - utf8InputByteCount);
Unsafe.InitBlockUnaligned(utf8InputBytes + utf8InputByteCount + 1, 0, clearBytesCount);
Unsafe.CopyBlock(originalUtf8InputBytes, utf8InputBytes, (uint)inputBufSize);
byte result = ImGuiNative.igInputTextMultiline( byte result = ImGuiNative.igInputTextMultiline(
labelBytes, utf8LabelBytes,
bufBytes, utf8InputBytes,
(uint)stackBufSize, (uint)inputBufSize,
size, size,
flags, flags,
callback, callback,
user_data.ToPointer()); user_data.ToPointer());
if (!Util.AreStringsEqual(originalBufBytes, originalByteCount, bufBytes)) if (!Util.AreStringsEqual(originalUtf8InputBytes, inputBufSize, utf8InputBytes))
{
input = Util.StringFromPtr(utf8InputBytes);
}
if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{
Util.Free(utf8LabelBytes);
}
if (inputBufSize > Util.StackAllocationSizeLimit)
{ {
input = Util.StringFromPtr(bufBytes); Util.Free(utf8InputBytes);
Util.Free(originalUtf8InputBytes);
} }
return result != 0; return result != 0;
@ -214,28 +282,52 @@ namespace ImGuiNET
ImGuiInputTextCallback callback, ImGuiInputTextCallback callback,
IntPtr user_data) IntPtr user_data)
{ {
int utf8LabelByteCount = Encoding.UTF8.GetByteCount(label);
byte* utf8LabelBytes;
if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
{
utf8LabelBytes = Util.Allocate(utf8LabelByteCount + 1);
}
else
{
byte* stackPtr = stackalloc byte[utf8LabelByteCount + 1];
utf8LabelBytes = stackPtr;
}
Util.GetUtf8(label, utf8LabelBytes, utf8LabelByteCount);
bool ret = ImGuiNative.igInputText(utf8LabelBytes, (byte*)buf.ToPointer(), buf_size, flags, callback, user_data.ToPointer()) != 0;
int labelByteCount = Encoding.UTF8.GetByteCount(label); if (utf8LabelByteCount > Util.StackAllocationSizeLimit)
byte* labelBytes = stackalloc byte[labelByteCount + 1];
fixed (char* labelPtr = label)
{ {
Encoding.UTF8.GetBytes(labelPtr, label.Length, labelBytes, labelByteCount); Util.Free(utf8LabelBytes);
} }
return ImGuiNative.igInputText(labelBytes, (byte*)buf.ToPointer(), buf_size, flags, callback, user_data.ToPointer()) != 0; return ret;
} }
public static bool Begin(string name, ImGuiWindowFlags flags) public static bool Begin(string name, ImGuiWindowFlags flags)
{ {
int name_byteCount = Encoding.UTF8.GetByteCount(name); int utf8NameByteCount = Encoding.UTF8.GetByteCount(name);
byte* native_name = stackalloc byte[name_byteCount + 1]; byte* utf8NameBytes;
fixed (char* name_ptr = name) if (utf8NameByteCount > Util.StackAllocationSizeLimit)
{
utf8NameBytes = Util.Allocate(utf8NameByteCount + 1);
}
else
{ {
int native_name_offset = Encoding.UTF8.GetBytes(name_ptr, name.Length, native_name, name_byteCount); byte* stackPtr = stackalloc byte[utf8NameByteCount + 1];
native_name[native_name_offset] = 0; utf8NameBytes = stackPtr;
} }
Util.GetUtf8(name, utf8NameBytes, utf8NameByteCount);
byte* p_open = null; byte* p_open = null;
byte ret = ImGuiNative.igBegin(native_name, p_open, flags); byte ret = ImGuiNative.igBegin(utf8NameBytes, p_open, flags);
if (utf8NameByteCount > Util.StackAllocationSizeLimit)
{
Util.Free(utf8NameBytes);
}
return ret != 0; return ret != 0;
} }

@ -1,10 +1,14 @@
using System.Text; using System;
using System.Runtime.InteropServices;
using System.Text;
namespace ImGuiNET namespace ImGuiNET
{ {
internal static class Util internal static unsafe class Util
{ {
public static unsafe string StringFromPtr(byte* ptr) internal const int StackAllocationSizeLimit = 2048;
public static string StringFromPtr(byte* ptr)
{ {
int characters = 0; int characters = 0;
while (ptr[characters] != 0) while (ptr[characters] != 0)
@ -15,7 +19,7 @@ namespace ImGuiNET
return Encoding.UTF8.GetString(ptr, characters); return Encoding.UTF8.GetString(ptr, characters);
} }
internal static unsafe bool AreStringsEqual(byte* a, int aLength, byte* b) internal static bool AreStringsEqual(byte* a, int aLength, byte* b)
{ {
for (int i = 0; i < aLength; i++) for (int i = 0; i < aLength; i++)
{ {
@ -26,5 +30,15 @@ namespace ImGuiNET
return true; return true;
} }
internal static byte* Allocate(int byteCount) => (byte*)Marshal.AllocHGlobal(byteCount);
internal static void Free(byte* ptr) => Marshal.FreeHGlobal((IntPtr)ptr);
internal static int GetUtf8(string s, byte* utf8Bytes, int utf8ByteCount)
{
fixed (char* utf16Ptr = s)
{
return Encoding.UTF8.GetBytes(utf16Ptr, s.Length, utf8Bytes, utf8ByteCount);
}
}
} }
} }

Loading…
Cancel
Save