mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Merge remote-tracking branch 'upstream/master' into Yuvan/CustomBuildProperties
This commit is contained in:
commit
524ebaa914
49 changed files with 1372 additions and 146 deletions
40
BeefLibs/Beefy2D/src/geom/Oval.bf
Normal file
40
BeefLibs/Beefy2D/src/geom/Oval.bf
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
namespace Beefy.geom;
|
||||||
|
|
||||||
|
struct Oval
|
||||||
|
{
|
||||||
|
public float mX;
|
||||||
|
public float mY;
|
||||||
|
public float mRadiusX;
|
||||||
|
public float mRadiusY;
|
||||||
|
|
||||||
|
public this(float x, float y, float radiusX, float radiusY)
|
||||||
|
{
|
||||||
|
mX = x;
|
||||||
|
mY = y;
|
||||||
|
mRadiusX = radiusX;
|
||||||
|
mRadiusY = radiusY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(Rect rect)
|
||||||
|
{
|
||||||
|
mX = rect.CenterX;
|
||||||
|
mY = rect.CenterY;
|
||||||
|
mRadiusX = rect.mWidth / 2;
|
||||||
|
mRadiusY = rect.mHeight / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(float x, float y)
|
||||||
|
{
|
||||||
|
float dx = (x - mX) / mRadiusX;
|
||||||
|
float dy = (y - mY) / mRadiusY;
|
||||||
|
return dx*dx + dy*dy <= 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inflate(float x, float y) mut
|
||||||
|
{
|
||||||
|
mRadiusX += x;
|
||||||
|
mRadiusY += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Vector2 vec) => Contains(vec.mX, vec.mY);
|
||||||
|
}
|
|
@ -212,6 +212,12 @@ namespace Beefy.geom
|
||||||
(y >= mY) && (y < mY + mHeight));
|
(y >= mY) && (y < mY + mHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsInclusive(T x, T y)
|
||||||
|
{
|
||||||
|
return ((x >= mX) && (x <= mX + mWidth) &&
|
||||||
|
(y >= mY) && (y <= mY + mHeight));
|
||||||
|
}
|
||||||
|
|
||||||
public bool Contains(Point<T> pt)
|
public bool Contains(Point<T> pt)
|
||||||
{
|
{
|
||||||
return Contains(pt.x, pt.y);
|
return Contains(pt.x, pt.y);
|
||||||
|
@ -219,7 +225,7 @@ namespace Beefy.geom
|
||||||
|
|
||||||
public bool Contains(Self rect)
|
public bool Contains(Self rect)
|
||||||
{
|
{
|
||||||
return Contains(rect.mX, rect.mY) && Contains(rect.mX + rect.mWidth, rect.mY + rect.mHeight);
|
return Contains(rect.mX, rect.mY) && ContainsInclusive(rect.mX + rect.mWidth, rect.mY + rect.mHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Offset(T x, T y) mut
|
public void Offset(T x, T y) mut
|
||||||
|
|
|
@ -1035,6 +1035,27 @@ namespace Beefy.gfx
|
||||||
{
|
{
|
||||||
Gfx_CopyDrawVertex((.)idx, (.)srcIdx);
|
Gfx_CopyDrawVertex((.)idx, (.)srcIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OutlineOval(float x, float y, float radiusX, float radiusY)
|
||||||
|
{
|
||||||
|
int numSections = 12 + (.)((radiusX + radiusY) * 0.15f);
|
||||||
|
for (int section < numSections)
|
||||||
|
{
|
||||||
|
float ang0 = (section * Math.PI_f * 2) / numSections;
|
||||||
|
float ang1 = ((section + 1) * Math.PI_f * 2) / numSections;
|
||||||
|
|
||||||
|
float x0 = x + Math.Cos(ang0) * radiusX;
|
||||||
|
float y0 = y + Math.Sin(ang0) * radiusY;
|
||||||
|
float x1 = x + Math.Cos(ang1) * radiusX;
|
||||||
|
float y1 = y + Math.Sin(ang1) * radiusY;
|
||||||
|
DrawLine(x0, y0, x1, y1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OutlineCircle(float x, float y, float radius)
|
||||||
|
{
|
||||||
|
OutlineOval(x, y, radius, radius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public class Graphics : GraphicsBase
|
public class Graphics : GraphicsBase
|
||||||
|
|
|
@ -103,6 +103,7 @@ namespace Beefy.gfx
|
||||||
scope AutoBeefPerf("Image.LoadFromFile");
|
scope AutoBeefPerf("Image.LoadFromFile");
|
||||||
|
|
||||||
var useFileName = scope String()..Append(fileName);
|
var useFileName = scope String()..Append(fileName);
|
||||||
|
useFileName.Replace('\\', '/');
|
||||||
FilePackManager.TryMakeMemoryString(useFileName);
|
FilePackManager.TryMakeMemoryString(useFileName);
|
||||||
void* aNativeTextureSegment = Gfx_LoadTexture(useFileName, (int32)flags);
|
void* aNativeTextureSegment = Gfx_LoadTexture(useFileName, (int32)flags);
|
||||||
if (aNativeTextureSegment == null)
|
if (aNativeTextureSegment == null)
|
||||||
|
|
|
@ -125,7 +125,11 @@ namespace Beefy.widgets
|
||||||
case .LWin,
|
case .LWin,
|
||||||
.RWin,
|
.RWin,
|
||||||
.Alt,
|
.Alt,
|
||||||
|
.LAlt,
|
||||||
|
.RAlt,
|
||||||
.Control,
|
.Control,
|
||||||
|
.LCtrl,
|
||||||
|
.RCtrl,
|
||||||
.Command,
|
.Command,
|
||||||
.Shift:
|
.Shift:
|
||||||
return true;
|
return true;
|
||||||
|
@ -144,7 +148,7 @@ namespace Beefy.widgets
|
||||||
return (KeyCode)c;
|
return (KeyCode)c;
|
||||||
if ((c >= '0') && (c <= '9'))
|
if ((c >= '0') && (c <= '9'))
|
||||||
return (KeyCode)c;
|
return (KeyCode)c;
|
||||||
if ((c >= 'a') && (c <= 'a'))
|
if ((c >= 'a') && (c <= 'z'))
|
||||||
return (KeyCode)(c.ToUpper);
|
return (KeyCode)(c.ToUpper);
|
||||||
if (c == '[')
|
if (c == '[')
|
||||||
return (KeyCode)LBracket;
|
return (KeyCode)LBracket;
|
||||||
|
@ -160,6 +164,14 @@ namespace Beefy.widgets
|
||||||
return (KeyCode)Period;
|
return (KeyCode)Period;
|
||||||
if (c == ',')
|
if (c == ',')
|
||||||
return (KeyCode)Comma;
|
return (KeyCode)Comma;
|
||||||
|
if (c == ' ')
|
||||||
|
return (KeyCode)Space;
|
||||||
|
if (c == '-')
|
||||||
|
return (KeyCode)Minus;
|
||||||
|
if (c == '+')
|
||||||
|
return (KeyCode)Add;
|
||||||
|
if (c == '=')
|
||||||
|
return (KeyCode)Equals;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str.StartsWith("0x"))
|
if (str.StartsWith("0x"))
|
||||||
|
|
|
@ -570,6 +570,12 @@ namespace System
|
||||||
return &mFirstElement;
|
return &mFirstElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[,] arrayTo)
|
||||||
|
{
|
||||||
|
Debug.Assert(arrayTo.mLength >= mLength);
|
||||||
|
Internal.MemCpy(&arrayTo.GetRef(0), &GetRef(0), strideof(T) * mLength, alignof(T));
|
||||||
|
}
|
||||||
|
|
||||||
public Span<T>.Enumerator GetEnumerator()
|
public Span<T>.Enumerator GetEnumerator()
|
||||||
{
|
{
|
||||||
return .(.(&mFirstElement, mLength));
|
return .(.(&mFirstElement, mLength));
|
||||||
|
|
|
@ -85,10 +85,19 @@ namespace System
|
||||||
|
|
||||||
static void SetupOutStringEx()
|
static void SetupOutStringEx()
|
||||||
{
|
{
|
||||||
OutString = => OutString_Ex;
|
sOutString = => OutString_Ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function void(StringView str) OutString = => OutString_Simple;
|
static function void(StringView str) sOutString;
|
||||||
|
static function void(StringView str) OutString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (sOutString == null)
|
||||||
|
sOutString = => OutString_Simple;
|
||||||
|
return sOutString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !BF_RUNTIME_DISABLE && !BF_PLATFORM_WASM
|
#if !BF_RUNTIME_DISABLE && !BF_PLATFORM_WASM
|
||||||
private static extern void PutChars(char8* c, int32 len);
|
private static extern void PutChars(char8* c, int32 len);
|
||||||
|
|
|
@ -99,8 +99,11 @@ namespace System
|
||||||
[CallingConvention(.Cdecl)]
|
[CallingConvention(.Cdecl)]
|
||||||
public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage);
|
public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage);
|
||||||
#else
|
#else
|
||||||
|
[LinkName("__GC_Report")]
|
||||||
public static void Report() {}
|
public static void Report() {}
|
||||||
|
[LinkName("__GC_Shutdown")]
|
||||||
public static void Shutdown() {}
|
public static void Shutdown() {}
|
||||||
|
[LinkName("__GC_SetMaxRawDeferredObjectFreePercentage")]
|
||||||
public static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage) {}
|
public static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -138,17 +141,27 @@ namespace System
|
||||||
[CallingConvention(.Cdecl)]
|
[CallingConvention(.Cdecl)]
|
||||||
public extern static void ExcludeThreadId(int thereadId);
|
public extern static void ExcludeThreadId(int thereadId);
|
||||||
#else
|
#else
|
||||||
|
[LinkName("__GC_Disable")]
|
||||||
public static void Disable() {}
|
public static void Disable() {}
|
||||||
|
[LinkName("__GC_Collect")]
|
||||||
public static void Collect(bool async = true) {}
|
public static void Collect(bool async = true) {}
|
||||||
|
[LinkName("__GC_MarkAllStaticMembers")]
|
||||||
private static void MarkAllStaticMembers() {}
|
private static void MarkAllStaticMembers() {}
|
||||||
|
[LinkName("__GC_DebugDumpLeaks")]
|
||||||
public static void DebugDumpLeaks() {}
|
public static void DebugDumpLeaks() {}
|
||||||
[SkipCall]
|
[SkipCall, LinkName("__GC_Mark1")]
|
||||||
public static void Mark(Object obj) {}
|
public static void Mark(Object obj) {}
|
||||||
|
[LinkName("__GC_Mark2")]
|
||||||
public static void Mark(void* ptr, int size) {}
|
public static void Mark(void* ptr, int size) {}
|
||||||
|
[LinkName("__GC_SetAutoCollectPeriod")]
|
||||||
public static void SetAutoCollectPeriod(int periodMS) {}
|
public static void SetAutoCollectPeriod(int periodMS) {}
|
||||||
|
[LinkName("__GC_SetCollectFreeThreshold")]
|
||||||
public static void SetCollectFreeThreshold(int freeBytes) {}
|
public static void SetCollectFreeThreshold(int freeBytes) {}
|
||||||
|
[LinkName("__GC_SetMaxPausePercentage")]
|
||||||
public static void SetMaxPausePercentage(int maxPausePercentage) {}
|
public static void SetMaxPausePercentage(int maxPausePercentage) {}
|
||||||
|
[LinkName("__GC_AddPendingThread")]
|
||||||
static void AddPendingThread(void* internalThreadInfo) {}
|
static void AddPendingThread(void* internalThreadInfo) {}
|
||||||
|
[LinkName("__GC_ExcludeThreadId")]
|
||||||
public static void ExcludeThreadId(int thereadId) {}
|
public static void ExcludeThreadId(int thereadId) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -623,6 +623,9 @@ abstract class CommonDialog
|
||||||
|
|
||||||
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
||||||
{
|
{
|
||||||
|
if (!Linux.IsSystemdAvailable)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
TryC!(Linux.SdBusOpenUser(&mBus)); // Maybe keep the bus open while the program is running ?
|
TryC!(Linux.SdBusOpenUser(&mBus)); // Maybe keep the bus open while the program is running ?
|
||||||
|
|
||||||
Linux.DBusMsg* call = ?;
|
Linux.DBusMsg* call = ?;
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RefCounted<T> : IRefCounted where T : class, delete
|
class RefCounted<T> : IRefCounted where T : delete
|
||||||
{
|
{
|
||||||
public T mVal;
|
public T mVal;
|
||||||
public int mRefCount = 1;
|
public int mRefCount = 1;
|
||||||
|
@ -178,7 +178,7 @@ namespace System
|
||||||
public virtual T Detach()
|
public virtual T Detach()
|
||||||
{
|
{
|
||||||
var val = mVal;
|
var val = mVal;
|
||||||
mVal = null;
|
mVal = default;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,33 @@ class Linux
|
||||||
|
|
||||||
public typealias DBusMsgHandler = function int32(DBusMsg *m, void *userdata, DBusErr *ret_error);
|
public typealias DBusMsgHandler = function int32(DBusMsg *m, void *userdata, DBusErr *ret_error);
|
||||||
|
|
||||||
|
public static bool IsSystemdAvailable { get; private set; } = true;
|
||||||
|
|
||||||
|
[AlwaysInclude, StaticInitPriority(100)]
|
||||||
|
static class AllowFail
|
||||||
|
{
|
||||||
|
public static this()
|
||||||
|
{
|
||||||
|
Runtime.AddErrorHandler(new => Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Runtime.ErrorHandlerResult Handle(Runtime.ErrorStage errorStage, Runtime.Error error)
|
||||||
|
{
|
||||||
|
if (errorStage == .PreFail)
|
||||||
|
{
|
||||||
|
if (var loadLibaryError = error as Runtime.LoadSharedLibraryError)
|
||||||
|
{
|
||||||
|
if (loadLibaryError.mPath == "libsystemd.so")
|
||||||
|
{
|
||||||
|
IsSystemdAvailable = false;
|
||||||
|
return .Ignore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .ContinueFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Import("libsystemd.so"), LinkName("sd_bus_open_user")]
|
[Import("libsystemd.so"), LinkName("sd_bus_open_user")]
|
||||||
public static extern c_int SdBusOpenUser(DBus **ret);
|
public static extern c_int SdBusOpenUser(DBus **ret);
|
||||||
[Import("libsystemd.so"), LinkName("sd_bus_open_system")]
|
[Import("libsystemd.so"), LinkName("sd_bus_open_system")]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Interop;
|
||||||
|
|
||||||
namespace System.Net
|
namespace System.Net
|
||||||
{
|
{
|
||||||
|
@ -134,6 +135,26 @@ namespace System.Net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CRepr, Union]
|
||||||
|
public struct IPv6Address
|
||||||
|
{
|
||||||
|
public uint8[16] byte;
|
||||||
|
public uint16[8] word;
|
||||||
|
|
||||||
|
public this(params uint16[8] addr)
|
||||||
|
{
|
||||||
|
for(let i < 8)
|
||||||
|
{
|
||||||
|
this.word[i] = (.)htons((int16)addr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(params uint8[16] addr)
|
||||||
|
{
|
||||||
|
this.byte = addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[CRepr]
|
[CRepr]
|
||||||
public struct SockAddr
|
public struct SockAddr
|
||||||
{
|
{
|
||||||
|
@ -149,6 +170,16 @@ namespace System.Net
|
||||||
public char8[8] sin_zero;
|
public char8[8] sin_zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
public struct SockAddr_in6 : SockAddr
|
||||||
|
{
|
||||||
|
public int16 sin6_family;
|
||||||
|
public uint16 sin6_port;
|
||||||
|
public uint32 sin6_flowinfo;
|
||||||
|
public IPv6Address sin6_addr;
|
||||||
|
public uint32 sin6_scope_id;
|
||||||
|
}
|
||||||
|
|
||||||
[CRepr]
|
[CRepr]
|
||||||
public struct HostEnt
|
public struct HostEnt
|
||||||
{
|
{
|
||||||
|
@ -159,13 +190,33 @@ namespace System.Net
|
||||||
public char8** h_addr_list; /* list of addresses */
|
public char8** h_addr_list; /* list of addresses */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
public struct AddrInfo
|
||||||
|
{
|
||||||
|
public int32 ai_flags;
|
||||||
|
public int32 ai_family;
|
||||||
|
public int32 ai_socktype;
|
||||||
|
public int32 ai_protocol;
|
||||||
|
public c_size ai_addrlen;
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
public char8* ai_canonname;
|
||||||
|
public SockAddr* ai_addr;
|
||||||
|
#else
|
||||||
|
public SockAddr* ai_addr;
|
||||||
|
public char8* ai_canonname;
|
||||||
|
#endif
|
||||||
|
public SockAddr* ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
public const HSocket INVALID_SOCKET = (HSocket)-1;
|
public const HSocket INVALID_SOCKET = (HSocket)-1;
|
||||||
public const int32 SOCKET_ERROR = -1;
|
public const int32 SOCKET_ERROR = -1;
|
||||||
public const int AF_INET = 2;
|
public const int AF_INET = 2;
|
||||||
|
public const int AF_INET6 = 23;
|
||||||
public const int SOCK_STREAM = 1;
|
public const int SOCK_STREAM = 1;
|
||||||
public const int SOCK_DGRAM = 2;
|
public const int SOCK_DGRAM = 2;
|
||||||
public const int IPPROTO_TCP = 6;
|
public const int IPPROTO_TCP = 6;
|
||||||
public const int IPPROTO_UDP = 17;
|
public const int IPPROTO_UDP = 17;
|
||||||
|
public const int IPPROTO_IPV6 = 41;
|
||||||
|
|
||||||
public const int TCP_NODELAY = 1;
|
public const int TCP_NODELAY = 1;
|
||||||
public const int TCP_MAXSEG = 2;
|
public const int TCP_MAXSEG = 2;
|
||||||
|
@ -176,12 +227,16 @@ namespace System.Net
|
||||||
public const int SOL_SOCKET = 0xffff;
|
public const int SOL_SOCKET = 0xffff;
|
||||||
public const int SO_REUSEADDR = 0x0004;
|
public const int SO_REUSEADDR = 0x0004;
|
||||||
public const int SO_BROADCAST = 0x0020;
|
public const int SO_BROADCAST = 0x0020;
|
||||||
|
public const int IPV6_V6ONLY = 27;
|
||||||
#else
|
#else
|
||||||
public const int SOL_SOCKET = 1;
|
public const int SOL_SOCKET = 1;
|
||||||
public const int SO_REUSEADDR = 2;
|
public const int SO_REUSEADDR = 2;
|
||||||
public const int SO_BROADCAST = 6;
|
public const int SO_BROADCAST = 6;
|
||||||
|
public const int IPV6_V6ONLY = 26;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public const IPv4Address INADDR_ANY = default;
|
public const IPv4Address INADDR_ANY = default;
|
||||||
|
public const IPv6Address IN6ADDR_ANY = default;
|
||||||
|
|
||||||
#if BF_PLATFORM_WINDOWS
|
#if BF_PLATFORM_WINDOWS
|
||||||
const int FIONBIO = (int)0x8004667e;
|
const int FIONBIO = (int)0x8004667e;
|
||||||
|
@ -252,6 +307,9 @@ namespace System.Net
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
static extern HostEnt* gethostbyname(char8* name);
|
static extern HostEnt* gethostbyname(char8* name);
|
||||||
|
|
||||||
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
|
static extern int32 getaddrinfo(char8* pNodeName, char8* pServiceName, AddrInfo* pHints, AddrInfo** ppResult);
|
||||||
|
|
||||||
[CLink, CallingConvention(.Stdcall)]
|
[CLink, CallingConvention(.Stdcall)]
|
||||||
static extern HSocket socket(int32 af, int32 type, int32 protocol);
|
static extern HSocket socket(int32 af, int32 type, int32 protocol);
|
||||||
|
|
||||||
|
@ -395,8 +453,49 @@ namespace System.Net
|
||||||
int32 size = sizeof(SockAddr_in);
|
int32 size = sizeof(SockAddr_in);
|
||||||
if (bind(mHandle, &service, size) == SOCKET_ERROR)
|
if (bind(mHandle, &service, size) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
int err = WSAGetLastError();
|
Close();
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(mHandle, backlog) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
int err = GetLastError();
|
||||||
|
Close();
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<void> Listen(IPv6Address address, int32 port, int32 backlog = 5, bool v6Only = false)
|
||||||
|
{
|
||||||
|
Debug.Assert(mHandle == INVALID_SOCKET);
|
||||||
|
|
||||||
|
mHandle = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
|
||||||
|
if (mHandle == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
int32 err = GetLastError();
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ipv6Opt = v6Only ? 1 : 0;
|
||||||
|
setsockopt(mHandle, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6Opt, 4);
|
||||||
|
|
||||||
|
RehupSettings();
|
||||||
|
|
||||||
|
SockAddr_in6 service;
|
||||||
|
service.sin6_family = AF_INET6;
|
||||||
|
service.sin6_addr = address;
|
||||||
|
service.sin6_port = (uint16)htons((int16)port);
|
||||||
|
|
||||||
|
int32 size = sizeof(SockAddr_in6);
|
||||||
|
if (bind(mHandle, &service, size) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
int err = GetLastError();
|
||||||
Close();
|
Close();
|
||||||
return .Err;
|
return .Err;
|
||||||
}
|
}
|
||||||
|
@ -443,13 +542,47 @@ namespace System.Net
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<void> Connect(StringView addr, int32 port, out SockAddr* sockAddr, out int addrFamily)
|
||||||
|
{
|
||||||
|
sockAddr = null;
|
||||||
|
addrFamily = default;
|
||||||
|
|
||||||
|
AddrInfo hints = default;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
AddrInfo* addrInfo = null;
|
||||||
|
if (getaddrinfo(addr.Ptr, null, &hints, &addrInfo) < 0)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
sockAddr = addrInfo.ai_addr;
|
||||||
|
addrFamily = addrInfo.ai_family;
|
||||||
|
|
||||||
|
mHandle = socket(addrInfo.ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (mHandle == INVALID_SOCKET)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
if (connect(mHandle, sockAddr, (.)addrInfo.ai_addrlen) == SOCKET_ERROR)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
if (mHandle == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
int32 err = GetLastError();
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsConnected = true;
|
||||||
|
RehupSettings();
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
public Result<void> Connect(StringView addr, int32 port) => Connect(addr, port, ?);
|
public Result<void> Connect(StringView addr, int32 port) => Connect(addr, port, ?);
|
||||||
|
|
||||||
public Result<void> AcceptFrom(Socket listenSocket, out SockAddr_in clientAddr)
|
public Result<void> AcceptFrom(Socket listenSocket, SockAddr* from, int32* fromLen)
|
||||||
{
|
{
|
||||||
clientAddr = default;
|
mHandle = accept(listenSocket.mHandle, from, fromLen);
|
||||||
int32 clientAddrLen = sizeof(SockAddr_in);
|
|
||||||
mHandle = accept(listenSocket.mHandle, &clientAddr, &clientAddrLen);
|
|
||||||
if (mHandle == INVALID_SOCKET)
|
if (mHandle == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
#unwarn
|
#unwarn
|
||||||
|
@ -462,7 +595,14 @@ namespace System.Net
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<void> AcceptFrom(Socket listenSocket) => AcceptFrom(listenSocket, ?);
|
public Result<void> AcceptFrom(Socket listenSocket, out SockAddr_in clientAddr)
|
||||||
|
{
|
||||||
|
clientAddr = default;
|
||||||
|
int32 clientAddrLen = sizeof(SockAddr_in);
|
||||||
|
return AcceptFrom(listenSocket, &clientAddr, &clientAddrLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<void> AcceptFrom(Socket listenSocket) => AcceptFrom(listenSocket, null, null);
|
||||||
|
|
||||||
public static int32 Select(FDSet* readFDS, FDSet* writeFDS, FDSet* exceptFDS, int waitTimeMS)
|
public static int32 Select(FDSet* readFDS, FDSet* writeFDS, FDSet* exceptFDS, int waitTimeMS)
|
||||||
{
|
{
|
||||||
|
@ -597,6 +737,8 @@ namespace System.Net
|
||||||
|
|
||||||
#unwarn
|
#unwarn
|
||||||
public Result<int> SendTo(void* ptr, int size, SockAddr_in to) => SendTo(ptr, size, &to, sizeof(SockAddr_in));
|
public Result<int> SendTo(void* ptr, int size, SockAddr_in to) => SendTo(ptr, size, &to, sizeof(SockAddr_in));
|
||||||
|
#unwarn
|
||||||
|
public Result<int> SendTo(void* ptr, int size, SockAddr_in6 to) => SendTo(ptr, size, &to, sizeof(SockAddr_in6));
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
|
@ -632,5 +774,32 @@ namespace System.Net
|
||||||
status = bind(mHandle, &bindAddr, sizeof(SockAddr_in));
|
status = bind(mHandle, &bindAddr, sizeof(SockAddr_in));
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<void> OpenUDPIPv6(int32 port = -1, bool v6Only = false)
|
||||||
|
{
|
||||||
|
SockAddr_in6 bindAddr = default;
|
||||||
|
|
||||||
|
mHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (mHandle == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
RehupSettings();
|
||||||
|
|
||||||
|
int32 yes = 1;
|
||||||
|
//setsockopt(mHandle, SOL_SOCKET, SO_REUSEADDR, &yes, 4);
|
||||||
|
int32 status = setsockopt(mHandle, SOL_SOCKET, SO_BROADCAST, &yes, 4);
|
||||||
|
|
||||||
|
int32 ipv6Opt = v6Only ? 1 : 0;
|
||||||
|
setsockopt(mHandle, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6Opt, 4);
|
||||||
|
|
||||||
|
bindAddr.sin6_addr = IN6ADDR_ANY;
|
||||||
|
bindAddr.sin6_port = (.)htons((int16)port);
|
||||||
|
bindAddr.sin6_family = AF_INET6;
|
||||||
|
|
||||||
|
status = bind(mHandle, &bindAddr, sizeof(SockAddr_in6));
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace System
|
||||||
public bool AVX, AVX2, AVX512;
|
public bool AVX, AVX2, AVX512;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StaticInitPriority(201)]
|
|
||||||
static class Runtime
|
static class Runtime
|
||||||
{
|
{
|
||||||
const int32 cVersion = 10;
|
const int32 cVersion = 10;
|
||||||
|
@ -284,7 +283,7 @@ namespace System
|
||||||
mDebugMessageData_SetupProfilerCmd = => DebugMessageData_SetupProfilerCmd;
|
mDebugMessageData_SetupProfilerCmd = => DebugMessageData_SetupProfilerCmd;
|
||||||
mDebugMessageData_Fatal = => DebugMessageData_Fatal;
|
mDebugMessageData_Fatal = => DebugMessageData_Fatal;
|
||||||
mDebugMessageData_Clear = => DebugMessageData_Clear;
|
mDebugMessageData_Clear = => DebugMessageData_Clear;
|
||||||
mCheckErrorHandler = => CheckErrorHandler;
|
mCheckErrorHandler = => CheckErrorHandler_Thunk;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -389,13 +388,23 @@ namespace System
|
||||||
public static bool sInsideErrorHandler;
|
public static bool sInsideErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[AlwaysInclude, StaticInitPriority(201)]
|
||||||
|
static struct RuntimeInit
|
||||||
|
{
|
||||||
|
public static this()
|
||||||
|
{
|
||||||
|
Runtime.Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static RtFlags sExtraFlags;
|
static RtFlags sExtraFlags;
|
||||||
static bool sQueriedFeatures = false;
|
static bool sQueriedFeatures = false;
|
||||||
static RuntimeFeatures sFeatures;
|
static RuntimeFeatures sFeatures;
|
||||||
|
|
||||||
static function void() sThreadInit;
|
static function void() sThreadInit;
|
||||||
|
|
||||||
public static this()
|
static void Init()
|
||||||
{
|
{
|
||||||
#if !BF_RUNTIME_DISABLE
|
#if !BF_RUNTIME_DISABLE
|
||||||
BfRtCallbacks.sCallbacks.Init();
|
BfRtCallbacks.sCallbacks.Init();
|
||||||
|
@ -422,6 +431,11 @@ namespace System
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static this()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[NoReturn]
|
[NoReturn]
|
||||||
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
|
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
|
||||||
{
|
{
|
||||||
|
@ -497,6 +511,13 @@ namespace System
|
||||||
public static function int32(char8* kind, char8* arg1, char8* arg2, int arg3) CheckErrorHandler;
|
public static function int32(char8* kind, char8* arg1, char8* arg2, int arg3) CheckErrorHandler;
|
||||||
public static function void*(char8* filePath) LibraryLoadCallback;
|
public static function void*(char8* filePath) LibraryLoadCallback;
|
||||||
|
|
||||||
|
public static int32 CheckErrorHandler_Thunk(char8* kind, char8* arg1, char8* arg2, int arg3)
|
||||||
|
{
|
||||||
|
if (CheckErrorHandler != null)
|
||||||
|
return CheckErrorHandler(kind, arg1, arg2, arg3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ErrorHandlerResult CheckAssertError_Impl(AssertError.Kind kind, String error, String filePath, int lineNum)
|
static ErrorHandlerResult CheckAssertError_Impl(AssertError.Kind kind, String error, String filePath, int lineNum)
|
||||||
{
|
{
|
||||||
return CheckErrorHandlers(scope AssertError(kind, error, filePath, lineNum));
|
return CheckErrorHandlers(scope AssertError(kind, error, filePath, lineNum));
|
||||||
|
|
|
@ -972,6 +972,9 @@ namespace System
|
||||||
|
|
||||||
public void Append(char8* appendPtr, int length)
|
public void Append(char8* appendPtr, int length)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
if (length <= 0)
|
||||||
|
return;
|
||||||
int newCurrentIndex = mLength + length;
|
int newCurrentIndex = mLength + length;
|
||||||
char8* ptr;
|
char8* ptr;
|
||||||
if (newCurrentIndex > AllocSize)
|
if (newCurrentIndex > AllocSize)
|
||||||
|
@ -996,6 +999,9 @@ namespace System
|
||||||
|
|
||||||
public void Append(char8[] arr, int idx, int length)
|
public void Append(char8[] arr, int idx, int length)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(length >= 0);
|
||||||
|
if (length <= 0)
|
||||||
|
return;
|
||||||
int newCurrentIndex = mLength + length;
|
int newCurrentIndex = mLength + length;
|
||||||
char8* ptr;
|
char8* ptr;
|
||||||
if (newCurrentIndex > AllocSize)
|
if (newCurrentIndex > AllocSize)
|
||||||
|
|
|
@ -107,6 +107,7 @@ namespace System
|
||||||
public int32 Height => bottom - top;
|
public int32 Height => bottom - top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
public struct Point : this(int32 x, int32 y)
|
public struct Point : this(int32 x, int32 y)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1715,6 +1716,9 @@ namespace System
|
||||||
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
public static extern HWnd SetForegroundWindow(HWnd wnd);
|
public static extern HWnd SetForegroundWindow(HWnd wnd);
|
||||||
|
|
||||||
|
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
|
public static extern HWnd ShowWindow(HWnd wnd, int32 cmdShow);
|
||||||
|
|
||||||
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
public static extern HWnd GetForegroundWindow();
|
public static extern HWnd GetForegroundWindow();
|
||||||
|
|
||||||
|
|
|
@ -155,8 +155,9 @@ namespace BeefPerf
|
||||||
LogLine(text);
|
LogLine(text);
|
||||||
|
|
||||||
mFailed = true;
|
mFailed = true;
|
||||||
if (!mShuttingDown)
|
/*if (!mShuttingDown)
|
||||||
Shutdown();
|
Shutdown();*/
|
||||||
|
//Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +648,7 @@ namespace BeefPerf
|
||||||
|
|
||||||
public override void UnhandledCommandLine(String key, String value)
|
public override void UnhandledCommandLine(String key, String value)
|
||||||
{
|
{
|
||||||
Fail(StackStringFormat!("Unhandled command line param: {0}", key));
|
Fail(scope:: String()..AppendF("Unhandled command line param: {0}", key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupNewWindow(WidgetWindow window)
|
void SetupNewWindow(WidgetWindow window)
|
||||||
|
@ -729,6 +730,9 @@ namespace BeefPerf
|
||||||
|
|
||||||
public override void Update(bool batchStart)
|
public override void Update(bool batchStart)
|
||||||
{
|
{
|
||||||
|
if (mFailed)
|
||||||
|
Stop();
|
||||||
|
|
||||||
base.Update(batchStart);
|
base.Update(batchStart);
|
||||||
|
|
||||||
/*if (!mListenSocket.IsConnected)
|
/*if (!mListenSocket.IsConnected)
|
||||||
|
|
|
@ -1441,6 +1441,8 @@ namespace BeefPerf
|
||||||
|
|
||||||
if (cNext == 'd')
|
if (cNext == 'd')
|
||||||
zoneName.mParamsSize += 4;
|
zoneName.mParamsSize += 4;
|
||||||
|
else if (cNext == 'p')
|
||||||
|
zoneName.mParamsSize += 8;
|
||||||
else if (cNext == 'f')
|
else if (cNext == 'f')
|
||||||
zoneName.mParamsSize += 4;
|
zoneName.mParamsSize += 4;
|
||||||
else if (cNext == 's')
|
else if (cNext == 's')
|
||||||
|
|
|
@ -216,6 +216,12 @@ namespace BeefPerf
|
||||||
Read(&val, 4);
|
Read(&val, 4);
|
||||||
val.ToString(outStr);
|
val.ToString(outStr);
|
||||||
}
|
}
|
||||||
|
else if (cNext == 'p')
|
||||||
|
{
|
||||||
|
int64 val = 0;
|
||||||
|
Read(&val, 8);
|
||||||
|
val.ToString(outStr, "X", null);
|
||||||
|
}
|
||||||
else if (cNext == 'f')
|
else if (cNext == 'f')
|
||||||
{
|
{
|
||||||
float val = 0;
|
float val = 0;
|
||||||
|
|
|
@ -767,6 +767,12 @@ namespace BeefPerf
|
||||||
stateCtx.Read(&val, 4);
|
stateCtx.Read(&val, 4);
|
||||||
val.ToString(str);
|
val.ToString(str);
|
||||||
}
|
}
|
||||||
|
else if (cNext == 'p')
|
||||||
|
{
|
||||||
|
int64 val = 0;
|
||||||
|
stateCtx.Read(&val, 8);
|
||||||
|
val.ToString(str, "X", null);
|
||||||
|
}
|
||||||
else if (cNext == 'f')
|
else if (cNext == 'f')
|
||||||
{
|
{
|
||||||
float val = 0;
|
float val = 0;
|
||||||
|
@ -2316,6 +2322,11 @@ namespace BeefPerf
|
||||||
{
|
{
|
||||||
switch (keyCode)
|
switch (keyCode)
|
||||||
{
|
{
|
||||||
|
case (KeyCode)'C':
|
||||||
|
if (DarkTooltipManager.sTooltip != null)
|
||||||
|
{
|
||||||
|
gApp.SetClipboardText(DarkTooltipManager.sTooltip.mText);
|
||||||
|
}
|
||||||
case (KeyCode)'Z':
|
case (KeyCode)'Z':
|
||||||
mUndoManager.Undo();
|
mUndoManager.Undo();
|
||||||
case (KeyCode)'Y':
|
case (KeyCode)'Y':
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace LogViewer
|
||||||
public List<Match> mNewMatches ~ delete _;
|
public List<Match> mNewMatches ~ delete _;
|
||||||
public bool mRefreshing;
|
public bool mRefreshing;
|
||||||
|
|
||||||
|
public String mFilePath ~ delete _;
|
||||||
|
public String mMemLogName ~ delete _;
|
||||||
|
|
||||||
public uint32[] mColors = new .(
|
public uint32[] mColors = new .(
|
||||||
0xFFFFFFFF,
|
0xFFFFFFFF,
|
||||||
0xFFFC5858,
|
0xFFFC5858,
|
||||||
|
@ -54,6 +57,7 @@ namespace LogViewer
|
||||||
ewc.mFont = gApp.mFont;
|
ewc.mFont = gApp.mFont;
|
||||||
ewc.mWordWrap = false;
|
ewc.mWordWrap = false;
|
||||||
ewc.mTextColors = mColors;
|
ewc.mTextColors = mColors;
|
||||||
|
ewc.mIsReadOnly = true;
|
||||||
mDocEdit.InitScrollbars(true, true);
|
mDocEdit.InitScrollbars(true, true);
|
||||||
AddWidget(mDocEdit);
|
AddWidget(mDocEdit);
|
||||||
|
|
||||||
|
@ -79,6 +83,12 @@ namespace LogViewer
|
||||||
|
|
||||||
public void Load(StringView filePath)
|
public void Load(StringView filePath)
|
||||||
{
|
{
|
||||||
|
DeleteAndNullify!(mFilePath);
|
||||||
|
DeleteAndNullify!(mMemLogName);
|
||||||
|
mFilePath = new .(filePath);
|
||||||
|
|
||||||
|
mWidgetWindow.SetTitle(scope $"LogViewer - {mFilePath}");
|
||||||
|
|
||||||
scope AutoBeefPerf("Board.Load");
|
scope AutoBeefPerf("Board.Load");
|
||||||
|
|
||||||
delete mContent;
|
delete mContent;
|
||||||
|
@ -89,9 +99,45 @@ namespace LogViewer
|
||||||
{
|
{
|
||||||
gApp.Fail("Failed to open file '{0}'", filePath);
|
gApp.Fail("Failed to open file '{0}'", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mFilterDirtyCountdown = 1;
|
||||||
|
//Refresh();
|
||||||
//mDocEdit.SetText(mContent);
|
//mDocEdit.SetText(mContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern char8* MemLogger_Get(char8* name);
|
||||||
|
|
||||||
|
public void LoadMemLog(StringView name)
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(mFilePath);
|
||||||
|
DeleteAndNullify!(mMemLogName);
|
||||||
|
mMemLogName = new .(name);
|
||||||
|
|
||||||
|
mWidgetWindow.SetTitle(scope $"LogViewer - {mMemLogName}");
|
||||||
|
|
||||||
|
var result = MemLogger_Get(name.ToScopeCStr!());
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
gApp.Fail("Failed to open MemLog '{0}'", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete mContent;
|
||||||
|
mContent = new String();
|
||||||
|
mContent.Append(result);
|
||||||
|
|
||||||
|
mFilterDirtyCountdown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reload()
|
||||||
|
{
|
||||||
|
if (mFilePath != null)
|
||||||
|
Load(mFilePath);
|
||||||
|
if (mMemLogName != null)
|
||||||
|
LoadMemLog(mMemLogName);
|
||||||
|
}
|
||||||
|
|
||||||
void Refresh()
|
void Refresh()
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("Board.Refresh");
|
scope AutoBeefPerf("Board.Refresh");
|
||||||
|
@ -105,6 +151,8 @@ namespace LogViewer
|
||||||
|
|
||||||
let filters = mFilter.Split!('\n');
|
let filters = mFilter.Split!('\n');
|
||||||
|
|
||||||
|
if (mContent != null)
|
||||||
|
{
|
||||||
for (var line in mContent.Split('\n'))
|
for (var line in mContent.Split('\n'))
|
||||||
{
|
{
|
||||||
bool hadMatch = false;
|
bool hadMatch = false;
|
||||||
|
@ -138,6 +186,7 @@ namespace LogViewer
|
||||||
mNewContent.Append('\n');
|
mNewContent.Append('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mRefreshing = false;
|
mRefreshing = false;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ using Beefy.utils;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Beefy.sys;
|
||||||
|
|
||||||
namespace LogViewer
|
namespace LogViewer
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,45 @@ namespace LogViewer
|
||||||
{
|
{
|
||||||
base.Init();
|
base.Init();
|
||||||
|
|
||||||
|
/*var dialog = scope OpenFileDialog();
|
||||||
|
dialog.SetFilter("All files (*.*)|*.*");
|
||||||
|
dialog.InitialDirectory = mInstallDir;
|
||||||
|
dialog.Title = "Open Log";
|
||||||
|
let result = dialog.ShowDialog();
|
||||||
|
if ((result case .Err) || (dialog.FileNames.Count == 0))
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
BeefPerf.Init("127.0.0.1", "LogViewer");
|
||||||
|
|
||||||
|
DarkTheme darkTheme = new DarkTheme();
|
||||||
|
darkTheme.Init();
|
||||||
|
ThemeFactory.mDefault = darkTheme;
|
||||||
|
|
||||||
|
BFWindow.Flags windowFlags = BFWindow.Flags.Border | //BFWindow.Flags.SysMenu | //| BFWindow.Flags.CaptureMediaKeys |
|
||||||
|
BFWindow.Flags.Caption | BFWindow.Flags.Minimize | BFWindow.Flags.QuitOnClose | BFWindowBase.Flags.Resizable |
|
||||||
|
BFWindow.Flags.SysMenu | .Menu;
|
||||||
|
|
||||||
|
mFont = new Font();
|
||||||
|
float fontSize = 12;
|
||||||
|
mFont.Load(scope String(BFApp.sApp.mInstallDir, "fonts/SourceCodePro-Regular.ttf"), fontSize);
|
||||||
|
mFont.AddAlternate("Segoe UI Symbol", fontSize);
|
||||||
|
mFont.AddAlternate("Segoe UI Historic", fontSize);
|
||||||
|
mFont.AddAlternate("Segoe UI Emoji", fontSize);
|
||||||
|
|
||||||
|
mBoard = new Board();
|
||||||
|
//mBoard.Load(dialog.FileNames[0]);
|
||||||
|
mMainWindow = new WidgetWindow(null, "LogViewer", 20, 20, 1600, 1200, windowFlags, mBoard);
|
||||||
|
//mMainWindow.mWindowKeyDownDelegate.Add(new => SysKeyDown);
|
||||||
|
mMainWindow.SetMinimumSize(480, 360);
|
||||||
|
mMainWindow.mIsMainWindow = true;
|
||||||
|
|
||||||
|
SysMenu root = mMainWindow.mSysMenu;
|
||||||
|
var subMenu = root.AddMenuItem("&File");
|
||||||
|
subMenu.AddMenuItem("&Open", "Ctrl+O", new (menu) =>
|
||||||
|
{
|
||||||
var dialog = scope OpenFileDialog();
|
var dialog = scope OpenFileDialog();
|
||||||
dialog.SetFilter("All files (*.*)|*.*");
|
dialog.SetFilter("All files (*.*)|*.*");
|
||||||
dialog.InitialDirectory = mInstallDir;
|
dialog.InitialDirectory = mInstallDir;
|
||||||
|
@ -36,36 +76,23 @@ namespace LogViewer
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BeefPerf.Init("127.0.0.1", "LogViewer");
|
|
||||||
|
|
||||||
DarkTheme darkTheme = new DarkTheme();
|
|
||||||
darkTheme.Init();
|
|
||||||
ThemeFactory.mDefault = darkTheme;
|
|
||||||
|
|
||||||
BFWindow.Flags windowFlags = BFWindow.Flags.Border | //BFWindow.Flags.SysMenu | //| BFWindow.Flags.CaptureMediaKeys |
|
|
||||||
BFWindow.Flags.Caption | BFWindow.Flags.Minimize | BFWindow.Flags.QuitOnClose | BFWindowBase.Flags.Resizable |
|
|
||||||
BFWindow.Flags.SysMenu;
|
|
||||||
|
|
||||||
mFont = new Font();
|
|
||||||
float fontSize = 12;
|
|
||||||
mFont.Load(scope String(BFApp.sApp.mInstallDir, "fonts/SourceCodePro-Regular.ttf"), fontSize);
|
|
||||||
mFont.AddAlternate("Segoe UI Symbol", fontSize);
|
|
||||||
mFont.AddAlternate("Segoe UI Historic", fontSize);
|
|
||||||
mFont.AddAlternate("Segoe UI Emoji", fontSize);
|
|
||||||
|
|
||||||
mBoard = new Board();
|
|
||||||
mBoard.Load(dialog.FileNames[0]);
|
mBoard.Load(dialog.FileNames[0]);
|
||||||
mMainWindow = new WidgetWindow(null, "LogViewer", 0, 0, 1600, 1200, windowFlags, mBoard);
|
});
|
||||||
//mMainWindow.mWindowKeyDownDelegate.Add(new => SysKeyDown);
|
subMenu.AddMenuItem("Read &MemLog", "Ctrl+M", new (menu) =>
|
||||||
mMainWindow.SetMinimumSize(480, 360);
|
{
|
||||||
mMainWindow.mIsMainWindow = true;
|
var dialog = new MemLogDialog();
|
||||||
|
dialog.PopupWindow(mMainWindow);
|
||||||
|
});
|
||||||
|
subMenu.AddMenuItem("&Reload", "Ctrl+R", new (menu) =>
|
||||||
|
{
|
||||||
|
mBoard.Reload();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Fail(String str, params Object[] paramVals)
|
public void Fail(String str, params Object[] paramVals)
|
||||||
{
|
{
|
||||||
var errStr = scope String();
|
var errStr = scope String();
|
||||||
errStr.AppendF(str, paramVals);
|
errStr.AppendF(str, params paramVals);
|
||||||
Fail(errStr);
|
Fail(errStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
BeefTools/LogViewer/src/MemLogDialog.bf
Normal file
21
BeefTools/LogViewer/src/MemLogDialog.bf
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using Beefy.theme.dark;
|
||||||
|
using Beefy.widgets;
|
||||||
|
|
||||||
|
namespace LogViewer;
|
||||||
|
|
||||||
|
class MemLogDialog : DarkDialog
|
||||||
|
{
|
||||||
|
EditWidget mEditWidget;
|
||||||
|
|
||||||
|
public this() : base("Open MemLog", "MemLog Name")
|
||||||
|
{
|
||||||
|
|
||||||
|
mDefaultButton = AddButton("OK", new (evt) =>
|
||||||
|
{
|
||||||
|
var name = mEditWidget.GetText(.. scope .());
|
||||||
|
gApp.mBoard.LoadMemLog(name);
|
||||||
|
});
|
||||||
|
mEscButton = AddButton("Cancel", new (evt) => Close());
|
||||||
|
mEditWidget = AddEdit("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
#include "util/Vector.h"
|
#include "util/Vector.h"
|
||||||
#include "util/PerfTimer.h"
|
#include "util/PerfTimer.h"
|
||||||
#include "util/TLSingleton.h"
|
#include "util/TLSingleton.h"
|
||||||
|
#include "util/MemLogger.h"
|
||||||
#include "img/ImgEffects.h"
|
#include "img/ImgEffects.h"
|
||||||
|
|
||||||
#include "util/AllocDebug.h"
|
#include "util/AllocDebug.h"
|
||||||
|
@ -927,3 +928,35 @@ BF_EXPORT void BF_CALLTYPE BF_Test()
|
||||||
for (int i : iArr)
|
for (int i : iArr)
|
||||||
OutputDebugStrF("Hey %d\n", i);
|
OutputDebugStrF("Hey %d\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void* BF_CALLTYPE MemLogger_Create(const char* memName, int size)
|
||||||
|
{
|
||||||
|
MemLogger* memLogger = new MemLogger();
|
||||||
|
if (!memLogger->Create(memName, size))
|
||||||
|
{
|
||||||
|
delete memLogger;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return memLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE MemLogger_Write(MemLogger* memLogger, void* ptr, int size)
|
||||||
|
{
|
||||||
|
memLogger->Write(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT void BF_CALLTYPE MemLogger_Delete(MemLogger* memLogger)
|
||||||
|
{
|
||||||
|
delete memLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT const char* BF_CALLTYPE MemLogger_Get(const char* memName)
|
||||||
|
{
|
||||||
|
MemLogger memLogger;
|
||||||
|
|
||||||
|
String& outString = *gBeefySys_TLStrReturn.Get();
|
||||||
|
outString.Clear();
|
||||||
|
if (!memLogger.Get(memName, outString))
|
||||||
|
return NULL;
|
||||||
|
return outString.c_str();
|
||||||
|
}
|
||||||
|
|
|
@ -1950,6 +1950,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClCompile Include="util\MappedFile.cpp" />
|
<ClCompile Include="util\MappedFile.cpp" />
|
||||||
<ClCompile Include="util\MathUtils.cpp" />
|
<ClCompile Include="util\MathUtils.cpp" />
|
||||||
<ClCompile Include="util\Matrix4.cpp" />
|
<ClCompile Include="util\Matrix4.cpp" />
|
||||||
|
<ClCompile Include="util\MemLogger.cpp" />
|
||||||
<ClCompile Include="util\MTRand.cpp" />
|
<ClCompile Include="util\MTRand.cpp" />
|
||||||
<ClCompile Include="util\PerfTimer.cpp" />
|
<ClCompile Include="util\PerfTimer.cpp" />
|
||||||
<ClCompile Include="util\Point.cpp" />
|
<ClCompile Include="util\Point.cpp" />
|
||||||
|
@ -2189,6 +2190,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
|
||||||
<ClInclude Include="util\MappedFile.h" />
|
<ClInclude Include="util\MappedFile.h" />
|
||||||
<ClInclude Include="util\MathUtils.h" />
|
<ClInclude Include="util\MathUtils.h" />
|
||||||
<ClInclude Include="util\Matrix4.h" />
|
<ClInclude Include="util\Matrix4.h" />
|
||||||
|
<ClInclude Include="util\MemLogger.h" />
|
||||||
<ClInclude Include="util\MTRand.h" />
|
<ClInclude Include="util\MTRand.h" />
|
||||||
<ClInclude Include="util\MultiDictionary.h" />
|
<ClInclude Include="util\MultiDictionary.h" />
|
||||||
<ClInclude Include="util\MultiHashSet.h" />
|
<ClInclude Include="util\MultiHashSet.h" />
|
||||||
|
|
|
@ -743,6 +743,9 @@
|
||||||
<ClCompile Include="img\BMPData.cpp">
|
<ClCompile Include="img\BMPData.cpp">
|
||||||
<Filter>src\img</Filter>
|
<Filter>src\img</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\MemLogger.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Common.h">
|
<ClInclude Include="Common.h">
|
||||||
|
@ -1147,6 +1150,9 @@
|
||||||
<ClInclude Include="img\BMPData.h">
|
<ClInclude Include="img\BMPData.h">
|
||||||
<Filter>src\img</Filter>
|
<Filter>src\img</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\MemLogger.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
||||||
|
|
|
@ -880,6 +880,7 @@
|
||||||
<ClCompile Include="util\Json.cpp" />
|
<ClCompile Include="util\Json.cpp" />
|
||||||
<ClCompile Include="util\MappedFile.cpp" />
|
<ClCompile Include="util\MappedFile.cpp" />
|
||||||
<ClCompile Include="util\Matrix4.cpp" />
|
<ClCompile Include="util\Matrix4.cpp" />
|
||||||
|
<ClCompile Include="util\MemLogger.cpp" />
|
||||||
<ClCompile Include="util\PerfTimer.cpp" />
|
<ClCompile Include="util\PerfTimer.cpp" />
|
||||||
<ClCompile Include="util\Point.cpp" />
|
<ClCompile Include="util\Point.cpp" />
|
||||||
<ClCompile Include="util\PolySpline.cpp" />
|
<ClCompile Include="util\PolySpline.cpp" />
|
||||||
|
@ -1047,6 +1048,7 @@
|
||||||
<ClInclude Include="util\Json.h" />
|
<ClInclude Include="util\Json.h" />
|
||||||
<ClInclude Include="util\MappedFile.h" />
|
<ClInclude Include="util\MappedFile.h" />
|
||||||
<ClInclude Include="util\Matrix4.h" />
|
<ClInclude Include="util\Matrix4.h" />
|
||||||
|
<ClInclude Include="util\MemLogger.h" />
|
||||||
<ClInclude Include="util\PerfTimer.h" />
|
<ClInclude Include="util\PerfTimer.h" />
|
||||||
<ClInclude Include="util\Point.h" />
|
<ClInclude Include="util\Point.h" />
|
||||||
<ClInclude Include="util\PolySpline.h" />
|
<ClInclude Include="util\PolySpline.h" />
|
||||||
|
|
|
@ -593,6 +593,9 @@
|
||||||
<ClCompile Include="img\BMPData.cpp">
|
<ClCompile Include="img\BMPData.cpp">
|
||||||
<Filter>src\img</Filter>
|
<Filter>src\img</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\MemLogger.cpp">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Common.h">
|
<ClInclude Include="Common.h">
|
||||||
|
@ -913,6 +916,9 @@
|
||||||
<ClInclude Include="img\BMPData.h">
|
<ClInclude Include="img\BMPData.h">
|
||||||
<Filter>src\img</Filter>
|
<Filter>src\img</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\MemLogger.h">
|
||||||
|
<Filter>src\util</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
|
||||||
|
|
|
@ -294,6 +294,7 @@ file(GLOB SRC_FILES
|
||||||
util/MappedFile.cpp
|
util/MappedFile.cpp
|
||||||
util/MathUtils.cpp
|
util/MathUtils.cpp
|
||||||
util/Matrix4.cpp
|
util/Matrix4.cpp
|
||||||
|
util/MemLogger.cpp
|
||||||
util/PerfTimer.cpp
|
util/PerfTimer.cpp
|
||||||
util/Point.cpp
|
util/Point.cpp
|
||||||
util/PolySpline.cpp
|
util/PolySpline.cpp
|
||||||
|
|
|
@ -660,7 +660,7 @@ void Beefy::ExactMinimalDoubleToStr(double d, char* str)
|
||||||
|
|
||||||
static char* StbspCallback(char *buf, void *user, int len)
|
static char* StbspCallback(char *buf, void *user, int len)
|
||||||
{
|
{
|
||||||
((String*)user)->Append(buf, len);
|
((StringImpl*)user)->Append(buf, len);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,6 +821,12 @@ String Beefy::vformat(const char* fmt, va_list argPtr)
|
||||||
BF_stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
BF_stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Beefy::vformat(StringImpl& str, const char* fmt, va_list argPtr)
|
||||||
|
{
|
||||||
|
char buf[STB_SPRINTF_MIN];
|
||||||
|
BF_stbsp_vsprintfcb(StbspCallback, (void*)&str, buf, fmt, argPtr);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String Beefy::StrFormat(const char* fmt ...)
|
String Beefy::StrFormat(const char* fmt ...)
|
||||||
|
|
|
@ -195,6 +195,7 @@ uint64 BFGetTickCountMicro();
|
||||||
uint64 BFGetTickCountMicroFast();
|
uint64 BFGetTickCountMicroFast();
|
||||||
|
|
||||||
extern String vformat(const char* fmt, va_list argPtr);
|
extern String vformat(const char* fmt, va_list argPtr);
|
||||||
|
extern void vformat(StringImpl& str, const char* fmt, va_list argPtr);
|
||||||
extern String StrFormat(const char* fmt ...);
|
extern String StrFormat(const char* fmt ...);
|
||||||
void ExactMinimalFloatToStr(float f, char* str);
|
void ExactMinimalFloatToStr(float f, char* str);
|
||||||
void ExactMinimalDoubleToStr(double d, char* str);
|
void ExactMinimalDoubleToStr(double d, char* str);
|
||||||
|
|
|
@ -832,6 +832,17 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetComputerName(char* outStr, int* inOutS
|
||||||
|
|
||||||
// BfpProcess
|
// BfpProcess
|
||||||
|
|
||||||
|
struct BfpProcess
|
||||||
|
{
|
||||||
|
pid_t mProcessId;
|
||||||
|
String mImageName;
|
||||||
|
|
||||||
|
BfpProcess()
|
||||||
|
{
|
||||||
|
mProcessId = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BFP_EXPORT intptr BFP_CALLTYPE BfpProcess_GetCurrentId()
|
BFP_EXPORT intptr BFP_CALLTYPE BfpProcess_GetCurrentId()
|
||||||
{
|
{
|
||||||
return getpid();
|
return getpid();
|
||||||
|
@ -844,18 +855,87 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_IsRemoteMachine(const char* machineName)
|
||||||
|
|
||||||
BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult)
|
BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
pid_t pid = static_cast<pid_t>(processId);
|
||||||
|
|
||||||
|
char proc_dir[64];
|
||||||
|
snprintf(proc_dir, sizeof(proc_dir), "/proc/%d", pid);
|
||||||
|
|
||||||
|
if (access(proc_dir, F_OK) != 0)
|
||||||
|
{
|
||||||
|
OUTRESULT(BfpProcessResult_NotFound);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfpProcess* process = new BfpProcess();
|
||||||
|
process->mProcessId = pid;
|
||||||
|
return process;
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Enumerate(const char* machineName, BfpProcess** outProcesses, int* inOutProcessesSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Enumerate(const char* machineName, BfpProcess** outProcesses, int* inOutProcessesSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
DIR* procDir = opendir("/proc");
|
||||||
|
if (!procDir)
|
||||||
|
{
|
||||||
|
*inOutProcessesSize = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Beefy::Array<BfpProcess*> processList;
|
||||||
|
struct dirent* entry;
|
||||||
|
while ((entry = readdir(procDir)) != NULL)
|
||||||
|
{
|
||||||
|
const char* name = entry->d_name;
|
||||||
|
bool is_pid = name[0] != '\0';
|
||||||
|
for (const char* p = name; *p; ++p)
|
||||||
|
{
|
||||||
|
if (*p < '0' || *p > '9')
|
||||||
|
{
|
||||||
|
is_pid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_pid)
|
||||||
|
{
|
||||||
|
pid_t pid = static_cast<pid_t>(atoi(name));
|
||||||
|
if (pid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BfpProcess* proc = new BfpProcess();
|
||||||
|
proc->mProcessId = pid;
|
||||||
|
processList.Add(proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(procDir);
|
||||||
|
|
||||||
|
if (static_cast<int>(processList.size()) > *inOutProcessesSize)
|
||||||
|
{
|
||||||
|
*inOutProcessesSize = static_cast<int>(processList.size());
|
||||||
|
OUTRESULT(BfpProcessResult_InsufficientBuffer);
|
||||||
|
for (BfpProcess* p_del : processList)
|
||||||
|
delete p_del;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < processList.size(); ++i)
|
||||||
|
outProcesses[i] = processList[i];
|
||||||
|
*inOutProcessesSize = static_cast<int>(processList.size());
|
||||||
|
OUTRESULT(BfpProcessResult_Ok);
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
delete process;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult)
|
BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult)
|
||||||
|
@ -865,18 +945,49 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS,
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
String title;
|
||||||
|
TryStringOut(title, outTitle, inOutTitleSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char* outName, int* inOutNameSize, BfpProcessResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char* outName, int* inOutNameSize, BfpProcessResult* outResult)
|
||||||
{
|
{
|
||||||
|
if (process->mImageName.IsEmpty())
|
||||||
|
{
|
||||||
|
#ifdef BF_PLATFORM_LINUX
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/exe", process->mProcessId);
|
||||||
|
char name_buf[PATH_MAX] = {0};
|
||||||
|
ssize_t len = readlink(path, name_buf, sizeof(name_buf) - 1);
|
||||||
|
if (len != -1)
|
||||||
|
{
|
||||||
|
name_buf[len] = '\0';
|
||||||
|
process->mImageName.Append(basename(name_buf));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only 15 characters of the process name are returned by this, but it works for all processes.
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/comm", process->mProcessId);
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
if (fgets(name_buf, sizeof(name_buf), fp)) {
|
||||||
|
size_t len = strcspn(name_buf, "\n");
|
||||||
|
name_buf[len] = '\0';
|
||||||
|
process->mImageName.Append(name_buf, len);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
NOT_IMPL;
|
NOT_IMPL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
TryStringOut(process->mImageName, outName, inOutNameSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process)
|
BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
return process->mProcessId;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BfpSpawn
|
// BfpSpawn
|
||||||
|
@ -1822,7 +1933,27 @@ BFP_EXPORT void BFP_CALLTYPE BfpDirectory_Create(const char* path, BfpFileResult
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpDirectory_Rename(const char* oldName, const char* newName, BfpFileResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpDirectory_Rename(const char* oldName, const char* newName, BfpFileResult* outResult)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
if (rename(oldName, newName) != 0)
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case EEXIST:
|
||||||
|
OUTRESULT(BfpFileResult_AlreadyExists);
|
||||||
|
break;
|
||||||
|
case ENOTEMPTY:
|
||||||
|
OUTRESULT(BfpFileResult_NotEmpty);
|
||||||
|
break;
|
||||||
|
case EISDIR:
|
||||||
|
case ENOTDIR:
|
||||||
|
OUTRESULT(BfpFileResult_InvalidParameter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OUTRESULT(BfpFileResult_UnknownError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
OUTRESULT(BfpFileResult_Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpDirectory_Delete(const char* path, BfpFileResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpDirectory_Delete(const char* path, BfpFileResult* outResult)
|
||||||
|
@ -2372,9 +2503,148 @@ BFP_EXPORT void BFP_CALLTYPE BfpFile_GetFullPath(const char* inPath, char* outPa
|
||||||
TryStringOut(str, outPath, inOutPathSize, (BfpResult*)outResult);
|
TryStringOut(str, outPath, inOutPathSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpFile_GetActualPath(const char* inPath, char* outPath, int* inOutPathSize, BfpFileResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpFile_GetActualPath(const char* inPathC, char* outPathC, int* inOutPathSize, BfpFileResult* outResult)
|
||||||
{
|
{
|
||||||
NOT_IMPL;
|
String inPath = inPathC;
|
||||||
|
String outPath;
|
||||||
|
|
||||||
|
// Check for '/../' backtracking - handle those first
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int32 lastComponentStart = -1;
|
||||||
|
|
||||||
|
while (i < inPath.mLength)
|
||||||
|
{
|
||||||
|
// Skip until path separator
|
||||||
|
while ((i < inPath.mLength) && (inPath[i] != DIR_SEP_CHAR) && (inPath[i] != DIR_SEP_CHAR_ALT))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (lastComponentStart != -1)
|
||||||
|
{
|
||||||
|
if ((i - lastComponentStart == 2) && (inPath[lastComponentStart] == '.') && (inPath[lastComponentStart + 1] == '.'))
|
||||||
|
{
|
||||||
|
// Backtrack
|
||||||
|
while ((lastComponentStart > 0) &&
|
||||||
|
((inPath[lastComponentStart - 1] == DIR_SEP_CHAR) || (inPath[lastComponentStart - 1] == DIR_SEP_CHAR_ALT)))
|
||||||
|
lastComponentStart--;
|
||||||
|
while ((lastComponentStart > 0) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR_ALT))
|
||||||
|
lastComponentStart--;
|
||||||
|
inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
|
||||||
|
i = lastComponentStart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((i - lastComponentStart == 1) && (inPath[lastComponentStart] == '.'))
|
||||||
|
{
|
||||||
|
inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
|
||||||
|
i = lastComponentStart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
// Ignore multiple slashes in a row
|
||||||
|
while ((i < inPath.mLength) && ((inPath[i] == DIR_SEP_CHAR) || (inPath[i] == DIR_SEP_CHAR_ALT)))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
lastComponentStart = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 i = 0;
|
||||||
|
int length = (int)inPath.length();
|
||||||
|
|
||||||
|
if (length >= 1)
|
||||||
|
{
|
||||||
|
// Handle root paths starting with '/' or '\'
|
||||||
|
if ((inPath[0] == DIR_SEP_CHAR) || (inPath[0] == DIR_SEP_CHAR_ALT))
|
||||||
|
{
|
||||||
|
i++; // start after initial slash
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Relative path - prepend current working directory
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
if (getcwd(cwd, PATH_MAX) != NULL)
|
||||||
|
{
|
||||||
|
outPath.Append(cwd);
|
||||||
|
if (outPath[outPath.length() - 1] != DIR_SEP_CHAR)
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 lastComponentStart = i;
|
||||||
|
bool addSeparator = false;
|
||||||
|
String subName;
|
||||||
|
|
||||||
|
while (i < length)
|
||||||
|
{
|
||||||
|
// skip until path separator
|
||||||
|
while ((i < length) && (inPath[i] != DIR_SEP_CHAR) && (inPath[i] != DIR_SEP_CHAR_ALT))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (addSeparator)
|
||||||
|
outPath.Append(DIR_SEP_CHAR);
|
||||||
|
|
||||||
|
subName.Clear();
|
||||||
|
subName = inPath.Substring(0, i);
|
||||||
|
for (int j = 0; j < (int)subName.length(); j++)
|
||||||
|
if (subName[j] == DIR_SEP_CHAR_ALT)
|
||||||
|
subName[j] = DIR_SEP_CHAR;
|
||||||
|
|
||||||
|
String parentPath;
|
||||||
|
String componentName;
|
||||||
|
int32 lastSep = subName.LastIndexOf(DIR_SEP_CHAR);
|
||||||
|
|
||||||
|
if (lastSep != -1)
|
||||||
|
{
|
||||||
|
parentPath = subName.Substring(0, lastSep);
|
||||||
|
if (parentPath.length() == 0)
|
||||||
|
parentPath = "/";
|
||||||
|
componentName = subName.Substring(lastSep + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentPath = ".";
|
||||||
|
componentName = subName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
DIR* dir = opendir(parentPath.c_str());
|
||||||
|
if (dir != NULL)
|
||||||
|
{
|
||||||
|
struct dirent* entry = NULL;
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Linux is case-sensitive, but we do a case-insensitive comparison
|
||||||
|
// to help find the correct case for the file
|
||||||
|
if (strcasecmp(entry->d_name, componentName.c_str()) == 0)
|
||||||
|
{
|
||||||
|
outPath.Append(entry->d_name);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
// If not found, use the original component name
|
||||||
|
outPath.Append(inPath.Substring(lastComponentStart, i - lastComponentStart));
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
// Ignore multiple slashes in a row
|
||||||
|
while ((i < length) && ((inPath[i] == DIR_SEP_CHAR) || (inPath[i] == DIR_SEP_CHAR_ALT)))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
lastComponentStart = i;
|
||||||
|
addSeparator = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TryStringOut(outPath, outPathC, inOutPathSize, (BfpResult*)outResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BfpFindFileData
|
// BfpFindFileData
|
||||||
|
|
|
@ -553,12 +553,40 @@ struct BfpOverlappedFile : BfpOverlapped
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OverlappedReadResult : OVERLAPPED
|
||||||
|
{
|
||||||
|
BfpFile* mFile;
|
||||||
|
intptr mBytesRead;
|
||||||
|
DWORD mErrorCode;
|
||||||
|
Array<uint8> mData;
|
||||||
|
bool mPending;
|
||||||
|
bool mAttemptedRead;
|
||||||
|
|
||||||
|
OverlappedReadResult()
|
||||||
|
{
|
||||||
|
mFile = NULL;
|
||||||
|
mBytesRead = 0;
|
||||||
|
mErrorCode = 0;
|
||||||
|
mPending = false;
|
||||||
|
mAttemptedRead = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetPtr()
|
||||||
|
{
|
||||||
|
return mData.mVals;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct BfpAsyncData
|
struct BfpAsyncData
|
||||||
{
|
{
|
||||||
|
BfpFile* mFile;
|
||||||
|
Array<uint8> mQueuedData;
|
||||||
HANDLE mEvent;
|
HANDLE mEvent;
|
||||||
|
OverlappedReadResult mOverlappedResult;
|
||||||
|
|
||||||
BfpAsyncData()
|
BfpAsyncData(BfpFile* file)
|
||||||
{
|
{
|
||||||
|
mFile = file;
|
||||||
mEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
mEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +615,98 @@ struct BfpAsyncData
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ReadQueued(void* buffer, int size, int timeoutMS, bool& didWait)
|
||||||
|
{
|
||||||
|
gBfpCritSect.Lock();
|
||||||
|
|
||||||
|
if (mQueuedData.mSize == 0)
|
||||||
|
{
|
||||||
|
if (mOverlappedResult.mPending)
|
||||||
|
{
|
||||||
|
gBfpCritSect.Unlock();
|
||||||
|
WaitAndResetEvent(timeoutMS);
|
||||||
|
didWait = true;
|
||||||
|
gBfpCritSect.Lock();
|
||||||
|
}
|
||||||
|
if (mQueuedData.mSize == 0)
|
||||||
|
{
|
||||||
|
gBfpCritSect.Unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int readSize = BF_MIN(size, mQueuedData.mSize);
|
||||||
|
memcpy(buffer, mQueuedData.mVals, readSize);
|
||||||
|
mQueuedData.RemoveRange(0, readSize);
|
||||||
|
|
||||||
|
gBfpCritSect.Unlock();
|
||||||
|
return readSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleResult(uint32 errorCode, uint32 bytesRead)
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(gBfpCritSect);
|
||||||
|
BF_ASSERT(mOverlappedResult.mPending);
|
||||||
|
mOverlappedResult.mPending = false;
|
||||||
|
mOverlappedResult.mErrorCode = errorCode;
|
||||||
|
mOverlappedResult.mBytesRead = bytesRead;
|
||||||
|
if (mOverlappedResult.mAttemptedRead) // Already tried to read and failed
|
||||||
|
{
|
||||||
|
mQueuedData.Insert(mQueuedData.mSize, (uint8*)mOverlappedResult.GetPtr(), bytesRead);
|
||||||
|
mOverlappedResult.mData.Clear();
|
||||||
|
}
|
||||||
|
SetEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbortOverlapped()
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(gBfpCritSect);
|
||||||
|
BF_ASSERT(mOverlappedResult.mPending);
|
||||||
|
mOverlappedResult.mPending = false;
|
||||||
|
mOverlappedResult.mData.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FinishRead(void* buffer, int size, DWORD& errorCode)
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(gBfpCritSect);
|
||||||
|
BF_ASSERT(!mOverlappedResult.mAttemptedRead);
|
||||||
|
mOverlappedResult.mAttemptedRead = true;
|
||||||
|
if (mOverlappedResult.mPending)
|
||||||
|
{
|
||||||
|
return -2; // Still executing
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mOverlappedResult.mErrorCode != 0) && (mOverlappedResult.mBytesRead == 0))
|
||||||
|
{
|
||||||
|
mOverlappedResult.mData.Clear();
|
||||||
|
errorCode = mOverlappedResult.mErrorCode;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_ASSERT(size >= mOverlappedResult.mBytesRead);
|
||||||
|
memcpy(buffer, mOverlappedResult.GetPtr(), mOverlappedResult.mBytesRead);
|
||||||
|
int bytesRead = (int)mOverlappedResult.mBytesRead;
|
||||||
|
mOverlappedResult.mData.Clear();
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlappedReadResult* StartOverlapped(int size)
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(gBfpCritSect);
|
||||||
|
|
||||||
|
BF_ASSERT(!mOverlappedResult.mPending);
|
||||||
|
BF_ASSERT(mOverlappedResult.mData.IsEmpty());
|
||||||
|
|
||||||
|
memset(&mOverlappedResult, 0, sizeof(OVERLAPPED));
|
||||||
|
mOverlappedResult.mFile = mFile;
|
||||||
|
mOverlappedResult.mBytesRead = 0;
|
||||||
|
mOverlappedResult.mPending = true;
|
||||||
|
mOverlappedResult.mAttemptedRead = false;
|
||||||
|
mOverlappedResult.mErrorCode = -1;
|
||||||
|
mOverlappedResult.mData.Resize(size);
|
||||||
|
return &mOverlappedResult;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BfpFile
|
struct BfpFile
|
||||||
|
@ -618,6 +738,12 @@ struct BfpFile
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void WINAPI OverlappedReadComplete(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
|
||||||
|
{
|
||||||
|
OverlappedReadResult* readResult = (OverlappedReadResult*)lpOverlapped;
|
||||||
|
readResult->mFile->mAsyncData->HandleResult(dwErrorCode, dwNumberOfBytesTransfered);
|
||||||
|
}
|
||||||
|
|
||||||
struct BfpFileWatcher : public BfpOverlapped
|
struct BfpFileWatcher : public BfpOverlapped
|
||||||
{
|
{
|
||||||
String mPath;
|
String mPath;
|
||||||
|
@ -2952,7 +3078,7 @@ BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* path, BfpFileCreateK
|
||||||
|
|
||||||
if (isOverlapped)
|
if (isOverlapped)
|
||||||
{
|
{
|
||||||
bfpFile->mAsyncData = new BfpAsyncData();
|
bfpFile->mAsyncData = new BfpAsyncData(bfpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bfpFile;
|
return bfpFile;
|
||||||
|
@ -3048,7 +3174,7 @@ BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* path, BfpFileCreateK
|
||||||
bfpFile->mHandle = handle;
|
bfpFile->mHandle = handle;
|
||||||
|
|
||||||
if ((createFlags & BfpFileCreateFlag_AllowTimeouts) != 0)
|
if ((createFlags & BfpFileCreateFlag_AllowTimeouts) != 0)
|
||||||
bfpFile->mAsyncData = new BfpAsyncData();
|
bfpFile->mAsyncData = new BfpAsyncData(bfpFile);
|
||||||
|
|
||||||
if ((createFlags & BfpFileCreateFlag_Pipe) != 0)
|
if ((createFlags & BfpFileCreateFlag_Pipe) != 0)
|
||||||
bfpFile->mIsPipe = true;
|
bfpFile->mIsPipe = true;
|
||||||
|
@ -3142,21 +3268,6 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Write(BfpFile* file, const void* buffer,
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OverlappedReadResult : OVERLAPPED
|
|
||||||
{
|
|
||||||
BfpFile* mFile;
|
|
||||||
intptr mBytesRead;
|
|
||||||
DWORD mErrorCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void WINAPI OverlappedReadComplete(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
|
|
||||||
{
|
|
||||||
OverlappedReadResult* readResult = (OverlappedReadResult*)lpOverlapped;
|
|
||||||
readResult->mErrorCode = dwErrorCode;
|
|
||||||
readResult->mBytesRead = dwNumberOfBytesTransfered;
|
|
||||||
readResult->mFile->mAsyncData->SetEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr size, int timeoutMS, BfpFileResult* outResult)
|
BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr size, int timeoutMS, BfpFileResult* outResult)
|
||||||
{
|
{
|
||||||
bool forceNormalRead = false;
|
bool forceNormalRead = false;
|
||||||
|
@ -3208,6 +3319,23 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file->mAsyncData != NULL)
|
||||||
|
{
|
||||||
|
bool didWait = false;
|
||||||
|
int readSize = file->mAsyncData->ReadQueued(buffer, (int)size, timeoutMS, didWait);
|
||||||
|
if (readSize > 0)
|
||||||
|
{
|
||||||
|
OUTRESULT(BfpFileResult_Ok);
|
||||||
|
return readSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didWait)
|
||||||
|
{
|
||||||
|
OUTRESULT(BfpFileResult_Timeout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((timeoutMS != -1) && (!forceNormalRead))
|
if ((timeoutMS != -1) && (!forceNormalRead))
|
||||||
{
|
{
|
||||||
if (file->mAsyncData == NULL)
|
if (file->mAsyncData == NULL)
|
||||||
|
@ -3218,29 +3346,34 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
OverlappedReadResult overlapped;
|
OverlappedReadResult* overlapped = file->mAsyncData->StartOverlapped((int)size);
|
||||||
memset(&overlapped, 0, sizeof(OverlappedReadResult));
|
|
||||||
overlapped.mFile = file;
|
|
||||||
|
|
||||||
//TODO: this doesn't set file stream location. It only works for streams like pipes, sockets, etc
|
//TODO: this doesn't set file stream location. It only works for streams like pipes, sockets, etc
|
||||||
if (::ReadFileEx(file->mHandle, buffer, (uint32)size, &overlapped, OverlappedReadComplete))
|
if (::ReadFileEx(file->mHandle, overlapped->GetPtr(), (uint32)size, overlapped, OverlappedReadComplete))
|
||||||
{
|
{
|
||||||
if (!file->mAsyncData->WaitAndResetEvent(timeoutMS))
|
file->mAsyncData->WaitAndResetEvent(timeoutMS);
|
||||||
|
|
||||||
|
DWORD errorCode = 0;
|
||||||
|
int readResult = file->mAsyncData->FinishRead(buffer, (int)size, errorCode);
|
||||||
|
if (readResult != -2) // Still executing
|
||||||
{
|
{
|
||||||
::CancelIoEx(file->mHandle, &overlapped);
|
if (errorCode == 0)
|
||||||
// There's a chance we completed before we were cancelled -- check on that
|
{
|
||||||
if (!file->mAsyncData->WaitAndResetEvent(0))
|
OUTRESULT(BfpFileResult_Ok);
|
||||||
|
return readResult;
|
||||||
|
}
|
||||||
|
else if (errorCode == ERROR_OPERATION_ABORTED)
|
||||||
{
|
{
|
||||||
OUTRESULT(BfpFileResult_Timeout);
|
OUTRESULT(BfpFileResult_Timeout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
if (overlapped.mErrorCode == 0)
|
|
||||||
{
|
{
|
||||||
|
OUTRESULT(BfpFileResult_Ok);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (overlapped.mErrorCode == ERROR_OPERATION_ABORTED)
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
OUTRESULT(BfpFileResult_Timeout);
|
OUTRESULT(BfpFileResult_Timeout);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3248,21 +3381,19 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
file->mAsyncData->AbortOverlapped();
|
||||||
|
|
||||||
int lastError = ::GetLastError();
|
int lastError = ::GetLastError();
|
||||||
if (lastError == ERROR_PIPE_LISTENING)
|
if (lastError == ERROR_PIPE_LISTENING)
|
||||||
{
|
{
|
||||||
overlapped.hEvent = file->mAsyncData->mEvent;
|
overlapped->hEvent = file->mAsyncData->mEvent;
|
||||||
if (!::ConnectNamedPipe(file->mHandle, &overlapped))
|
if (!::ConnectNamedPipe(file->mHandle, overlapped))
|
||||||
{
|
{
|
||||||
int lastError = ::GetLastError();
|
int lastError = ::GetLastError();
|
||||||
if (lastError == ERROR_IO_PENDING)
|
if (lastError == ERROR_IO_PENDING)
|
||||||
{
|
{
|
||||||
if (!file->mAsyncData->WaitAndResetEvent(timeoutMS))
|
if (!file->mAsyncData->WaitAndResetEvent(timeoutMS))
|
||||||
{
|
{
|
||||||
::CancelIoEx(file->mHandle, &overlapped);
|
|
||||||
// Clear event set by CancelIoEx
|
|
||||||
file->mAsyncData->WaitAndResetEvent(0);
|
|
||||||
|
|
||||||
OUTRESULT(BfpFileResult_Timeout);
|
OUTRESULT(BfpFileResult_Timeout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3278,9 +3409,6 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OUTRESULT(BfpFileResult_Ok);
|
|
||||||
return overlapped.mBytesRead;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,11 @@ void BpCmdTarget::Enter(const char* name, va_list args)
|
||||||
intptr val = va_arg(args, intptr);
|
intptr val = va_arg(args, intptr);
|
||||||
paramSize += 4; // int32
|
paramSize += 4; // int32
|
||||||
}
|
}
|
||||||
|
else if (nextC == 'p')
|
||||||
|
{
|
||||||
|
intptr val = va_arg(args, intptr);
|
||||||
|
paramSize += 8; // int64
|
||||||
|
}
|
||||||
else if (nextC == 's')
|
else if (nextC == 's')
|
||||||
{
|
{
|
||||||
const char* str = ToStrPtr(va_arg(args, char*));
|
const char* str = ToStrPtr(va_arg(args, char*));
|
||||||
|
@ -488,6 +493,10 @@ void BpCmdTarget::Enter(const char* name, va_list args)
|
||||||
{
|
{
|
||||||
BPCMD_MEMBER(int32) = (int32)va_arg(args, intptr);
|
BPCMD_MEMBER(int32) = (int32)va_arg(args, intptr);
|
||||||
}
|
}
|
||||||
|
else if (nextC == 'p')
|
||||||
|
{
|
||||||
|
BPCMD_MEMBER(int64) = (int64)va_arg(args, intptr);
|
||||||
|
}
|
||||||
else if (nextC == 's')
|
else if (nextC == 's')
|
||||||
{
|
{
|
||||||
const char* str = ToStrPtr(va_arg(args, char*));
|
const char* str = ToStrPtr(va_arg(args, char*));
|
||||||
|
@ -1120,6 +1129,10 @@ void BpManager::ThreadProc()
|
||||||
{
|
{
|
||||||
zoneName->mSize += 4;
|
zoneName->mSize += 4;
|
||||||
}
|
}
|
||||||
|
else if (nextC == 'p')
|
||||||
|
{
|
||||||
|
zoneName->mSize += 8;
|
||||||
|
}
|
||||||
else if (nextC == 's')
|
else if (nextC == 's')
|
||||||
{
|
{
|
||||||
isDyn = true;
|
isDyn = true;
|
||||||
|
@ -1175,6 +1188,10 @@ void BpManager::ThreadProc()
|
||||||
{
|
{
|
||||||
checkDataIn += 4;
|
checkDataIn += 4;
|
||||||
}
|
}
|
||||||
|
else if (nextC == 'p')
|
||||||
|
{
|
||||||
|
checkDataIn += 8;
|
||||||
|
}
|
||||||
else if (nextC == 's')
|
else if (nextC == 's')
|
||||||
{
|
{
|
||||||
int len = (int)strlen((const char*)checkDataIn);
|
int len = (int)strlen((const char*)checkDataIn);
|
||||||
|
|
176
BeefySysLib/util/MemLogger.cpp
Normal file
176
BeefySysLib/util/MemLogger.cpp
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
#include "MemLogger.h"
|
||||||
|
|
||||||
|
USING_NS_BF;
|
||||||
|
|
||||||
|
struct MemLogger_Header
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int mHead;
|
||||||
|
int mTail;
|
||||||
|
int mSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
MemLogger::MemLogger()
|
||||||
|
{
|
||||||
|
mFileMap = NULL;
|
||||||
|
mMemBuffer = NULL;
|
||||||
|
mBufferSize = 0;
|
||||||
|
mTotalWriteSize = 0;
|
||||||
|
mNoOverflow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemLogger::~MemLogger()
|
||||||
|
{
|
||||||
|
#ifdef BF_PLATFORM_WINDOWS
|
||||||
|
if (mMemBuffer != NULL)
|
||||||
|
::UnmapViewOfFile(mMemBuffer);
|
||||||
|
if (mFileMap != NULL)
|
||||||
|
::CloseHandle(mFileMap);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemLogger::Write(const void* ptr, int size)
|
||||||
|
{
|
||||||
|
if (mMemBuffer == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int dataSize = mBufferSize - sizeof(MemLogger_Header);
|
||||||
|
void* dataPtr = (uint8*)mMemBuffer + sizeof(MemLogger_Header);
|
||||||
|
|
||||||
|
if (mNoOverflow)
|
||||||
|
size = BF_MIN(size, dataSize - mTotalWriteSize - 1);
|
||||||
|
|
||||||
|
if (size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MemLogger_Header* header = (MemLogger_Header*)mMemBuffer;
|
||||||
|
|
||||||
|
bool wasWrapped = header->mHead < header->mTail;
|
||||||
|
|
||||||
|
int writeSize = BF_MIN(size, dataSize - header->mHead);
|
||||||
|
memcpy((char*)dataPtr + header->mHead, ptr, writeSize);
|
||||||
|
size -= writeSize;
|
||||||
|
|
||||||
|
header->mHead += writeSize;
|
||||||
|
while (header->mHead >= dataSize)
|
||||||
|
header->mHead -= dataSize;
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
int writeSize2 = BF_MIN(size, dataSize - header->mHead);
|
||||||
|
memcpy((char*)dataPtr + header->mHead, (char*)ptr + writeSize, writeSize2);
|
||||||
|
header->mHead += writeSize2;
|
||||||
|
while (header->mHead >= dataSize)
|
||||||
|
header->mHead -= dataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTotalWriteSize += writeSize;
|
||||||
|
|
||||||
|
if (mTotalWriteSize >= dataSize)
|
||||||
|
{
|
||||||
|
header->mTail = header->mHead + 1;
|
||||||
|
if (header->mTail > dataSize)
|
||||||
|
header->mTail -= dataSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Beefy::MemLogger::Create(const StringImpl& memName, int size)
|
||||||
|
{
|
||||||
|
#ifdef BF_PLATFORM_WINDOWS
|
||||||
|
String sharedName = "MemLogger_" + memName;
|
||||||
|
HANDLE hMapFile = CreateFileMappingA(
|
||||||
|
INVALID_HANDLE_VALUE, // use paging file
|
||||||
|
NULL, // default security
|
||||||
|
PAGE_READWRITE, // read/write access
|
||||||
|
0, // maximum object size (high-order DWORD)
|
||||||
|
size, // maximum object size (low-order DWORD)
|
||||||
|
sharedName.c_str()); // name of mapping object
|
||||||
|
|
||||||
|
if (hMapFile == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mMemBuffer = MapViewOfFile(hMapFile, // handle to map object
|
||||||
|
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
size);
|
||||||
|
|
||||||
|
if (mMemBuffer == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mBufferSize = size;
|
||||||
|
|
||||||
|
MemLogger_Header* header = (MemLogger_Header*)mMemBuffer;
|
||||||
|
header->mHead = 0;
|
||||||
|
header->mTail = 0;
|
||||||
|
header->mSize = size;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Beefy::MemLogger::Get(const StringImpl& memName, String& outStr)
|
||||||
|
{
|
||||||
|
#ifdef BF_PLATFORM_WINDOWS
|
||||||
|
String sharedName = "MemLogger_" + memName;
|
||||||
|
HANDLE hMapFile = ::OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, sharedName.c_str());
|
||||||
|
if (hMapFile == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
void* memPtr = MapViewOfFile(hMapFile, // handle to map object
|
||||||
|
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
sizeof(MemLogger_Header));
|
||||||
|
|
||||||
|
MemLogger_Header* header = (MemLogger_Header*)(memPtr);
|
||||||
|
int size = header->mSize;
|
||||||
|
UnmapViewOfFile(memPtr);
|
||||||
|
|
||||||
|
memPtr = MapViewOfFile(hMapFile, // handle to map object
|
||||||
|
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
size);
|
||||||
|
|
||||||
|
if (memPtr == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
::CloseHandle(hMapFile);
|
||||||
|
|
||||||
|
header = (MemLogger_Header*)(memPtr);
|
||||||
|
|
||||||
|
int dataSize = header->mSize - sizeof(MemLogger_Header);
|
||||||
|
void* dataPtr = (uint8*)memPtr + sizeof(MemLogger_Header);
|
||||||
|
|
||||||
|
if (header->mHead >= header->mTail)
|
||||||
|
{
|
||||||
|
// Not wrapped around
|
||||||
|
outStr.Insert(outStr.mLength, (char*)dataPtr + header->mTail, header->mHead - header->mTail);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outStr.Insert(outStr.mLength, (char*)dataPtr + header->mTail, dataSize - header->mTail);
|
||||||
|
outStr.Insert(outStr.mLength, (char*)dataPtr, header->mHead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Beefy::MemLogger::Log(const char* fmt ...)
|
||||||
|
{
|
||||||
|
if (mMemBuffer == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
StringT<4096> str;
|
||||||
|
va_list argList;
|
||||||
|
va_start(argList, fmt);
|
||||||
|
vformat(str, fmt, argList);
|
||||||
|
va_end(argList);
|
||||||
|
|
||||||
|
Write(str.c_str(), str.mLength);
|
||||||
|
}
|
29
BeefySysLib/util/MemLogger.h
Normal file
29
BeefySysLib/util/MemLogger.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Common.h"
|
||||||
|
|
||||||
|
NS_BF_BEGIN
|
||||||
|
|
||||||
|
class MemLogger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HANDLE mFileMap;
|
||||||
|
void* mMemBuffer;
|
||||||
|
int mBufferSize;
|
||||||
|
int mTotalWriteSize;
|
||||||
|
bool mNoOverflow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemLogger();
|
||||||
|
|
||||||
|
~MemLogger();
|
||||||
|
|
||||||
|
bool Create(const StringImpl& memName, int size);
|
||||||
|
bool Get(const StringImpl& memName, String& outStr);
|
||||||
|
void Log(const char* fmt ...);
|
||||||
|
void Write(const void* ptr, int size);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NS_BF_END
|
|
@ -119,13 +119,13 @@ typedef Rect<double> RectD;
|
||||||
typedef Rect<float> RectF;
|
typedef Rect<float> RectF;
|
||||||
typedef Rect<int32> RectI32;
|
typedef Rect<int32> RectI32;
|
||||||
|
|
||||||
|
NS_BF_END;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BeefHash<RectI32>
|
struct BeefHash<Beefy::RectI32>
|
||||||
{
|
{
|
||||||
size_t operator()(RectI32 val)
|
size_t operator()(Beefy::RectI32 val)
|
||||||
{
|
{
|
||||||
return (size_t)val.x * 4790557 + (size_t)val.y * 6578863 + (size_t)val.width * 6273881 + (size_t)val.height * 9501077;
|
return (size_t)val.x * 4790557 + (size_t)val.y * 6578863 + (size_t)val.width * 6273881 + (size_t)val.height * 9501077;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_BF_END;
|
|
|
@ -3461,6 +3461,8 @@ namespace IDE
|
||||||
delete mWorkspace.mDir;
|
delete mWorkspace.mDir;
|
||||||
mWorkspace.mDir = newPath;
|
mWorkspace.mDir = newPath;
|
||||||
}
|
}
|
||||||
|
else if (mWorkspace.mDir == null)
|
||||||
|
mWorkspace.mDir = new String();
|
||||||
|
|
||||||
List<String> platforms = scope List<String>();
|
List<String> platforms = scope List<String>();
|
||||||
if (IDEApp.sPlatform32Name != null)
|
if (IDEApp.sPlatform32Name != null)
|
||||||
|
|
|
@ -1179,14 +1179,18 @@ namespace IDE.ui
|
||||||
|
|
||||||
if (!docString.IsWhiteSpace)
|
if (!docString.IsWhiteSpace)
|
||||||
{
|
{
|
||||||
curY += font.GetLineSpacing() + GS!(4);
|
|
||||||
if (g != null)
|
if (g != null)
|
||||||
{
|
{
|
||||||
|
let docY = curY + font.GetLineSpacing() + GS!(4);
|
||||||
|
|
||||||
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mAutoCompleteDocText))
|
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mAutoCompleteDocText))
|
||||||
docHeight = g.DrawString(docString, curX, curY, .Left, maxDocWidth, .Wrap);
|
docHeight = g.DrawString(docString, curX, docY, .Left, maxDocWidth, .Wrap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
docHeight = font.GetWrapHeight(docString, maxDocWidth);
|
docHeight = font.GetWrapHeight(docString, maxDocWidth);
|
||||||
|
|
||||||
|
curY += docHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
extWidth = Math.Max(extWidth, Math.Min(font.GetWidth(docString), maxDocWidth) + GS!(48));
|
extWidth = Math.Max(extWidth, Math.Min(font.GetWidth(docString), maxDocWidth) + GS!(48));
|
||||||
|
|
|
@ -95,6 +95,8 @@ class GitManager
|
||||||
if (!File.Exists(gitPath))
|
if (!File.Exists(gitPath))
|
||||||
gitPath.Clear();
|
gitPath.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
psi.UseShellExecute = false;
|
||||||
#endif
|
#endif
|
||||||
if (gitPath.IsEmpty)
|
if (gitPath.IsEmpty)
|
||||||
gitPath.Set("git");
|
gitPath.Set("git");
|
||||||
|
@ -103,7 +105,6 @@ class GitManager
|
||||||
psi.SetArguments(mArgs);
|
psi.SetArguments(mArgs);
|
||||||
if (mPath != null)
|
if (mPath != null)
|
||||||
psi.SetWorkingDirectory(mPath);
|
psi.SetWorkingDirectory(mPath);
|
||||||
psi.UseShellExecute = false;
|
|
||||||
psi.RedirectStandardError = true;
|
psi.RedirectStandardError = true;
|
||||||
psi.RedirectStandardOutput = true;
|
psi.RedirectStandardOutput = true;
|
||||||
psi.CreateNoWindow = true;
|
psi.CreateNoWindow = true;
|
||||||
|
|
|
@ -179,7 +179,12 @@ namespace IDE.util
|
||||||
if (!CheckInit())
|
if (!CheckInit())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String beefBuildPath = scope $"{gApp.mInstallDir}BeefBuild.exe";
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
let ext = ".exe";
|
||||||
|
#else
|
||||||
|
let ext = "";
|
||||||
|
#endif
|
||||||
|
String beefBuildPath = scope $"{gApp.mInstallDir}BeefBuild{ext}";
|
||||||
String args = scope $"-run";
|
String args = scope $"-run";
|
||||||
var execInst = gApp.DoRun(beefBuildPath, args, path, .None);
|
var execInst = gApp.DoRun(beefBuildPath, args, path, .None);
|
||||||
execInst?.mAutoDelete = false;
|
execInst?.mAutoDelete = false;
|
||||||
|
|
|
@ -3296,6 +3296,9 @@ void BfAutoComplete::CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* pre
|
||||||
String filter;
|
String filter;
|
||||||
if (identifierNode != NULL)
|
if (identifierNode != NULL)
|
||||||
{
|
{
|
||||||
|
if (mModule->mCurMethodState == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((mModule->mCompiler->mResolvePassData != NULL) && (scopeData != NULL))
|
if ((mModule->mCompiler->mResolvePassData != NULL) && (scopeData != NULL))
|
||||||
{
|
{
|
||||||
auto rootMethodState = mModule->mCurMethodState->GetRootMethodState();
|
auto rootMethodState = mModule->mCurMethodState->GetRootMethodState();
|
||||||
|
|
|
@ -7223,14 +7223,32 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
||||||
|
|
||||||
//HashSet<BfTypeDef*> internalTypeDefs;
|
//HashSet<BfTypeDef*> internalTypeDefs;
|
||||||
|
|
||||||
|
BfProject* corlibProject = NULL;
|
||||||
|
|
||||||
auto _GetRequiredType = [&](const StringImpl& typeName, int genericArgCount = 0)
|
auto _GetRequiredType = [&](const StringImpl& typeName, int genericArgCount = 0)
|
||||||
{
|
{
|
||||||
auto typeDef = mSystem->FindTypeDef(typeName, genericArgCount);
|
BfTypeDef* ambigiousTypeDef = NULL;
|
||||||
|
auto typeDef = mSystem->FindTypeDef(typeName, genericArgCount, NULL, {}, &ambigiousTypeDef);
|
||||||
if (typeDef == NULL)
|
if (typeDef == NULL)
|
||||||
{
|
{
|
||||||
mPassInstance->Fail(StrFormat("Unable to find system type: %s", typeName.c_str()));
|
mPassInstance->Fail(StrFormat("Unable to find system type: %s", typeName.c_str()));
|
||||||
mHasRequiredTypes = false;
|
mHasRequiredTypes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ambigiousTypeDef != NULL)
|
||||||
|
{
|
||||||
|
mPassInstance->Fail(StrFormat("Found multiple declarations of require type '%s'", typeName.c_str()), typeDef->GetRefNode());
|
||||||
|
mPassInstance->MoreInfo("See additional declaration", ambigiousTypeDef->GetRefNode());
|
||||||
|
if (typeDef->mProject != corlibProject)
|
||||||
|
{
|
||||||
|
auto rootTypeDef = mSystem->FindTypeDef(typeName, genericArgCount, corlibProject);
|
||||||
|
if (rootTypeDef != NULL)
|
||||||
|
typeDef = rootTypeDef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corlibProject == NULL)
|
||||||
|
corlibProject = typeDef->mProject;
|
||||||
return typeDef;
|
return typeDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7125,7 +7125,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
|
|
||||||
if (mDeferCallData != NULL)
|
if (mDeferCallData != NULL)
|
||||||
{
|
{
|
||||||
if (mDeferCallData->mFuncAlloca_Orig == func)
|
if ((func) && (mDeferCallData->mFuncAlloca_Orig == func))
|
||||||
mModule->AddDeferredCall(BfModuleMethodInstance(methodInstance, mDeferCallData->mFuncAlloca), irArgs, mDeferCallData->mScopeAlloc, mDeferCallData->mRefNode, bypassVirtual, false, true);
|
mModule->AddDeferredCall(BfModuleMethodInstance(methodInstance, mDeferCallData->mFuncAlloca), irArgs, mDeferCallData->mScopeAlloc, mDeferCallData->mRefNode, bypassVirtual, false, true);
|
||||||
else
|
else
|
||||||
mModule->AddDeferredCall(BfModuleMethodInstance(methodInstance, func), irArgs, mDeferCallData->mScopeAlloc, mDeferCallData->mRefNode, bypassVirtual);
|
mModule->AddDeferredCall(BfModuleMethodInstance(methodInstance, func), irArgs, mDeferCallData->mScopeAlloc, mDeferCallData->mRefNode, bypassVirtual);
|
||||||
|
@ -19701,7 +19701,7 @@ void BfExprEvaluator::DoInvocation(BfInvocationExpression* invocationExpr)
|
||||||
{
|
{
|
||||||
arrSize = constant->mInt32;
|
arrSize = constant->mInt32;
|
||||||
}
|
}
|
||||||
else
|
else if (constant->mConstType != BfConstType_Undef)
|
||||||
mModule->Fail("Non-negative integer expected", indexerExpr->mArguments[0]);
|
mModule->Fail("Non-negative integer expected", indexerExpr->mArguments[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,6 +552,31 @@ void BfIRCodeGen::FixValues(llvm::StructType* structType, llvm::SmallVector<llvm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfIRCodeGen::FixValues(llvm::StructType* structType, llvm::SmallVector<llvm::Constant*, 8>& values)
|
||||||
|
{
|
||||||
|
if (values.size() >= structType->getNumElements())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int readIdx = (int)values.size() - 1;
|
||||||
|
values.resize(structType->getNumElements());
|
||||||
|
for (int i = (int)values.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (values[readIdx]->getType() == structType->getElementType(i))
|
||||||
|
{
|
||||||
|
values[i] = values[readIdx];
|
||||||
|
readIdx--;
|
||||||
|
}
|
||||||
|
else if (structType->getElementType(i)->isArrayTy())
|
||||||
|
{
|
||||||
|
values[i] = llvm::ConstantAggregateZero::get(structType->getElementType(i));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BF_FATAL("Malformed structure values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BfIRCodeGen::FixIndexer(llvm::Value*& val)
|
void BfIRCodeGen::FixIndexer(llvm::Value*& val)
|
||||||
{
|
{
|
||||||
if ((int)val->getType()->getScalarSizeInBits() > mPtrSize * 8)
|
if ((int)val->getType()->getScalarSizeInBits() > mPtrSize * 8)
|
||||||
|
@ -1285,6 +1310,8 @@ void BfIRCodeGen::Read(BfIRTypedValue& typedValue, BfIRCodeGenEntry** codeGenEnt
|
||||||
}
|
}
|
||||||
else if (auto structType = llvm::dyn_cast<llvm::StructType>(type->mLLVMType))
|
else if (auto structType = llvm::dyn_cast<llvm::StructType>(type->mLLVMType))
|
||||||
{
|
{
|
||||||
|
FixValues(structType, values);
|
||||||
|
|
||||||
for (int i = 0; i < (int)values.size(); i++)
|
for (int i = 0; i < (int)values.size(); i++)
|
||||||
{
|
{
|
||||||
if (values[i]->getType() != structType->getElementType(i))
|
if (values[i]->getType() != structType->getElementType(i))
|
||||||
|
|
|
@ -178,6 +178,7 @@ public:
|
||||||
public:
|
public:
|
||||||
void InitTarget();
|
void InitTarget();
|
||||||
void FixValues(llvm::StructType* structType, llvm::SmallVector<llvm::Value*, 8>& values);
|
void FixValues(llvm::StructType* structType, llvm::SmallVector<llvm::Value*, 8>& values);
|
||||||
|
void FixValues(llvm::StructType* structType, llvm::SmallVector<llvm::Constant*, 8>& values);
|
||||||
void FixIndexer(llvm::Value*& val);
|
void FixIndexer(llvm::Value*& val);
|
||||||
void FixTypedValue(BfIRTypedValue& typedValue);
|
void FixTypedValue(BfIRTypedValue& typedValue);
|
||||||
BfTypeCode GetTypeCode(llvm::Type* type, bool isSigned);
|
BfTypeCode GetTypeCode(llvm::Type* type, bool isSigned);
|
||||||
|
|
|
@ -13415,6 +13415,8 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, const BfTypedValue& targe
|
||||||
}
|
}
|
||||||
if ((mCompiler->mOptions.mAllowHotSwapping) && (!mIsComptimeModule))
|
if ((mCompiler->mOptions.mAllowHotSwapping) && (!mIsComptimeModule))
|
||||||
bindFuncVal = mBfIRBuilder->RemapBindFunction(bindFuncVal);
|
bindFuncVal = mBfIRBuilder->RemapBindFunction(bindFuncVal);
|
||||||
|
if ((bindFuncVal.IsFake()) && (!mBfIRBuilder->mIgnoreWrites))
|
||||||
|
return GetDefaultValue(GetPrimitiveType(BfTypeCode_IntPtr));
|
||||||
return mBfIRBuilder->CreatePtrToInt(bindFuncVal, BfTypeCode_IntPtr);
|
return mBfIRBuilder->CreatePtrToInt(bindFuncVal, BfTypeCode_IntPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1837,6 +1837,8 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fail("Sized array type expected", typeRef);
|
Fail("Sized array type expected", typeRef);
|
||||||
|
AddErrorNode(typeRef);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ namespace Tests
|
||||||
|
|
||||||
interface ITest
|
interface ITest
|
||||||
{
|
{
|
||||||
|
void TestFunc();
|
||||||
static void Func();
|
static void Func();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +179,8 @@ namespace Tests
|
||||||
{
|
{
|
||||||
public static int sVal;
|
public static int sVal;
|
||||||
|
|
||||||
|
public void TestFunc() => Func();
|
||||||
|
|
||||||
public static void Func()
|
public static void Func()
|
||||||
{
|
{
|
||||||
sVal = 123;
|
sVal = 123;
|
||||||
|
@ -189,6 +192,12 @@ namespace Tests
|
||||||
if (func != null)
|
if (func != null)
|
||||||
defer:: func.Invoke();
|
defer:: func.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TestIFaceDefer()
|
||||||
|
{
|
||||||
|
ITest itest = scope Zoop();
|
||||||
|
defer itest.TestFunc();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int UseFunc0<T>(function int (T this, float f) func, T a, float b)
|
public static int UseFunc0<T>(function int (T this, float f) func, T a, float b)
|
||||||
|
@ -265,6 +274,10 @@ namespace Tests
|
||||||
Zoop.sVal = 0;
|
Zoop.sVal = 0;
|
||||||
Zoop.TestDefer();
|
Zoop.TestDefer();
|
||||||
Test.Assert(Zoop.sVal == 123);
|
Test.Assert(Zoop.sVal == 123);
|
||||||
|
|
||||||
|
Zoop.sVal = 0;
|
||||||
|
Zoop.TestIFaceDefer();
|
||||||
|
Test.Assert(Zoop.sVal == 123);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2660,8 +2660,15 @@ bool WinDebugger::DoUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_ASSERT(foundBreakpoint != NULL);
|
if (foundBreakpoint == NULL)
|
||||||
|
{
|
||||||
|
BfLogDbg("Unknown memory breakpoint hit %p\n", pcAddress);
|
||||||
|
mDebugManager->mOutMessages.push_back(StrFormat("memoryBreak %s", EncodeDataPtr(pcAddress, false).c_str()));
|
||||||
|
mRunState = RunState_Paused;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
DbgSubprogram* subprogram = mDebugTarget->FindSubProgram(pcAddress);
|
DbgSubprogram* subprogram = mDebugTarget->FindSubProgram(pcAddress);
|
||||||
if (CheckConditionalBreakpoint(foundBreakpoint, subprogram, pcAddress))
|
if (CheckConditionalBreakpoint(foundBreakpoint, subprogram, pcAddress))
|
||||||
{
|
{
|
||||||
|
@ -2680,6 +2687,7 @@ bool WinDebugger::DoUpdate()
|
||||||
ClearCallStack();
|
ClearCallStack();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((mRunState == RunState_DebugEval) && (mDebugEvalThreadInfo.mThreadId == mDebuggerWaitingThread->mThreadId))
|
if ((mRunState == RunState_DebugEval) && (mDebugEvalThreadInfo.mThreadId == mDebuggerWaitingThread->mThreadId))
|
||||||
{
|
{
|
||||||
|
@ -7507,7 +7515,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
|
||||||
String symbolName;
|
String symbolName;
|
||||||
addr_target offset;
|
addr_target offset;
|
||||||
DbgModule* dwarf;
|
DbgModule* dwarf;
|
||||||
static String demangledName;
|
String demangledName;
|
||||||
auto subProgram = mDebugTarget->FindSubProgram(funcPtr);
|
auto subProgram = mDebugTarget->FindSubProgram(funcPtr);
|
||||||
if (subProgram != NULL)
|
if (subProgram != NULL)
|
||||||
{
|
{
|
||||||
|
@ -7524,13 +7532,18 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
|
||||||
{
|
{
|
||||||
auto dbgModule = mDebugTarget->FindDbgModuleForAddress(funcPtr);
|
auto dbgModule = mDebugTarget->FindDbgModuleForAddress(funcPtr);
|
||||||
if (dbgModule != NULL)
|
if (dbgModule != NULL)
|
||||||
|
{
|
||||||
demangledName += dbgModule->GetLinkedModule()->mDisplayName + "!";
|
demangledName += dbgModule->GetLinkedModule()->mDisplayName + "!";
|
||||||
demangledName += StrFormat("0x%@", funcPtr);
|
demangledName += StrFormat("0x%@", funcPtr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!demangledName.IsEmpty())
|
||||||
|
{
|
||||||
retVal += " {";
|
retVal += " {";
|
||||||
retVal += demangledName;
|
retVal += demangledName;
|
||||||
retVal += "}";
|
retVal += "}";
|
||||||
|
}
|
||||||
retVal += "\n" + origValueType->ToString(language);
|
retVal += "\n" + origValueType->ToString(language);
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue