1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Merge remote-tracking branch 'upstream/master' into Yuvan/CustomBuildProperties

This commit is contained in:
LAPTOP-NV8MPI8C\Yuvan Wickramasinghe 2025-03-28 14:48:45 -07:00
commit 4b879670ca
No known key found for this signature in database
294 changed files with 15180 additions and 4106 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ SDL2.dll
*.vcxproj.user *.vcxproj.user
*/llvm-* */llvm-*
*/llvm_* */llvm_*
*/_llvm*
*/x64/* */x64/*
**/Debug/* **/Debug/*
**/Debug */* **/Debug */*

View file

@ -108,7 +108,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_18_1_4\llvm\include;..\extern\llvm_win64_18_1_4\include;..\extern\llvm-project_18_1_4\llvm\lib\Target;..\extern\llvm_win64_18_1_4\lib\Target\X86;..\extern\llvm-project_18_1_4\llvm\tools\clang\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_19_1_7\llvm\include;..\extern\llvm_win64_19_1_7\include;..\extern\llvm-project_19_1_7\llvm\lib\Target;..\extern\llvm_win64_19_1_7\lib\Target\X86;..\extern\llvm-project_19_1_7\llvm\tools\clang\include</AdditionalIncludeDirectories>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -152,7 +152,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_18_1_4\llvm\include;..\extern\llvm_win64_18_1_4\include;..\extern\llvm-project_18_1_4\llvm\lib\Target;..\extern\llvm_win64_18_1_4\lib\Target\X86;..\extern\llvm\tools\clang\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../;../IDEHelper;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_19_1_7\llvm\include;..\extern\llvm_win64_19_1_7\include;..\extern\llvm-project_19_1_7\llvm\lib\Target;..\extern\llvm_win64_19_1_7\lib\Target\X86;..\extern\llvm\tools\clang\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>

View file

@ -119,7 +119,7 @@ add_executable(${PROJECT_NAME}
${SRC_FILES} ${SRC_FILES}
) )
find_package(LLVM 18.1 CONFIG COMPONENTS) find_package(LLVM 19.1 CONFIG COMPONENTS)
if (LLVM_FOUND) if (LLVM_FOUND)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
@ -128,7 +128,7 @@ if (LLVM_FOUND)
include_directories(${LLVM_INCLUDE_DIRS}) include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS})
set(TARGET_LIBS_OS "-lLLVM-18") set(TARGET_LIBS_OS "-lLLVM-19")
else() else()
message(FATAL_ERROR "LLVM not found") message(FATAL_ERROR "LLVM not found")
endif() endif()

View file

@ -7,7 +7,7 @@ StartupObject = "BeefBuild.Program"
[Platform.Windows] [Platform.Windows]
Description = "BeefBuild" Description = "BeefBuild"
FileVersion = "0.43.5" FileVersion = "0.43.6"
[Configs.Debug.Win32] [Configs.Debug.Win32]
TargetName = "" TargetName = ""
@ -19,8 +19,8 @@ TargetName = "$(ProjectName)_d"
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib Rpcrt4.lib Ole32.lib" OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib Rpcrt4.lib Ole32.lib"
CLibType = "Dynamic" CLibType = "Dynamic"
BeefLibType = "DynamicDebug" BeefLibType = "DynamicDebug"
DebugCommandArguments = "-proddir=c:\\proj\\BeefTest update BeefProj1" DebugCommandArguments = "-run"
DebugWorkingDirectory = "c:\\beef\\ide" DebugWorkingDirectory = "c:\\proj\\BeefTest"
EnvironmentVars = ["_NO_DEBUG_HEAP=1"] EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
PreprocessorMacros = ["DEBUG", "CLI"] PreprocessorMacros = ["DEBUG", "CLI"]

View file

@ -25,6 +25,7 @@ namespace BeefBuild
public bool mWantsGenerate = false; public bool mWantsGenerate = false;
public bool mHandledVerb; public bool mHandledVerb;
public String mRunArgs ~ delete _; public String mRunArgs ~ delete _;
public String mStartingDirectory = new .() ~ delete _;
MainVerbState mMainVerbState; MainVerbState mMainVerbState;
/*void Test() /*void Test()
@ -57,6 +58,8 @@ namespace BeefBuild
public override void Init() public override void Init()
{ {
Directory.GetCurrentDirectory(mStartingDirectory);
GetVersionInfo(var exeTime); GetVersionInfo(var exeTime);
if (mVerbosity == .Default) if (mVerbosity == .Default)
@ -388,9 +391,9 @@ namespace BeefBuild
mFailed = true; mFailed = true;
} }
protected override void CompileFailed() protected override void CompileFailed(Stopwatch stopwatch)
{ {
base.CompileFailed(); base.CompileFailed(stopwatch);
mFailed = true; mFailed = true;
} }
@ -434,9 +437,6 @@ namespace BeefBuild
{ {
if ((mVerb == .Run) && (!mDidRun) && (!mFailed)) if ((mVerb == .Run) && (!mDidRun) && (!mFailed))
{ {
let curPath = scope String();
Directory.GetCurrentDirectory(curPath);
let workspaceOptions = gApp.GetCurWorkspaceOptions(); let workspaceOptions = gApp.GetCurWorkspaceOptions();
let options = gApp.GetCurProjectOptions(mWorkspace.mStartupProject); let options = gApp.GetCurProjectOptions(mWorkspace.mStartupProject);
let targetPaths = scope List<String>(); let targetPaths = scope List<String>();
@ -445,7 +445,7 @@ namespace BeefBuild
if (targetPaths.IsEmpty) if (targetPaths.IsEmpty)
return; return;
ExecutionQueueCmd executionCmd = QueueRun(targetPaths[0], mRunArgs ?? "", curPath); ExecutionQueueCmd executionCmd = QueueRun(targetPaths[0], mRunArgs ?? "", mStartingDirectory);
executionCmd.mRunFlags |= .NoRedirect; executionCmd.mRunFlags |= .NoRedirect;
executionCmd.mIsTargetRun = true; executionCmd.mIsTargetRun = true;
mDidRun = true; mDidRun = true;

View file

@ -31,7 +31,7 @@ namespace BeefBuild
//TestZip2(); //TestZip2();
String commandLine = scope String(); String commandLine = scope String();
commandLine.Join(" ", params args); commandLine.Join(" ", args);
BuildApp mApp = new BuildApp(); BuildApp mApp = new BuildApp();
mApp.ParseCommandLine(commandLine); mApp.ParseCommandLine(commandLine);

View file

@ -1,4 +1,5 @@
FileVersion = 1 FileVersion = 1
Dependencies = {corlib = "*", MiniZ = "*"}
[Project] [Project]
Name = "Beefy2D" Name = "Beefy2D"
@ -50,3 +51,7 @@ OtherLinkFlags = "$(LinkFlags) \"$(ProjectDir)/dist/BeefySysLib64.lib\""
CLibType = "Static" CLibType = "Static"
BeefLibType = "Static" BeefLibType = "Static"
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"] PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.dll\")", "CopyToDependents(\"$(ProjectDir)/dist/BeefySysLib64.pdb\")"]
[Configs.Release_NoLink.Win32]
OtherLinkFlags = ""
PreprocessorMacros = ["RELEASE", "BF32"]

View file

@ -332,6 +332,22 @@ namespace Beefy
} }
} }
public Point? CursorScreenPos
{
get
{
for (var window in mWindows)
{
if (var widgetWindow = window as WidgetWindow)
{
if (widgetWindow.mHasMouseInside)
return .(widgetWindow.mClientMouseX + widgetWindow.mClientX, widgetWindow.mClientMouseY + widgetWindow.mClientY);
}
}
return null;
}
}
public static void Startup(String[] args, Action startupCallback) public static void Startup(String[] args, Action startupCallback)
{ {
/*string[] newArgs = new string[args.Length + 1]; /*string[] newArgs = new string[args.Length + 1];

View file

@ -5,6 +5,7 @@ using System.Diagnostics;
using Beefy.gfx; using Beefy.gfx;
using Beefy.sys; using Beefy.sys;
using System.IO; using System.IO;
using Beefy.geom;
#if MONOTOUCH #if MONOTOUCH
using MonoTouch; using MonoTouch;
@ -109,7 +110,7 @@ namespace Beefy
public virtual void PreDraw(Graphics g) public virtual void PreDraw(Graphics g)
{ {
g.PushDrawLayer(mDefaultDrawLayer); g.PushDrawLayer(mDefaultDrawLayer);
} }
public virtual void PostDraw(Graphics g) public virtual void PostDraw(Graphics g)
@ -327,6 +328,9 @@ namespace Beefy
static void Static_NativeDragDropFileDelegate(void* window, char8* filePath) { GetBFWindow(window).DragDropFile(StringView(filePath)); } static void Static_NativeDragDropFileDelegate(void* window, char8* filePath) { GetBFWindow(window).DragDropFile(StringView(filePath)); }
#endif #endif
public Rect<int32> ClientRect => .(mClientX, mClientY, mClientWidth, mClientHeight);
public Rect<int32> WindowRect => .(mX, mY, mWindowWidth, mWindowHeight);
public this() public this()
{ {
} }
@ -480,6 +484,11 @@ namespace Beefy
BFWindow_Resize(mNativeWindow, (int32)x, (int32)y, (int32)width, (int32)height, (int32)showKind); BFWindow_Resize(mNativeWindow, (int32)x, (int32)y, (int32)width, (int32)height, (int32)showKind);
} }
public virtual void ResizeClient(int width, int height)
{
Resize(mX, mY, mWindowWidth + (width - mClientWidth), mWindowHeight + (height - mClientHeight));
}
public void SetForeground() public void SetForeground()
{ {
BFWindow_SetForeground(mNativeWindow); BFWindow_SetForeground(mNativeWindow);

View file

@ -6,6 +6,7 @@ using System.Threading;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Cryptography; using System.Security.Cryptography;
using Beefy.gfx;
namespace Beefy namespace Beefy
{ {
@ -21,8 +22,6 @@ namespace Beefy
public static float Deg2Rad = Math.PI_f / 180.0f; public static float Deg2Rad = Math.PI_f / 180.0f;
public static int32 Rand() public static int32 Rand()
{ {
return mRandom.NextI32(); return mRandom.NextI32();
@ -33,6 +32,12 @@ namespace Beefy
return (Rand() & 0xFFFFFF) / (float)0xFFFFFF; return (Rand() & 0xFFFFFF) / (float)0xFFFFFF;
} }
public static float RandFloatS()
{
#unwarn
return ((Rand() & 0x1FFFFFF) / (float)0xFFFFFF) - 1.0f;
}
public static float Interpolate(float left, float right, float pct) public static float Interpolate(float left, float right, float pct)
{ {
return left + (right - left) * pct; return left + (right - left) * pct;
@ -472,5 +477,12 @@ namespace Beefy
{ {
val = (float)Math.Round(val * scale); val = (float)Math.Round(val * scale);
} }
public static Image GetAnimFrame(Image[] images, float pct)
{
int frameNum = (int)(images.Count * (pct - 0.000001f));
frameNum %= images.Count;
return images[frameNum];
}
} }
} }

View file

@ -283,7 +283,7 @@ namespace Beefy.geom
public override void ToString(String str) public override void ToString(String str)
{ {
str.AppendF($"{Normal:{Normal} D:{D}}"); str.AppendF($"{{Normal:{Normal} D:{D}}}");
} }
#endregion #endregion

View file

@ -97,6 +97,14 @@ namespace Beefy.geom
public T CenterX => mX + mWidth / 2; public T CenterX => mX + mWidth / 2;
public T CenterY => mY + mHeight / 2; public T CenterY => mY + mHeight / 2;
public static Rect<T> operator implicit <TOther>(Rect<TOther> value)
where T : operator implicit TOther
where TOther : operator TOther + TOther, operator TOther - TOther, operator TOther * TOther, operator TOther / TOther, operator -TOther, operator TOther / int8, IIsNaN, operator implicit int8
where int : operator TOther <=> TOther
{
return .(value.mX, value.mY, value.mWidth, value.mHeight);
}
public this(T x = default, T y = default, T width = default, T height = default) public this(T x = default, T y = default, T width = default, T height = default)
{ {
mX = x; mX = x;
@ -236,6 +244,11 @@ namespace Beefy.geom
mHeight *= scaleY; mHeight *= scaleY;
} }
public void Scale(T scale) mut
{
Scale(scale, scale);
}
public void ScaleFrom(T scaleX, T scaleY, T centerX, T centerY) mut public void ScaleFrom(T scaleX, T scaleY, T centerX, T centerY) mut
{ {
Offset(-centerX, -centerY); Offset(-centerX, -centerY);
@ -249,6 +262,7 @@ namespace Beefy.geom
} }
} }
typealias RectI32 = Rect<int32>;
typealias Rect = Rect<float>; typealias Rect = Rect<float>;
typealias RectD = Rect<double>; typealias RectD = Rect<double>;
} }

View file

@ -46,6 +46,11 @@ namespace Beefy.geom
public Vector2 Normalized => Vector2(mX, mY)..Normalize(); public Vector2 Normalized => Vector2(mX, mY)..Normalize();
public bool IsLengthLess(float check)
{
return mX * mX + mY * mY < check * check;
}
public static Vector2 Normalize(Vector2 vector) public static Vector2 Normalize(Vector2 vector)
{ {
Vector2 newVec; Vector2 newVec;
@ -104,6 +109,11 @@ namespace Beefy.geom
return Vector2((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length); return Vector2((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
} }
public static Vector2 operator -(Vector2 vec1)
{
return Vector2(-vec1.mX, -vec1.mY);
}
public static Vector2 operator +(Vector2 vec1, Vector2 vec2) public static Vector2 operator +(Vector2 vec1, Vector2 vec2)
{ {
return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY); return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
@ -123,5 +133,10 @@ namespace Beefy.geom
{ {
return Vector2(vec1.mX / factor, vec1.mY / factor); return Vector2(vec1.mX / factor, vec1.mY / factor);
} }
public override void ToString(String strBuffer)
{
strBuffer.AppendF("{0:0.0#}, {1:0.0#}", mX, mY);
}
} }
} }

View file

@ -101,6 +101,8 @@ namespace Beefy.geom
} }
} }
public Vector2 XY => .(mX, mY);
public this(float x, float y, float z) public this(float x, float y, float z)
{ {
mX = x; mX = x;
@ -306,5 +308,7 @@ namespace Beefy.geom
{ {
str.AppendF("{0:0.0#}, {1:0.0#}, {2:0.0#}", mX, mY, mZ); str.AppendF("{0:0.0#}, {1:0.0#}, {2:0.0#}", mX, mY, mZ);
} }
public static Vector3 operator implicit(Vector2 vec) => .(vec.mX, vec.mY, 0);
} }
} }

View file

@ -13,6 +13,8 @@ namespace Beefy.gfx
#if !STUDIO_CLIENT #if !STUDIO_CLIENT
public class DrawLayer public class DrawLayer
{ {
public static List<DrawLayer> sDrawLayers = new .() ~ delete _;
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void* DrawLayer_Create(void* window); static extern void* DrawLayer_Create(void* window);
@ -33,10 +35,12 @@ namespace Beefy.gfx
public this(BFWindow window) public this(BFWindow window)
{ {
mNativeDrawLayer = DrawLayer_Create((window != null) ? (window.mNativeWindow) : null); mNativeDrawLayer = DrawLayer_Create((window != null) ? (window.mNativeWindow) : null);
sDrawLayers.Add(this);
} }
public ~this() public ~this()
{ {
sDrawLayers.Remove(this);
DrawLayer_Delete(mNativeDrawLayer); DrawLayer_Delete(mNativeDrawLayer);
} }

View file

@ -6,6 +6,7 @@ using Beefy.geom;
using Beefy.utils; using Beefy.utils;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using res;
namespace Beefy.gfx namespace Beefy.gfx
{ {
@ -36,6 +37,104 @@ namespace Beefy.gfx
public float mMaxWidth; public float mMaxWidth;
} }
public class FontEffect
{
public enum Kind
{
case None;
case Outline(float thickness, uint32 color);
}
public class EffectCharData
{
public Font.CharData mSrcCharData;
public Font.CharData mEffectCharData ~ delete _;
}
public class FontEntry
{
public Font mFont;
public ImageAtlas mAtlas = new ImageAtlas() ~ delete _;
public List<EffectCharData> mCharData = new .() ~ delete _;
}
public Kind mKind;
public String mEffectOptions = new .() ~ delete _;
public Dictionary<Font, FontEntry> mFontEntries = new .() ~ DeleteDictionaryAndValues!(_);
public Dictionary<Font.CharData, EffectCharData> mCharData = new .() ~ DeleteDictionaryAndValues!(_);
public this(Kind kind)
{
mKind = kind;
switch (mKind)
{
case .Outline(let thickness, let color):
mEffectOptions..Clear().AppendF(
$"""
Effect=Stroke
Size={thickness}
Color=#{color:X}
""");
default:
}
}
public ~this()
{
}
public Font.CharData Apply(Font font, Font.CharData charData)
{
EffectCharData effectCharData = null;
if (mCharData.TryAdd(charData, ?, var effectCharDataPtr))
{
effectCharData = new EffectCharData();
*effectCharDataPtr = effectCharData;
effectCharData.mSrcCharData = charData;
effectCharData.mEffectCharData = new .(charData);
}
else
{
return (*effectCharDataPtr).mEffectCharData;
}
FontEntry fontEntry = null;
if (mFontEntries.TryAdd(font, ?, var fontEntryPtr))
{
fontEntry = new .();
*fontEntryPtr = fontEntry;
}
else
fontEntry = *fontEntryPtr;
int32 ofsX = 0;
int32 ofsY = 0;
if (mKind case .Outline(let thickness, ?))
{
ofsX += (.)Math.Ceiling(thickness) + 2;
ofsY += (.)Math.Ceiling(thickness) + 2;
}
effectCharData.mEffectCharData.mXOffset -= ofsX;
effectCharData.mEffectCharData.mYOffset -= ofsY;
var effectImage = fontEntry.mAtlas.Alloc(charData.mImageSegment.mSrcWidth + ofsX * 2, charData.mImageSegment.mSrcHeight + ofsY * 2);
effectCharData.mEffectCharData.mImageSegment = effectImage;
effectCharData.mSrcCharData.mImageSegment.ApplyEffect(effectImage, mEffectOptions);
/*uint32 color = 0xFFFFFFFF;
effectImage.SetBits(0, 0, 1, 1, 1, &color);*/
return effectCharData.mEffectCharData;
}
public void Prepare(Font font, StringView str)
{
}
}
public class Font public class Font
{ {
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -89,6 +188,24 @@ namespace Beefy.gfx
public int32 mYOffset; public int32 mYOffset;
public int32 mXAdvance; public int32 mXAdvance;
public bool mIsCombiningMark; public bool mIsCombiningMark;
public this()
{
}
public this(CharData copyFrom)
{
mImageSegment = copyFrom.mImageSegment;
mX = copyFrom.mX;
mY = copyFrom.mY;
mWidth = copyFrom.mWidth;
mHeight = copyFrom.mHeight;
mXOffset = copyFrom.mXOffset;
mYOffset = copyFrom.mYOffset;
mXAdvance = copyFrom.mXAdvance;
mIsCombiningMark = copyFrom.mIsCombiningMark;
}
} }
public class Page public class Page
@ -139,6 +256,9 @@ namespace Beefy.gfx
//BitmapFont mBMFont ~ delete _; //BitmapFont mBMFont ~ delete _;
public StringView mEllipsis = "..."; public StringView mEllipsis = "...";
List<FontEffect> mFontEffectStack ~ delete _;
DisposeProxy mFontEffectDisposeProxy = new .(new () => { PopFontEffect(); }) ~ delete _;
public this() public this()
{ {
} }
@ -153,6 +273,19 @@ namespace Beefy.gfx
FTFont_ClearCache(); FTFont_ClearCache();
} }
public DisposeProxy PushFontEffect(FontEffect fontEffect)
{
if (mFontEffectStack == null)
mFontEffectStack = new .();
mFontEffectStack.Add(fontEffect);
return mFontEffectDisposeProxy;
}
public void PopFontEffect()
{
mFontEffectStack.PopBack();
}
static void BuildFontNameCache() static void BuildFontNameCache()
{ {
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS
@ -383,6 +516,14 @@ namespace Beefy.gfx
void GetFontPath(StringView fontName, String path) void GetFontPath(StringView fontName, String path)
{ {
if (fontName.StartsWith('['))
{
path.Set(fontName);
if (FilePackManager.TryMakeMemoryString(path))
return;
path.Clear();
}
if (fontName.Contains('.')) if (fontName.Contains('.'))
{ {
Path.GetAbsolutePath(fontName, BFApp.sApp.mInstallDir, path); Path.GetAbsolutePath(fontName, BFApp.sApp.mInstallDir, path);
@ -666,13 +807,23 @@ namespace Beefy.gfx
mLowCharData[(int)checkChar] = charData; mLowCharData[(int)checkChar] = charData;
else else
mCharData[checkChar] = charData; mCharData[checkChar] = charData;
return charData; break;
} }
}
if (charData == null)
{
if (checkChar == (char32)'?') if (checkChar == (char32)'?')
return null; return null;
return GetCharData((char32)'?'); return GetCharData((char32)'?');
} }
if (mFontEffectStack?.IsEmpty == false)
{
var fontEffect = mFontEffectStack.Back;
charData = fontEffect.Apply(this, charData);
}
return charData; return charData;
} }
@ -828,10 +979,10 @@ namespace Beefy.gfx
} }
} }
public void Draw(Graphics g, StringView theString, FontMetrics* fontMetrics = null) public void Draw(Graphics g, float x, float y, StringView theString, FontMetrics* fontMetrics = null)
{ {
float curX = 0; float curX = x;
float curY = 0; float curY = y;
Matrix newMatrix = Matrix(); Matrix newMatrix = Matrix();
bool hasClipRect = g.mClipRect.HasValue; bool hasClipRect = g.mClipRect.HasValue;
@ -839,7 +990,10 @@ namespace Beefy.gfx
uint32 color = g.mColor; uint32 color = g.mColor;
g.PushTextRenderState(); bool usingTextRenderState = mFontEffectStack?.IsEmpty != false;
if (usingTextRenderState)
g.PushTextRenderState();
float markTopOfs = 0; float markTopOfs = 0;
float markBotOfs = 0; float markBotOfs = 0;
@ -869,6 +1023,8 @@ namespace Beefy.gfx
} }
CharData charData = GetCharData(c); CharData charData = GetCharData(c);
if (charData == null)
continue;
float drawX = curX + charData.mXOffset; float drawX = curX + charData.mXOffset;
float drawY = curY + charData.mYOffset; float drawY = curY + charData.mYOffset;
@ -943,7 +1099,11 @@ namespace Beefy.gfx
prevChar = c; prevChar = c;
} }
g.PopRenderState(); if (usingTextRenderState)
g.PopRenderState();
if (fontMetrics != null)
fontMetrics.mMaxX = Math.Max(fontMetrics.mMaxX, curX);
} }
public float Draw(Graphics g, StringView theString, float x, float y, int32 justification = -1, float width = 0, FontOverflowMode stringEndMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null) public float Draw(Graphics g, StringView theString, float x, float y, int32 justification = -1, float width = 0, FontOverflowMode stringEndMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null)
@ -1060,14 +1220,11 @@ namespace Beefy.gfx
if (g != null) if (g != null)
{ {
using (g.PushTranslate(useX, useY)) Draw(g, useX, useY, workingStr, fontMetrics);
Draw(g, workingStr, fontMetrics);
}
else
{
if (fontMetrics != null)
fontMetrics.mMaxWidth = Math.Max(fontMetrics.mMaxWidth, GetWidth(workingStr));
} }
if (fontMetrics != null)
fontMetrics.mMaxWidth = Math.Max(fontMetrics.mMaxWidth, GetWidth(workingStr));
drawHeight += GetLineSpacing(); drawHeight += GetLineSpacing();
if (fontMetrics != null) if (fontMetrics != null)

View file

@ -547,6 +547,11 @@ namespace Beefy.gfx
(int)mPixelSnapping, mSmoothing ? 1 : 0, mAdditive ? 1 : 0, (int)g.mColor);*/ (int)mPixelSnapping, mSmoothing ? 1 : 0, mAdditive ? 1 : 0, (int)g.mColor);*/
} }
public void DrawCentered(Image image, float x = 0, float y = 0)
{
Draw(image, x - image.mWidth / 2, y - image.mHeight / 2);
}
public void Draw(IDrawable drawable, Vector2 vec) => Draw(drawable, vec.mX, vec.mY); public void Draw(IDrawable drawable, Vector2 vec) => Draw(drawable, vec.mX, vec.mY);
public void DrawButton(Image image, float x, float y, float width) public void DrawButton(Image image, float x, float y, float width)
@ -924,6 +929,11 @@ namespace Beefy.gfx
FillRect(x, y + height - thickness, width, thickness); FillRect(x, y + height - thickness, width, thickness);
} }
public void OutlineRect(Rect rect)
{
OutlineRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
}
public void FillRectGradient(float x, float y, float width, float height, public void FillRectGradient(float x, float y, float width, float height,
Color colorTopLeft, Color colorTopRight, Color colorBotLeft, Color colorBotRight) Color colorTopLeft, Color colorTopRight, Color colorBotLeft, Color colorBotRight)
{ {
@ -943,6 +953,39 @@ namespace Beefy.gfx
Gfx_SetDrawVertex(5, m.tx + (m.a + m.c), m.ty + (m.b + m.d), 0, 0, 0, Color.Mult(mColor, colorBotRight)); Gfx_SetDrawVertex(5, m.tx + (m.a + m.c), m.ty + (m.b + m.d), 0, 0, 0, Color.Mult(mColor, colorBotRight));
} }
public void FillRectGradientEx(float x, float y, float width, float height,
Color colorTopLeft, Color colorTopRight, Color colorBotLeft, Color colorBotRight)
{
Matrix m = Matrix.IdentityMatrix;
m.SetMultiplied(x, y, width, height, ref mMatrix);
int32 r = ((int32)colorTopLeft.R + colorTopRight.R + colorBotLeft.R + colorBotRight.R) / 4;
int32 g = ((int32)colorTopLeft.G + colorTopRight.G + colorBotLeft.G + colorBotRight.G) / 4;
int32 b = ((int32)colorTopLeft.B + colorTopRight.B + colorBotLeft.B + colorBotRight.B) / 4;
int32 a = ((int32)colorTopLeft.A + colorTopRight.A + colorBotLeft.A + colorBotRight.A) / 4;
Color centerColor = .(r, g, b, a);
//TODO: Multiply color
Gfx_AllocTris(mWhiteDot.mNativeTextureSegment, 12);
Gfx_SetDrawVertex(0, m.tx, m.ty, 0, 0, 0, Color.Mult(mColor, colorTopLeft));
Gfx_SetDrawVertex(1, m.tx + m.a, m.ty + m.b, 0, 0, 0, Color.Mult(mColor, colorTopRight));
Gfx_SetDrawVertex(2, m.tx + (m.a + m.c) * 0.5f, m.ty + (m.b + m.d) * 0.5f, 0, 0, 0, Color.Mult(mColor, centerColor));
Gfx_CopyDrawVertex(3, 1); // Top Right
Gfx_SetDrawVertex(4, m.tx + (m.a + m.c), m.ty + (m.b + m.d), 0, 0, 0, Color.Mult(mColor, colorBotRight));
Gfx_CopyDrawVertex(5, 2); // Center
Gfx_CopyDrawVertex(6, 2); // Center
Gfx_CopyDrawVertex(7, 4); // Bottom Right
Gfx_SetDrawVertex(8, m.tx + m.c, m.ty + m.d, 0, 0, 0, Color.Mult(mColor, colorBotLeft));
Gfx_CopyDrawVertex(9, 8); // Bottom Left
Gfx_CopyDrawVertex(10, 0); // Top Left
Gfx_CopyDrawVertex(11, 2); // Center
}
void DoDrawLine(float x0, float y0, float x1, float y1, float width) void DoDrawLine(float x0, float y0, float x1, float y1, float width)
{ {
Image img = GetBorderedWhiteSquare(Math.Max((int)width, 1)); Image img = GetBorderedWhiteSquare(Math.Max((int)width, 1));

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Text; using System.Text;
using Beefy.utils; using Beefy.utils;
using System.Diagnostics; using System.Diagnostics;
using res;
#if STUDIO_CLIENT #if STUDIO_CLIENT
using Beefy.ipc; using Beefy.ipc;
@ -70,6 +71,9 @@ namespace Beefy.gfx
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern int32 Gfx_Texture_GetHeight(void* textureSegment); static extern int32 Gfx_Texture_GetHeight(void* textureSegment);
[CallingConvention(.Stdcall), CLink]
static extern void Gfx_ApplyEffect(void* destTextureSegment, void* srcTextureSegment, char8* options);
public this() public this()
{ {
} }
@ -94,11 +98,13 @@ namespace Beefy.gfx
return CreateFromNativeTextureSegment(aNativeTextureSegment); return CreateFromNativeTextureSegment(aNativeTextureSegment);
} }
public static Image LoadFromFile(String fileName, LoadFlags flags = .None) public static Image LoadFromFile(StringView fileName, LoadFlags flags = .None)
{ {
scope AutoBeefPerf("Image.LoadFromFile"); scope AutoBeefPerf("Image.LoadFromFile");
void* aNativeTextureSegment = Gfx_LoadTexture(fileName, (int32)flags); var useFileName = scope String()..Append(fileName);
FilePackManager.TryMakeMemoryString(useFileName);
void* aNativeTextureSegment = Gfx_LoadTexture(useFileName, (int32)flags);
if (aNativeTextureSegment == null) if (aNativeTextureSegment == null)
{ {
if (flags.HasFlag(.FatalError)) if (flags.HasFlag(.FatalError))
@ -186,6 +192,11 @@ namespace Beefy.gfx
Gfx_ModifyTextureSegment(mNativeTextureSegment, srcImage.mNativeTextureSegment, (int32)srcX, (int32)srcY, (int32)srcWidth, (int32)srcHeight); Gfx_ModifyTextureSegment(mNativeTextureSegment, srcImage.mNativeTextureSegment, (int32)srcX, (int32)srcY, (int32)srcWidth, (int32)srcHeight);
} }
public void ApplyEffect(Image destImage, StringView options)
{
Gfx_ApplyEffect(destImage.mNativeTextureSegment, mNativeTextureSegment, options.ToScopeCStr!());
}
public void SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits) public void SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{ {
Gfx_Texture_SetBits(mNativeTextureSegment, (.)destX, (.)destY, (.)destWidth, (.)destHeight, (.)srcPitch, bits); Gfx_Texture_SetBits(mNativeTextureSegment, (.)destX, (.)destY, (.)destWidth, (.)destHeight, (.)srcPitch, bits);

View file

@ -0,0 +1,66 @@
using System.Collections;
using System;
namespace Beefy.gfx;
class ImageAtlas
{
public class Page
{
public Image mImage ~ delete _;
public int32 mCurX;
public int32 mCurY;
public int32 mMaxRowHeight;
}
public List<Page> mPages = new .() ~ DeleteContainerAndItems!(_);
public bool mAllowMultiplePages = true;
public int32 mImageWidth = 1024;
public int32 mImageHeight = 1024;
public this()
{
}
public Image Alloc(int32 width, int32 height)
{
Page page = null;
if (!mPages.IsEmpty)
{
page = mPages.Back;
if (page.mCurX + (int)width > page.mImage.mSrcWidth)
{
// Move down to next row
page.mCurX = 0;
page.mCurY += page.mMaxRowHeight;
page.mMaxRowHeight = 0;
}
if (page.mCurY + height > page.mImage.mSrcHeight)
{
// Doesn't fit
page = null;
}
}
if (page == null)
{
page = new .();
page.mImage = Image.CreateDynamic(mImageWidth, mImageHeight);
uint32* colors = new uint32[mImageWidth*mImageHeight]*;
defer delete colors;
for (int i < mImageWidth*mImageHeight)
colors[i] = 0xFF000000 | (.)i;
page.mImage.SetBits(0, 0, mImageWidth, mImageHeight, mImageWidth, colors);
mPages.Add(page);
}
Image image = page.mImage.CreateImageSegment(page.mCurX, page.mCurY, width, height);
page.mCurX += width;
page.mMaxRowHeight = Math.Max(page.mMaxRowHeight, height);
return image;
}
}

View file

@ -168,6 +168,11 @@ namespace Beefy.gfx
return Point(tx + a * point.x + c * point.y, ty + b * point.x + d * point.y); return Point(tx + a * point.x + c * point.y, ty + b * point.x + d * point.y);
} }
public Vector2 Multiply(Vector2 point)
{
return Vector2(tx + a * point.mX + c * point.mY, ty + b * point.mX + d * point.mY);
}
public void Invert() mut public void Invert() mut
{ {
float _a = a; float _a = a;

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using res;
namespace Beefy.gfx namespace Beefy.gfx
{ {
@ -28,9 +29,22 @@ namespace Beefy.gfx
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern void* Gfx_GetShaderParam(void* shader, String paramName); static extern void* Gfx_GetShaderParam(void* shader, String paramName);
public static Shader CreateFromFile(String fileName, VertexDefinition vertexDefinition) public static Shader CreateFromFile(StringView fileName, VertexDefinition vertexDefinition)
{ {
void* aNativeShader = Gfx_LoadShader(fileName, vertexDefinition.mNativeVertexDefinition); var useFileName = scope String(fileName);
if (FilePackManager.TryMakeMemoryString(useFileName, ".fx_VS_vs_4_0"))
{
var useFileName2 = scope String(fileName);
if (FilePackManager.TryMakeMemoryString(useFileName2, ".fx_PS_ps_4_0"))
{
useFileName.Append("\n");
useFileName.Append(useFileName2);
}
}
FilePackManager.TryMakeMemoryString(useFileName, ".fx");
void* aNativeShader = Gfx_LoadShader(useFileName, vertexDefinition.mNativeVertexDefinition);
if (aNativeShader == null) if (aNativeShader == null)
return null; return null;

View file

@ -0,0 +1,592 @@
#pragma warning disable 168
using System;
using System.IO;
using System.Collections;
using utils;
namespace res;
class FilePack
{
public class FindFileData
{
public enum Flags
{
None = 0,
Files = 1,
Directories = 2,
}
public virtual bool MoveNext() => false;
public virtual void GetFileName(String outStr) {}
public virtual void GetFilePath(String outStr) {}
public virtual Platform.BfpTimeStamp GetWriteTime() => 0;
public virtual Platform.BfpTimeStamp GetCreatedTime() => 0;
public virtual Platform.BfpTimeStamp GetAccessTime() => 0;
public virtual Platform.BfpFileAttributes GetFileAttributes() => 0;
public virtual int64 GetFileSize() => 0;
}
public class FileEntry
{
public virtual void GetFilePath(String outFileName) {}
public virtual void GetFileName(String outFileName) {}
public virtual Result<Span<uint8>> GetFileData() => .Err;
public virtual FindFileData CreateFindFileData(StringView wildcard, FindFileData.Flags flags) => null;
public virtual Result<void> ExtractTo(StringView dest) => .Err;
}
public virtual StringView FilePath => default;
public virtual bool PathPackMatches(StringView path)
{
return false;
}
public virtual Stream OpenFile(StringView file)
{
return null;
}
public virtual FileEntry GetFileEntry(StringView path)
{
return null;
}
}
#if BF_DEPENDS_MINIZ
class ZipFilePack : FilePack
{
public class ZipFindFileData : FindFileData
{
public ZipFileEntry mZipFileEntry;
public int32 mIdx = -1;
public String mWildcard ~ delete _;
public Flags mFlags;
public override bool MoveNext()
{
while (true)
{
mIdx++;
if ((mZipFileEntry.mFiles == null) || (mIdx >= mZipFileEntry.mFiles.Count))
return false;
var fileName = GetFileName(.. scope .());
if (Path.WildcareCompare(fileName, mWildcard))
break;
}
return true;
}
public override void GetFilePath(String outFileName)
{
var fileEntry = mZipFileEntry.mFiles[mIdx];
fileEntry.mZipEntry.GetFileName(outFileName);
}
public override void GetFileName(String outFileName)
{
var fileEntry = mZipFileEntry.mFiles[mIdx];
var filePath = fileEntry.mZipEntry.GetFileName(.. scope .());
Path.GetFileName(filePath, outFileName);
}
public override Platform.BfpTimeStamp GetWriteTime()
{
return (.)mZipFileEntry.mFiles[mIdx].mZipEntry.GetTimestamp();
}
public override Platform.BfpTimeStamp GetCreatedTime()
{
return GetWriteTime();
}
public override Platform.BfpTimeStamp GetAccessTime()
{
return GetWriteTime();
}
public override Platform.BfpFileAttributes GetFileAttributes()
{
return .Normal;
}
public override int64 GetFileSize()
{
return mZipFileEntry.mFiles[mIdx].mZipEntry.GetUncompressedSize();
}
}
public class ZipFileEntry : FileEntry
{
public MiniZ.ZipFile.Entry mZipEntry ~ delete _;
public List<ZipFileEntry> mFiles ~ delete _;
public override Result<Span<uint8>> GetFileData()
{
return mZipEntry.ExtractToMemory();
}
public override FindFileData CreateFindFileData(StringView wildcard, FindFileData.Flags flags)
{
var findFileData = new ZipFindFileData();
findFileData.mZipFileEntry = this;
findFileData.mWildcard = new .(wildcard);
findFileData.mFlags = flags;
return findFileData;
}
public override Result<void> ExtractTo(StringView dest)
{
return mZipEntry.ExtractToFile(dest);
}
public override void GetFilePath(String outFileName)
{
mZipEntry.GetFileName(outFileName);
}
public override void GetFileName(String outFileName)
{
var filePath = mZipEntry.GetFileName(.. scope .());
Path.GetFileName(filePath, outFileName);
}
}
String mPath ~ delete _;
MiniZ.ZipFile mZipFile ~ delete _;
Dictionary<String, ZipFileEntry> mFileMap ~ DeleteDictionaryAndKeysAndValues!(_);
ZipFileEntry mRootFileEntry;
public List<ZipFileEntry> RootFiles
{
get
{
FillFileMap();
return mRootFileEntry.mFiles;
}
}
public this()
{
}
public override StringView FilePath => mPath;
public Result<void> Init(StringView path)
{
mPath = new .(path);
mZipFile = new MiniZ.ZipFile();
Try!(mZipFile.OpenMapped(path));
return .Ok;
}
public Result<void> Init(StringView path, Range range)
{
mPath = new .(path);
mZipFile = new MiniZ.ZipFile();
Try!(mZipFile.OpenMapped(path, range));
return .Ok;
}
public Result<void> Init(StringView path, Span<uint8> data)
{
mPath = new .(path);
mZipFile = new MiniZ.ZipFile();
Try!(mZipFile.Open(data));
return .Ok;
}
void FillFileMap()
{
if (mFileMap != null)
return;
mRootFileEntry = new .();
mRootFileEntry.mFiles = new .();
mFileMap = new .();
mFileMap[new .("/")] = mRootFileEntry;
for (int i < mZipFile.GetNumFiles())
{
var entry = new MiniZ.ZipFile.Entry();
mZipFile.SelectEntry(i, entry);
var fileName = entry.GetFileName(.. new .());
ZipFileEntry zipFileEntry = new .();
zipFileEntry.mZipEntry = entry;
mFileMap[fileName] = zipFileEntry;
var checkFileName = StringView(fileName);
if (checkFileName.EndsWith('/'))
checkFileName.RemoveFromEnd(1);
var fileDir = Path.GetDirectoryPath(checkFileName, .. scope .());
fileDir.Append("/");
if (mFileMap.TryGet(fileDir, ?, var dirEntry))
{
if (dirEntry.mFiles == null)
dirEntry.mFiles = new .();
dirEntry.mFiles.Add(zipFileEntry);
}
}
}
public override FileEntry GetFileEntry(StringView path)
{
var path;
FillFileMap();
if (path.StartsWith('/'))
path.RemoveFromStart(1);
if (path.Contains('\\'))
{
var pathStr = scope:: String(path);
pathStr.Replace('\\', '/');
path = pathStr;
}
if (mFileMap.TryGetAlt(path, ?, var entry))
return entry;
return null;
}
public override bool PathPackMatches(StringView path)
{
return Path.Equals(path, mPath);
}
public override Stream OpenFile(StringView file)
{
return base.OpenFile(file);
}
}
#endif
static class FilePackManager
{
public static List<FilePack> sFilePacks = new .() ~ DeleteContainerAndItems!(_);
public static void AddFilePack(FilePack filePack)
{
sFilePacks.Add(filePack);
}
public static void RemoveFilePack(FilePack filePack)
{
sFilePacks.Remove(filePack);
}
[StaticHook(typeof(Platform.Hook), typeof(FilePackManager.HookOverrides)), AlwaysInclude]
public static struct Hook
{
}
static StableIndexedList<Stream> sStreams = new .() ~ { DeleteContainerAndItems!(_); _ = null; }
static StableIndexedList<FilePack.FindFileData> sFindFileData = new .() ~ { DeleteContainerAndItems!(_); _ = null; }
static Stream TryGetStream(Platform.BfpFile* file, out int idx)
{
idx = (int)(void*)file;
return sStreams?.SafeGet(idx);
}
static FilePack.FindFileData TryGetFindFileData(Platform.BfpFindFileData* findFileData, out int idx)
{
idx = (int)(void*)findFileData;
return sFindFileData?.SafeGet(idx);
}
public static struct HookOverrides
{
[StaticHook]
public static Platform.BfpFile* BfpFile_Create(char8* name, Platform.BfpFileCreateKind createKind, Platform.BfpFileCreateFlags createFlags, Platform.BfpFileAttributes createdFileAttrs, Platform.BfpFileResult* outResult)
{
if ((createKind == .OpenExisting) && (!createFlags.HasFlag(.Write)))
{
if (var memory = TryGetMemory(.(name)))
{
var memoryStream = new FixedMemoryStream(memory);
return (.)(void*)sStreams.Add(memoryStream);
}
}
return Hook.sBfpFile_Create(name, createKind, createFlags, createdFileAttrs, outResult);
}
[StaticHook]
public static int BfpFile_GetSystemHandle(Platform.BfpFile* file)
{
return Hook.sBfpFile_GetSystemHandle(file);
}
[StaticHook]
public static void BfpFile_Release(Platform.BfpFile* file)
{
if (var stream = TryGetStream(file, var idx))
{
sStreams.RemoveAt(idx);
delete stream;
return;
}
Hook.sBfpFile_Release(file);
}
[StaticHook]
public static int BfpFile_Write(Platform.BfpFile* file, void* buffer, int size, int timeoutMS, Platform.BfpFileResult* outResult)
{
return Hook.sBfpFile_Write(file, buffer, size, timeoutMS, outResult);
}
[StaticHook]
public static int BfpFile_Read(Platform.BfpFile* file, void* buffer, int size, int timeoutMS, Platform.BfpFileResult* outResult)
{
if (var stream = TryGetStream(file, ?))
{
switch (stream.TryRead(.((.)buffer, size)))
{
case .Ok(let val):
if (val != size)
{
if (outResult != null)
*outResult = .PartialData;
}
else if (outResult != null)
*outResult = .Ok;
return val;
case .Err(let err):
if (outResult != null)
*outResult = .UnknownError;
return 0;
}
}
return Hook.sBfpFile_Read(file, buffer, size, timeoutMS, outResult);
}
[StaticHook]
public static void BfpFile_Flush(Platform.BfpFile* file)
{
if (var stream = TryGetStream(file, ?))
{
return;
}
Hook.sBfpFile_Flush(file);
}
[StaticHook]
public static int64 BfpFile_GetFileSize(Platform.BfpFile* file)
{
if (var stream = TryGetStream(file, ?))
{
return stream.Length;
}
return Hook.sBfpFile_GetFileSize(file);
}
[StaticHook]
public static int64 BfpFile_Seek(Platform.BfpFile* file, int64 offset, Platform.BfpFileSeekKind seekKind)
{
if (var stream = TryGetStream(file, ?))
{
stream.Seek(offset, (.)seekKind);
return stream.Position;
}
return Hook.sBfpFile_Seek(file, offset, seekKind);
}
[StaticHook]
public static void BfpFile_Truncate(Platform.BfpFile* file, Platform.BfpFileResult* outResult)
{
Hook.sBfpFile_Truncate(file, outResult);
}
[StaticHook]
public static Platform.BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, Platform.BfpFindFileFlags flags, Platform.BfpFileResult* outResult)
{
StringView pathStr = .(path);
String findDir = scope .();
Path.GetDirectoryPath(pathStr, findDir).IgnoreError();
findDir.Append("/");
String wildcard = scope .();
Path.GetFileName(pathStr, wildcard);
if (var packFile = FindFilePackEntry(findDir))
{
var packFindFile = packFile.CreateFindFileData(wildcard, (.)flags);
if (!packFindFile.MoveNext())
{
delete packFile;
if (outResult != null)
*outResult = .NoResults;
return null;
}
return (.)(void*)sFindFileData.Add(packFindFile);
}
return Hook.sBfpFindFileData_FindFirstFile(path, flags, outResult);
}
[StaticHook]
public static bool BfpFindFileData_FindNextFile(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.MoveNext();
}
return Hook.sBfpFindFileData_FindNextFile(findData);
}
[StaticHook]
public static void BfpFindFileData_GetFileName(Platform.BfpFindFileData* findData, char8* outName, int32* inOutNameSize, Platform.BfpFileResult* outResult)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
var str = packFindFile.GetFileName(.. scope .());
Platform.SetStrHelper(str, outName, inOutNameSize, (.)outResult);
return;
}
Hook.sBfpFindFileData_GetFileName(findData, outName, inOutNameSize, outResult);
}
[StaticHook]
public static Platform.BfpTimeStamp BfpFindFileData_GetTime_LastWrite(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.GetWriteTime();
}
return Hook.sBfpFindFileData_GetTime_LastWrite(findData);
}
[StaticHook]
public static Platform.BfpTimeStamp BfpFindFileData_GetTime_Created(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.GetCreatedTime();
}
return Hook.sBfpFindFileData_GetTime_Created(findData);
}
[StaticHook]
public static Platform.BfpTimeStamp BfpFindFileData_GetTime_Access(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.GetAccessTime();
}
return Hook.sBfpFindFileData_GetTime_Access(findData);
}
[StaticHook]
public static Platform.BfpFileAttributes BfpFindFileData_GetFileAttributes(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.GetFileAttributes();
}
return Hook.sBfpFindFileData_GetFileAttributes(findData);
}
[StaticHook]
public static int64 BfpFindFileData_GetFileSize(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, ?))
{
return packFindFile.GetFileSize();
}
return Hook.sBfpFindFileData_GetFileSize(findData);
}
[StaticHook]
public static void BfpFindFileData_Release(Platform.BfpFindFileData* findData)
{
if (var packFindFile = TryGetFindFileData(findData, var idx))
{
sFindFileData.RemoveAt(idx);
delete packFindFile;
return;
}
Hook.sBfpFindFileData_Release(findData);
}
}
public static FilePack.FileEntry FindFilePackEntry(StringView path)
{
if (path.StartsWith('['))
{
int packEndIdx = path.IndexOf(']');
if (packEndIdx != -1)
{
var packPath = path.Substring(1, packEndIdx - 1);
var filePath = path.Substring(packEndIdx + 1);
for (var filePack in sFilePacks)
{
if (filePack.PathPackMatches(packPath))
{
return filePack.GetFileEntry(filePath);
}
}
}
}
return null;
}
public static Result<Span<uint8>> TryGetMemory(StringView path)
{
var fileEntry = FindFilePackEntry(path);
if (fileEntry == null)
return .Err;
return fileEntry.GetFileData();
}
public static bool TryMakeMemoryString(String path)
{
if (TryGetMemory(path) case .Ok(let val))
{
String prevPath = scope .()..Append(path);
var ext = Path.GetExtension(path, .. scope .());
path.Set(scope $"@{(int)(void*)val.Ptr:X}:{val.Length}:{prevPath}");
return true;
}
return false;
}
public static bool TryMakeMemoryString(String path, params Span<StringView> checkExts)
{
var ext = Path.GetExtension(path, .. scope .());
if (!ext.IsEmpty)
return TryMakeMemoryString(path);
for (var checkExt in checkExts)
{
var testPath = scope String();
testPath.Append(path);
testPath.Append(checkExt);
if (TryMakeMemoryString(testPath))
{
path.Set(testPath);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,275 @@
#pragma warning disable 168
using System;
using System.IO;
namespace Beefy.Res;
static class PEFile
{
public const uint16 PE_MACHINE_X86 = 0x14c;
public const uint16 PE_MACHINE_X64 = 0x8664;
[CRepr]
public struct PEHeader
{
public uint16 e_magic; // Magic number
public uint16 e_cblp; // uint8s on last page of file
public uint16 e_cp; // Pages in file
public uint16 e_crlc; // Relocations
public uint16 e_cparhdr; // Size of header in paragraphs
public uint16 e_minalloc; // Minimum extra paragraphs needed
public uint16 e_maxalloc; // Maximum extra paragraphs needed
public uint16 e_ss; // Initial (relative) SS value
public uint16 e_sp; // Initial SP value
public uint16 e_csum; // Checksum
public uint16 e_ip; // Initial IP value
public uint16 e_cs; // Initial (relative) CS value
public uint16 e_lfarlc; // File address of relocation table
public uint16 e_ovno; // Overlay number
public uint16[4] e_res; // Reserved uint16s
public uint16 e_oemid; // OEM identifier (for e_oeminfo)
public uint16 e_oeminfo; // OEM information; e_oemid specific
public uint16[10] e_res2; // Reserved uint16s
public int32 e_lfanew; // File address of new exe header
};
[CRepr]
public struct PEFileHeader
{
public uint16 mMachine;
public uint16 mNumberOfSections;
public uint32 mTimeDateStamp;
public uint32 mPointerToSymbolTable;
public uint32 mNumberOfSymbols;
public uint16 mSizeOfOptionalHeader;
public uint16 mCharacteristics;
};
[CRepr]
public struct PEImportObjectHeader
{
public uint16 mSig1;
public uint16 mSig2;
public uint16 mVersion;
public uint16 mMachine;
public uint32 mTimeDateStamp;
public uint32 mDataSize;
public uint16 mHint;
public uint16 mType;
};
[CRepr]
public struct PEDataDirectory
{
public uint32 mVirtualAddress;
public uint32 mSize;
};
[CRepr]
public struct PEOptionalHeader32
{
//
// Standard fields.
//
public uint16 mMagic;
public uint8 mMajorLinkerVersion;
public uint8 mMinorLinkerVersion;
public uint32 mSizeOfCode;
public uint32 mSizeOfInitializedData;
public uint32 mSizeOfUninitializedData;
public uint32 mAddressOfEntryPoint;
public uint32 mBaseOfCode;
public uint32 mBaseOfData;
//
// NT additional fields.
//
public uint32 mImageBase;
public uint32 mSectionAlignment;
public uint32 mFileAlignment;
public uint16 mMajorOperatingSystemVersion;
public uint16 mMinorOperatingSystemVersion;
public uint16 mMajorImageVersion;
public uint16 mMinorImageVersion;
public uint16 mMajorSubsystemVersion;
public uint16 mMinorSubsystemVersion;
public uint32 mReserved1;
public uint32 mSizeOfImage;
public uint32 mSizeOfHeaders;
public uint32 mCheckSum;
public uint16 mSubsystem;
public uint16 mDllCharacteristics;
public uint32 mSizeOfStackReserve;
public uint32 mSizeOfStackCommit;
public uint32 mSizeOfHeapReserve;
public uint32 mSizeOfHeapCommit;
public uint32 mLoaderFlags;
public uint32 mNumberOfRvaAndSizes;
public PEDataDirectory[16] mDataDirectory;
};
[CRepr]
public struct PEOptionalHeader64
{
//
// Standard fields.
//
public uint16 mMagic;
public uint8 mMajorLinkerVersion;
public uint8 mMinorLinkerVersion;
public uint32 mSizeOfCode;
public uint32 mSizeOfInitializedData;
public uint32 mSizeOfUninitializedData;
public uint32 mAddressOfEntryPoint;
public uint32 mBaseOfCode;
//
// NT additional fields.
//
public uint64 mImageBase;
public uint32 mSectionAlignment;
public uint32 mFileAlignment;
public uint16 mMajorOperatingSystemVersion;
public uint16 mMinorOperatingSystemVersion;
public uint16 mMajorImageVersion;
public uint16 mMinorImageVersion;
public uint16 mMajorSubsystemVersion;
public uint16 mMinorSubsystemVersion;
public uint32 mReserved1;
public uint32 mSizeOfImage;
public uint32 mSizeOfHeaders;
public uint32 mCheckSum;
public uint16 mSubsystem;
public uint16 mDllCharacteristics;
public uint64 mSizeOfStackReserve;
public uint64 mSizeOfStackCommit;
public uint64 mSizeOfHeapReserve;
public uint64 mSizeOfHeapCommit;
public uint32 mLoaderFlags;
public uint32 mNumberOfRvaAndSizes;
public PEDataDirectory[16] mDataDirectory;
};
[CRepr]
struct PE_NTHeaders32
{
uint32 mSignature;
PEFileHeader mFileHeader;
PEOptionalHeader32 mOptionalHeader;
};
[CRepr]
public struct PE_NTHeaders64
{
public uint32 mSignature;
public PEFileHeader mFileHeader;
public PEOptionalHeader64 mOptionalHeader;
};
const int IMAGE_SIZEOF_SHORT_NAME = 8;
[CRepr]
public struct PESectionHeader
{
public char8[IMAGE_SIZEOF_SHORT_NAME] mName;
public uint32 mVirtualSize;
public uint32 mVirtualAddress;
public uint32 mSizeOfRawData;
public uint32 mPointerToRawData;
public uint32 mPointerToRelocations;
public uint32 mPointerToLineNumbers;
public uint16 mNumberOfRelocations;
public uint16 mNumberOfLineNumbers;
public uint32 mCharacteristics;
};
[CRepr]
struct COFFRelocation
{
uint32 mVirtualAddress;
uint32 mSymbolTableIndex;
uint16 mType;
};
[CRepr]
struct PE_SymInfo
{
[Union]
public struct Name
{
public char8[8] mName;
public int32[2] mNameOfs;
}
public Name mName;
/*union
{
char mName[8];
int32 mNameOfs[2];
};*/
public int32 mValue;
public uint16 mSectionNum;
public uint16 mType;
public int8 mStorageClass;
public int8 mNumOfAuxSymbols;
};
[CRepr]
struct PE_SymInfoAux
{
public uint32 mLength;
public uint16 mNumberOfRelocations;
public uint16 mNumberOfLinenumbers;
public uint32 mCheckSum;
public uint16 mNumber;
public uint8 mSelection;
public char8 mUnused;
public char8 mUnused2;
public char8 mUnused3;
};
public static Result<Range> LocateExtraFileInExecutable()
{
#if BF_PLATFORM_WINDOWS
var exePath = Environment.GetExecutableFilePath(.. scope .());
var exeFileInfo = scope FileInfo(exePath);
int fileLength = exeFileInfo.GetFileSize();
var moduleHandle = Windows.GetModuleHandleA(null);
uint8* modulePtr = (.)(void*)(int)moduleHandle;
PEFile.PEHeader* header = (.)modulePtr;
PEFile.PE_NTHeaders64* hdr64 = (.)(modulePtr + header.e_lfanew);
if (hdr64.mFileHeader.mMachine != PEFile.PE_MACHINE_X64)
return .Err;
int exeEnd = 0;
for (int sectIdx < hdr64.mFileHeader.mNumberOfSections)
{
PEFile.PESectionHeader* sectHdrHead = (.)(modulePtr + header.e_lfanew + sizeof(PEFile.PE_NTHeaders64) + sectIdx * sizeof(PEFile.PESectionHeader));
exeEnd = Math.Max(exeEnd, sectHdrHead.mPointerToRawData + sectHdrHead.mSizeOfRawData);
}
if (hdr64.mOptionalHeader.mDataDirectory[4].mVirtualAddress != 0)
{
// This handles the case where our installer is signed
fileLength = hdr64.mOptionalHeader.mDataDirectory[4].mVirtualAddress;
}
Range span = .(exeEnd, fileLength);
if (span.Length > 0)
return span;
#endif
return .Err;
}
}

View file

@ -14,7 +14,7 @@ namespace Beefy.theme.dark
public float mLabelYOfs; public float mLabelYOfs;
[DesignEditable(DefaultEditString=true)] [DesignEditable(DefaultEditString=true)]
public String Label public StringView Label
{ {
get get
{ {

View file

@ -121,7 +121,8 @@ namespace Beefy.theme.dark
{ {
g.SetFont(mFont); g.SetFont(mFont);
DarkTheme.DrawUnderlined(g, mLabel, GS!(22), GS!(-1)); using(g.PushColor(DarkTheme.COLOR_TEXT))
DarkTheme.DrawUnderlined(g, mLabel, GS!(22), GS!(-1));
/*int underlinePos = mLabel.IndexOf('&'); /*int underlinePos = mLabel.IndexOf('&');
if ((underlinePos != -1) && (underlinePos < mLabel.Length - 1)) if ((underlinePos != -1) && (underlinePos < mLabel.Length - 1))

View file

@ -119,7 +119,8 @@ namespace Beefy.theme.dark
g.SetFont(mFont); g.SetFont(mFont);
if (mText != null) if (mText != null)
g.DrawString(mText, mTextInsets.mLeft, mTextInsets.mTop, FontAlign.Left, mWidth - mTextInsets.Horz, FontOverflowMode.Wrap); using (g.PushColor(DarkTheme.COLOR_TEXT))
g.DrawString(mText, mTextInsets.mLeft, mTextInsets.mTop, FontAlign.Left, mWidth - mTextInsets.Horz, FontOverflowMode.Wrap);
} }
} }
} }

View file

@ -50,6 +50,7 @@ namespace Beefy.theme.dark
} }
public Font mFont; public Font mFont;
public float mLineHeightScale = 1.0f;
public uint32[] mTextColors = sDefaultColors; public uint32[] mTextColors = sDefaultColors;
public uint32 mHiliteColor = 0xFF2f5c88; public uint32 mHiliteColor = 0xFF2f5c88;
public uint32 mUnfocusedHiliteColor = 0x00000000; public uint32 mUnfocusedHiliteColor = 0x00000000;
@ -68,6 +69,8 @@ namespace Beefy.theme.dark
protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _; protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
public float LineHeight => Math.Max(Math.Round(mFont.GetLineSpacing() * mLineHeightScale), 1);
public this(EditWidgetContent refContent = null) : base(refContent) public this(EditWidgetContent refContent = null) : base(refContent)
{ {
//mTextInsets.Set(-3, 2, 0, 2); //mTextInsets.Set(-3, 2, 0, 2);
@ -79,6 +82,8 @@ namespace Beefy.theme.dark
mHeight = GS!(24); mHeight = GS!(24);
mHorzJumpSize = GS!(40); mHorzJumpSize = GS!(40);
mFont = DarkTheme.sDarkTheme?.mSmallFont; mFont = DarkTheme.sDarkTheme?.mSmallFont;
mTextColors[0] = DarkTheme.COLOR_TEXT;
mHiliteColor = DarkTheme.COLOR_TEXT_SELECTED;
} }
protected override EditWidgetContent.Data CreateEditData() protected override EditWidgetContent.Data CreateEditData()
@ -102,7 +107,7 @@ namespace Beefy.theme.dark
mLineCoords.GrowUninitialized(mData.mLineStarts.Count); mLineCoords.GrowUninitialized(mData.mLineStarts.Count);
mLineCoordJumpTable.Clear(); mLineCoordJumpTable.Clear();
float fontHeight = mFont.GetLineSpacing(); float fontHeight = LineHeight;
int prevJumpIdx = -1; int prevJumpIdx = -1;
float jumpCoordSpacing = GetJumpCoordSpacing(); float jumpCoordSpacing = GetJumpCoordSpacing();
@ -212,6 +217,13 @@ namespace Beefy.theme.dark
return defaultVal; return defaultVal;
} }
public float GetTextOffset()
{
float baseLineSpacing = mFont.GetLineSpacing();
float lineSpacing = LineHeight;
return lineSpacing / 2.0f - baseLineSpacing / 2.0f;
}
public int FindUncollapsedLine(int line) public int FindUncollapsedLine(int line)
{ {
var line; var line;
@ -507,7 +519,7 @@ namespace Beefy.theme.dark
((embed.mKind == .HideLine) && (!hideLine))) ((embed.mKind == .HideLine) && (!hideLine)))
selStartX += GS!(4); selStartX += GS!(4);
Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(1), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(3)); Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(1) + GetTextOffset(), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(3));
if (rect.mY < 0) if (rect.mY < 0)
rect.mY = 0; rect.mY = 0;
return rect; return rect;
@ -524,7 +536,9 @@ namespace Beefy.theme.dark
#unwarn #unwarn
int lineCount = GetLineCount(); int lineCount = GetLineCount();
float lineSpacing = mFont.GetLineSpacing(); float lineSpacing = LineHeight;
float fontLineSpacing = mFont.GetLineSpacing();
float textYOffset = GetTextOffset();
float offsetY = mTextInsets.mTop; float offsetY = mTextInsets.mTop;
if (mHeight < lineSpacing) if (mHeight < lineSpacing)
@ -563,7 +577,7 @@ namespace Beefy.theme.dark
{ {
if (mHiliteCurrentLine && selStartIdx == selEndIdx) if (mHiliteCurrentLine && selStartIdx == selEndIdx)
{ {
float thickness = 2 * (lineSpacing / 18); float thickness = Math.Ceiling(2 * (Math.Floor(fontLineSpacing) / 18));
// This isn't quite the right value, but I'm not sure how to get this // This isn't quite the right value, but I'm not sure how to get this
// to properly highlight the whole line without getting cut off - this works well for now. // to properly highlight the whole line without getting cut off - this works well for now.
float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness; float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness;
@ -594,18 +608,18 @@ namespace Beefy.theme.dark
if (mCharWidth <= 2) if (mCharWidth <= 2)
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f)))) using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f))))
g.FillRect(x, y, GS!(2), lineSpacing); g.FillRect(x, y + textYOffset, GS!(2), fontLineSpacing);
} }
else else
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f)))) using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f))))
g.FillRect(x, y, mCharWidth, lineSpacing); g.FillRect(x, y + textYOffset, mCharWidth, fontLineSpacing);
} }
} }
else else
{ {
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness)))) using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness))))
g.FillRect(x, y, Math.Max(1.0f, GS!(1)), lineSpacing); g.FillRect(x, y + textYOffset, Math.Max(1.0f, GS!(1)), fontLineSpacing);
} }
drewCursor = true; drewCursor = true;
} }
@ -699,7 +713,7 @@ namespace Beefy.theme.dark
} }
float nextX = curX; float nextX = curX;
nextX = DrawText(g, sectionText, curX, curY, curTypeIdAndFlags); nextX = DrawText(g, sectionText, curX, curY + textYOffset, curTypeIdAndFlags);
DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags); DrawSectionFlagsOver(g, curX, curY, nextX - curX, flags);
//int32 lineDrawStartColumn = lineDrawStart - lineStart; //int32 lineDrawStartColumn = lineDrawStart - lineStart;

View file

@ -978,7 +978,7 @@ namespace Beefy.theme.dark
public float mDragOffset = 0; public float mDragOffset = 0;
public bool mShowColumnGrid; public bool mShowColumnGrid;
public bool mShowGridLines; public bool mShowGridLines;
public Color mGridLinesColor = 0x0CFFFFFF; public Color mGridLinesColor;
public bool mShowHeader = true; public bool mShowHeader = true;
public bool mEndInEllipsis; public bool mEndInEllipsis;
public bool mWordWrap; public bool mWordWrap;
@ -1002,6 +1002,7 @@ namespace Beefy.theme.dark
{ {
mFont = DarkTheme.sDarkTheme.mSmallFont; mFont = DarkTheme.sDarkTheme.mSmallFont;
mBoldFont = DarkTheme.sDarkTheme.mSmallBoldFont; mBoldFont = DarkTheme.sDarkTheme.mSmallBoldFont;
mGridLinesColor = DarkTheme.COLOR_GRID;
SetShowHeader(true); SetShowHeader(true);
} }
@ -1028,6 +1029,12 @@ namespace Beefy.theme.dark
mScrollContentInsets.mBottom += GS!(2); mScrollContentInsets.mBottom += GS!(2);
base.InitScrollbars(wantHorz, wantVert); base.InitScrollbars(wantHorz, wantVert);
float scrollIncrement = this.mFont.GetLineSpacing();
if (mHorzScrollbar != null)
mHorzScrollbar.mScrollIncrement = scrollIncrement;
if (mVertScrollbar != null)
mVertScrollbar.mScrollIncrement = scrollIncrement;
} }
protected override ListViewItem CreateListViewItem() protected override ListViewItem CreateListViewItem()
@ -1087,7 +1094,7 @@ namespace Beefy.theme.dark
if ((mShowColumnGrid) && (columnIdx < mColumns.Count - 1)) if ((mShowColumnGrid) && (columnIdx < mColumns.Count - 1))
{ {
DrawColumnGridColumn(g, column.mWidth, DarkTheme.sUnitSize, mHeight - DarkTheme.sUnitSize - 1, 0xFF707070); DrawColumnGridColumn(g, column.mWidth, DarkTheme.sUnitSize, mHeight - DarkTheme.sUnitSize - 1, DarkTheme.COLOR_GRID);
} }
float sortArrowX = g.mFont.GetWidth(column.mLabel) + DarkTheme.sUnitSize/2; float sortArrowX = g.mFont.GetWidth(column.mLabel) + DarkTheme.sUnitSize/2;
@ -1146,7 +1153,7 @@ namespace Beefy.theme.dark
if ((mShowColumnGrid) && (columnIdx < mColumns.Count - 1)) if ((mShowColumnGrid) && (columnIdx < mColumns.Count - 1))
{ {
DrawColumnGridColumn(g, curX, GS!(4), mHeight - GS!(8), 0xFF888888); DrawColumnGridColumn(g, curX, GS!(4), mHeight - GS!(8), DarkTheme.COLOR_GRID);
} }
} }
} }

View file

@ -32,7 +32,7 @@ namespace Beefy.theme.dark
let darkMenuWidget = (DarkMenuWidget)mMenuWidget; let darkMenuWidget = (DarkMenuWidget)mMenuWidget;
g.SetFont(mMenuItem.mBold ? darkMenuWidget.mBoldFont : darkMenuWidget.mFont); g.SetFont(mMenuItem.mBold ? darkMenuWidget.mBoldFont : darkMenuWidget.mFont);
using (g.PushColor(mMenuItem.mDisabled ? 0xFFA8A8A8 : 0xFFFFFFFF)) using (g.PushColor(mMenuItem.mDisabled ? DarkTheme.COLOR_TEXT_DISABLED : DarkTheme.COLOR_TEXT))
{ {
StringView leftStr = mMenuItem.mLabel; StringView leftStr = mMenuItem.mLabel;
StringView rightStr = default; StringView rightStr = default;
@ -43,12 +43,9 @@ namespace Beefy.theme.dark
leftStr.RemoveToEnd(barIdx); leftStr.RemoveToEnd(barIdx);
} }
using (g.PushColor(DarkTheme.COLOR_TEXT)) g.DrawString(leftStr, GS!(36), 0);
{ if (!rightStr.IsEmpty)
g.DrawString(leftStr, GS!(36), 0); g.DrawString(rightStr, mWidth - GS!(8), 0, .Right);
if (!rightStr.IsEmpty)
g.DrawString(rightStr, mWidth - GS!(8), 0, .Right);
}
} }
if (mMenuItem.mIconImage != null) if (mMenuItem.mIconImage != null)
@ -57,7 +54,7 @@ namespace Beefy.theme.dark
if (mMenuItem.IsParent) if (mMenuItem.IsParent)
{ {
using (g.PushColor(mMenuItem.mDisabled ? 0xFFA8A8A8 : 0xFFFFFFFF)) using (g.PushColor(mMenuItem.mDisabled ? DarkTheme.COLOR_TEXT_DISABLED : DarkTheme.COLOR_TEXT))
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.RightArrow), mWidth - GS!(16), 0); g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.RightArrow), mWidth - GS!(16), 0);
} }
} }
@ -239,6 +236,20 @@ namespace Beefy.theme.dark
MarkDirty(); MarkDirty();
} }
} }
public override void InitScrollbars(bool wantHorz, bool wantVert)
{
base.InitScrollbars(wantHorz, wantVert);
float scrollIncrement = 0;
if (var darkMenuWidget = mScrollContent as DarkMenuWidget)
scrollIncrement = darkMenuWidget.mFont.GetLineSpacing();
if (mHorzScrollbar != null)
mHorzScrollbar.mScrollIncrement = scrollIncrement;
if (mVertScrollbar != null)
mVertScrollbar.mScrollIncrement = scrollIncrement;
}
} }
public class DarkMenuWidget : MenuWidget public class DarkMenuWidget : MenuWidget

View file

@ -197,7 +197,12 @@ namespace Beefy.theme.dark
}; };
public static uint32 COLOR_TEXT = 0xFFFFFFFF; public static uint32 COLOR_TEXT = 0xFFFFFFFF;
public static uint32 COLOR_TEXT_DISABLED = 0xFFA8A8A8;
public static uint32 COLOR_TEXT_SELECTED = 0xFF2f5c88;
public static uint32 COLOR_WINDOW = 0xFF595962; public static uint32 COLOR_WINDOW = 0xFF595962;
public static uint32 COLOR_DIALOG_OUTLINE_IN = 0xFF404040;
public static uint32 COLOR_DIALOG_OUTLINE_OUT = 0xFF202020;
public static uint32 COLOR_GRID = 0x0CFFFFFF;
public static uint32 COLOR_BKG = 0xFF26262A; public static uint32 COLOR_BKG = 0xFF26262A;
public static uint32 COLOR_SELECTED_OUTLINE = 0xFFCFAE11; public static uint32 COLOR_SELECTED_OUTLINE = 0xFFCFAE11;
public static uint32 COLOR_MENU_FOCUSED = 0xFFE5A910; public static uint32 COLOR_MENU_FOCUSED = 0xFFE5A910;

View file

@ -33,7 +33,7 @@ namespace Beefy.theme.dark
public bool mAllowResize; public bool mAllowResize;
public bool mHasClosed; public bool mHasClosed;
public Insets mRelWidgetMouseInsets ~ delete _; public Insets mRelWidgetMouseInsets ~ delete _;
public bool mAllowMouseInsideSelf; public Insets mAllowMouseInsideInsets ~ delete _;
public bool mAllowMouseOutside; public bool mAllowMouseOutside;
public int mAutoCloseDelay; public int mAutoCloseDelay;
public bool mIsClipped; public bool mIsClipped;
@ -96,6 +96,21 @@ namespace Beefy.theme.dark
Detach(); Detach();
} }
public static Point CalcSize(StringView text, float x = 0, float y = 0)
{
var font = DarkTheme.sDarkTheme.mSmallFont;
float minWidth = 0;
float minHeight = 0;
BFApp.sApp.GetWorkspaceRectFrom((.)x, (.)y, 0, 0, var workspaceX, var workspaceY, var workspaceWidth, var workspaceHeight);
FontMetrics fontMetrics = .();
float height = font.Draw(null, text, x, y, 0, 0, FontOverflowMode.Overflow, &fontMetrics);
float tooltipWidth = Math.Max(fontMetrics.mMaxWidth + GS!(32), minWidth);
float tooltipHeight = Math.Clamp(height + GS!(16), minHeight, workspaceHeight);
return .(tooltipWidth, tooltipHeight);
}
void Attach(Widget widget) void Attach(Widget widget)
{ {
if (mRelWidget != null) if (mRelWidget != null)
@ -162,7 +177,7 @@ namespace Beefy.theme.dark
int32 relX = x - mWidgetWindow.mX; int32 relX = x - mWidgetWindow.mX;
int32 relY = y - mWidgetWindow.mY; int32 relY = y - mWidgetWindow.mY;
if ((relX >= mWidgetWindow.mWindowWidth - GS!(18)) && (relY >= mWidgetWindow.mWindowHeight - GS!(18))) if ((relX >= mWidgetWindow.mWindowWidth - GS!(22)) && (relY >= mWidgetWindow.mWindowHeight - GS!(22)))
return BFWindowBase.HitTestResult.BottomRight; return BFWindowBase.HitTestResult.BottomRight;
return BFWindowBase.HitTestResult.Client; return BFWindowBase.HitTestResult.Client;
} }
@ -178,10 +193,13 @@ namespace Beefy.theme.dark
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Menu), 0, 0, mWidth, mHeight); g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Menu), 0, 0, mWidth, mHeight);
g.SetFont(mFont); g.SetFont(mFont);
if (mIsClipped) using (g.PushColor(DarkTheme.COLOR_TEXT))
g.DrawString(mText, GS!(8), GS!(5), .Left, mWidth - GS!(16), .Ellipsis); {
else if (mIsClipped)
g.DrawString(mText, 0, GS!(5), .Centered, mWidth); g.DrawString(mText, GS!(8), GS!(5), .Left, mWidth - GS!(16), .Ellipsis);
else
g.DrawString(mText, 0, GS!(5), .Centered, mWidth);
}
if (mAllowResize) if (mAllowResize)
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.ResizeGrabber), mWidth - GS!(22), mHeight - GS!(22)); g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.ResizeGrabber), mWidth - GS!(22), mHeight - GS!(22));
@ -248,21 +266,42 @@ namespace Beefy.theme.dark
if (mAllowMouseOutside) if (mAllowMouseOutside)
return; return;
Rect widgetRect = .(0, 0, mRelWidget.mWidth, mRelWidget.mHeight);
mRelWidgetMouseInsets?.ApplyTo(ref widgetRect);
float rootX; float rootX;
float rootY; float rootY;
mRelWidget.SelfToRootTranslate(0, 0, out rootX, out rootY); mRelWidget.SelfToRootTranslate(widgetRect.mX, widgetRect.mY, out rootX, out rootY);
Rect checkRect = Rect(rootX, rootY, mRelWidget.mWidth, mRelWidget.mHeight); Rect checkRect = Rect(rootX, rootY, widgetRect.mWidth, widgetRect.mHeight);
mRelWidgetMouseInsets?.ApplyTo(ref checkRect);
if ((mRelWidget.mWidgetWindow != null) && (mRelWidget.mWidgetWindow.mHasMouseInside)) if ((mRelWidget.mWidgetWindow != null) && (mRelWidget.mWidgetWindow.mHasMouseInside))
{ {
//checkRect.Inflate(8, 8);
if (checkRect.Contains(mRelWidget.mWidgetWindow.mClientMouseX, mRelWidget.mWidgetWindow.mClientMouseY)) if (checkRect.Contains(mRelWidget.mWidgetWindow.mClientMouseX, mRelWidget.mWidgetWindow.mClientMouseY))
return; return;
} }
if (mAllowMouseInsideInsets != null)
{
if (mWidgetWindow.mHasMouseInside)
return;
if ((mWidgetWindow.mHasMouseInside) && (mAllowMouseInsideSelf)) Rect<float> clientRect = mWidgetWindow.ClientRect;
return; mAllowMouseInsideInsets.ApplyTo(ref clientRect);
var cursorScreenPos = BFApp.sApp.CursorScreenPos;
if (cursorScreenPos != null)
{
if (clientRect.Contains((.)cursorScreenPos.Value.x, (.)cursorScreenPos.Value.y))
return;
}
NOP!();
/*var screenX = (int32)rootX + mWidgetWindow.mClientX;
var screenY = (int32)rootY + mWidgetWindow.mClientY;
if (clientRect.Contains(screenX, screenY))
return;*/
}
var checkWindow = BFApp.sApp.FocusedWindow; var checkWindow = BFApp.sApp.FocusedWindow;
if ((checkWindow != null) && (checkWindow.HasParent(mWidgetWindow))) if ((checkWindow != null) && (checkWindow.HasParent(mWidgetWindow)))
@ -423,15 +462,6 @@ namespace Beefy.theme.dark
SetLastMouseWidget(null); SetLastMouseWidget(null);
sMouseStillTicks = -1; sMouseStillTicks = -1;
} }
if (numOverWidgets > 1)
{
//int a = 0;
Debug.WriteLine("numOverWidgets > 1");
}
//Debug.Assert(numOverWidgets <= 1);
} }
} }
} }

View file

@ -0,0 +1,60 @@
using System.Collections;
namespace utils;
class StableIndexedList<T>
{
public List<T> mList = new .() ~ delete _;
public List<int32> mFreeIndices = new .() ~ delete _;
public this()
{
mList.Add(default); // Reserve idx 0
}
public ref T this[int idx]
{
get
{
return ref mList[idx];
}
set
{
mList[idx] = value;
}
}
public int Add(T val)
{
if (!mFreeIndices.IsEmpty)
{
int32 idx = mFreeIndices.PopBack();
mList[idx] = val;
return idx;
}
mList.Add(val);
return mList.Count - 1;
}
public void RemoveAt(int idx)
{
if (idx == mList.Count - 1)
{
mList.PopBack();
}
else
{
mList[idx] = default;
mFreeIndices.Add((.)idx);
}
}
public List<T>.Enumerator GetEnumerator() => mList.GetEnumerator();
public T SafeGet(int idx)
{
if ((idx < 0) || (idx > mList.Count))
return default;
return mList[idx];
}
}

View file

@ -322,6 +322,11 @@ namespace Beefy.widgets
mDefaultButton.MouseClicked(0, 0, 0, 0, 3); mDefaultButton.MouseClicked(0, 0, 0, 0, 3);
} }
public virtual void GenerateClipboardText(String outText)
{
outText.AppendF("{}\n{}", mTitle, mText);
}
void WindowKeyDown(KeyDownEvent evt) void WindowKeyDown(KeyDownEvent evt)
{ {
if ((evt.mKeyCode != .Alt) && (mWidgetWindow.IsKeyDown(.Alt)) && (!mWidgetWindow.IsKeyDown(.Control))) if ((evt.mKeyCode != .Alt) && (mWidgetWindow.IsKeyDown(.Alt)) && (!mWidgetWindow.IsKeyDown(.Control)))
@ -387,6 +392,29 @@ namespace Beefy.widgets
evt.mHandled = true; evt.mHandled = true;
} }
} }
if (evt.mKeyFlags.HasFlag(.Ctrl) && (evt.mKeyCode == (KeyCode)'C'))
{
ClipboardBlock: do
{
if (mChildWidgets != null)
{
for (var child in mChildWidgets)
{
if (child is ButtonWidget)
continue;
break ClipboardBlock;
}
}
var clipboardText = GenerateClipboardText(.. scope String());
if (!clipboardText.IsEmpty)
{
BFApp.sApp.SetClipboardText(clipboardText, "");
evt.mHandled = true;
}
}
}
} }
} }
} }

View file

@ -2836,7 +2836,7 @@ namespace Beefy.widgets
hi = i - 1; hi = i - 1;
} }
if (hi < GetLineCount()) if ((hi >= 0) && (hi < GetLineCount()))
{ {
line = (int32)hi; line = (int32)hi;
theChar = idx - mData.mLineStarts[hi]; theChar = idx - mData.mLineStarts[hi];

View file

@ -158,7 +158,7 @@ namespace Beefy.widgets
} }
} }
public void WithSelectedItems(delegate void(ListViewItem) func, bool skipSelectedChildrenOnSelectedItems = false, bool skipClosed = false) public void WithSelectedItems(delegate void(ListViewItem item) func, bool skipSelectedChildrenOnSelectedItems = false, bool skipClosed = false)
{ {
bool selfSelected = Selected; bool selfSelected = Selected;
if (selfSelected) if (selfSelected)
@ -907,6 +907,9 @@ namespace Beefy.widgets
{ {
base.KeyDown(keyCode, isRepeat); base.KeyDown(keyCode, isRepeat);
if (mWidgetWindow == null)
return;
switch (keyCode) switch (keyCode)
{ {
case (KeyCode)'A': case (KeyCode)'A':

View file

@ -633,7 +633,7 @@ namespace Beefy.widgets
if (targetWidget.mParent == mParent) if (targetWidget.mParent == mParent)
{ {
mParent.ParentToSelfTranslate(transX, transY, out transX, out transY); targetWidget.ParentToSelfTranslate(transX, transY, out transX, out transY);
return; return;
} }

View file

@ -69,6 +69,7 @@ namespace Beefy.widgets
public bool mWantsUpdateF; public bool mWantsUpdateF;
public bool mTempWantsUpdateF; public bool mTempWantsUpdateF;
public Image mContentRenderTarget ~ delete _;
public int32 mContentClientWidth; public int32 mContentClientWidth;
public int32 mContentClientHeight; public int32 mContentClientHeight;
@ -229,11 +230,31 @@ namespace Beefy.widgets
public override void PreDraw(Graphics g) public override void PreDraw(Graphics g)
{ {
base.PreDraw(g); base.PreDraw(g);
if (mContentRenderTarget != null)
{
g.mMatrix.Set(Matrix.IdentityMatrix);
}
else
{
g.mMatrix.Set(mScaleMatrix);
}
g.mMatrix.Set(mScaleMatrix);
g.mMatrixStack[g.mMatrixStackIdx] = g.mMatrix; g.mMatrixStack[g.mMatrixStackIdx] = g.mMatrix;
} }
public override void PostDraw(Graphics g)
{
base.PostDraw(g);
if (mContentRenderTarget != null)
{
for (var drawLayer in DrawLayer.sDrawLayers)
drawLayer.DrawToRenderTarget(mContentRenderTarget);
g.DrawQuad(mContentRenderTarget, 0, 0, 0, 0, mClientWidth, mClientHeight, 1, 1);
}
}
public override void RehupSize() public override void RehupSize()
{ {
base.RehupSize(); base.RehupSize();
@ -880,8 +901,14 @@ namespace Beefy.widgets
mMouseFlags = default; mMouseFlags = default;
} }
public void SetContentSize(int width, int height) public void SetContentSize(int width, int height, bool createRenderTarget = false)
{ {
DeleteAndNullify!(mContentRenderTarget);
if (createRenderTarget)
{
mContentRenderTarget = Image.CreateRenderTarget((.)width, (.)height);
}
mContentClientWidth = (.)width; mContentClientWidth = (.)width;
mContentClientHeight = (.)height; mContentClientHeight = (.)height;
RehupSize(); RehupSize();

View file

@ -2012,14 +2012,14 @@ namespace FMOD
return result; return result;
} }
public RESULT createSound (uint8[] data, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound) public RESULT createSound (Span<uint8> data, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound)
{ {
sound = null; sound = null;
exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO); exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO);
int soundraw; int soundraw;
RESULT result = FMOD_System_CreateSound(rawPtr, (char8*)&data[0], mode, ref exinfo, out soundraw); RESULT result = FMOD_System_CreateSound(rawPtr, (.)data.Ptr, mode, ref exinfo, out soundraw);
sound = new Sound(soundraw); sound = new Sound(soundraw);
return result; return result;

View file

@ -34,21 +34,91 @@ Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://ww
using System; using System;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using System.Collections;
#define TINFL_USE_64BIT_BITBUF #define TINFL_USE_64BIT_BITBUF
#define MINIZ_HAS_64BIT_REGISTERS #define MINIZ_HAS_64BIT_REGISTERS
#define MINIZ_LITTLE_ENDIAN #define MINIZ_LITTLE_ENDIAN
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES
#if BF_PLATFORM_WINDOWS
#define ALLOW_FILE_MAPPING
#endif
namespace MiniZ namespace MiniZ
{ {
class ZipFile class ZipFile
{ {
class RangeStream : Stream
{
public bool mOwnsStream;
public Stream mStream ~ { if (mOwnsStream) delete _; };
public Range mRange;
public override bool CanRead => mStream.CanRead;
public override bool CanWrite => mStream.CanWrite;
public override int64 Length => mRange.Length;
public override int64 Position
{
get
{
return mStream.Position - mRange.Start;
}
set
{
mStream.Position = value + mRange.Start;
}
}
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
{
//return mStream.Seek(pos, seekKind);
switch (seekKind)
{
case .Absolute:
return mStream.Seek(pos + mRange.Start, .Absolute);
case .Relative:
return mStream.Seek(pos, .Relative);
case .FromEnd:
return mStream.Seek(mRange.End - pos);
}
}
public override Result<int> TryRead(Span<uint8> data)
{
return mStream.TryRead(data);
}
public override Result<int, FileError> TryRead(Span<uint8> data, int timeoutMS)
{
return mStream.TryRead(data, timeoutMS);
}
public override Result<int> TryWrite(Span<uint8> data)
{
return mStream.TryWrite(data);
}
public override Result<void> Close()
{
return mStream.Close();
}
public override Result<void> Flush()
{
return mStream.Flush();
}
}
public class Entry public class Entry
{ {
ZipFile mZipFile; ZipFile mZipFile;
MiniZ.ZipArchiveFileStat mFileStat; MiniZ.ZipArchiveFileStat mFileStat;
int32 mFileIdx; int32 mFileIdx;
Span<uint8> mAllocatedData ~ delete mAllocatedData.Ptr;
public bool IsDirectory public bool IsDirectory
{ {
@ -65,6 +135,17 @@ namespace MiniZ
return .Ok; return .Ok;
} }
public Result<Span<uint8>> ExtractToMemory()
{
if (mAllocatedData.IsEmpty)
{
mAllocatedData = .(new uint8[mFileStat.mUncompSize]*, mFileStat.mUncompSize);
if (!MiniZ.ZipReaderExtractToMem(&mZipFile.[Friend]mFile, mFileIdx, mAllocatedData.Ptr, mAllocatedData.Length, .None))
return .Err;
}
return .Ok(mAllocatedData);
}
int GetStrLen(char8* ptr, int max) int GetStrLen(char8* ptr, int max)
{ {
int i = 0; int i = 0;
@ -97,10 +178,27 @@ namespace MiniZ
outComment.Append(&mFileStat.mComment, GetStrLen(&mFileStat.mComment, mFileStat.mComment.Count)); outComment.Append(&mFileStat.mComment, GetStrLen(&mFileStat.mComment, mFileStat.mComment.Count));
return .Ok; return .Ok;
} }
public DateTime GetDateTime()
{
int64 time = (int64)mFileStat.mTime * 10000000L + 116444736000000000L;
return DateTime(time);
}
public Platform.BfpTimeStamp GetTimestamp()
{
return (.)(mFileStat.mTime * 10000000L + 116444736000000000L);
}
} }
MiniZ.ZipArchive mFile; MiniZ.ZipArchive mFile;
bool mInitialized; bool mInitialized;
#if ALLOW_FILE_MAPPING
Windows.FileHandle mShareFileHandle ~ _.Close();
Windows.Handle mShareFileMapping ~ _.Close();
Span<uint8> mMappedData;
#endif
Stream mOwnedStream ~ delete _;
public ~this() public ~this()
{ {
@ -117,6 +215,74 @@ namespace MiniZ
return .Ok; return .Ok;
} }
public Result<void> Open(StringView fileName, Range range)
{
Debug.Assert(!mInitialized);
FileStream fileStream = new FileStream();
if (fileStream.Open(fileName, .Read, .Read) case .Err)
{
delete fileStream;
return .Err;
}
RangeStream rangeStream = new RangeStream() { mStream = fileStream, mOwnsStream = true, mRange = range };
mOwnedStream = rangeStream;
if (!MiniZ.ZipReaderInitStream(&mFile, rangeStream, .None))
return .Err;
mInitialized = true;
return .Ok;
}
public Result<void> Open(Span<uint8> data)
{
Debug.Assert(!mInitialized);
if (!MiniZ.ZipReaderInitMem(&mFile, data.Ptr, data.Length, .None))
return .Err;
mInitialized = true;
return .Ok;
}
public Result<void> OpenMapped(StringView fileName)
{
#if ALLOW_FILE_MAPPING
mShareFileHandle = Windows.CreateFileA(fileName.ToScopeCStr!(), Windows.GENERIC_READ, .Read, null, .Open, 0, default);
uint32 sizeHigh = 0;
uint32 sizeLow = (.)Windows.GetFileSize(mShareFileHandle, (.)&sizeHigh);
mShareFileMapping = Windows.CreateFileMappingA(mShareFileHandle, null, Windows.PAGE_READONLY, sizeHigh, sizeLow, null);
mMappedData = .((.)Windows.MapViewOfFile(mShareFileMapping, Windows.FILE_MAP_READ, 0, 0, sizeLow), sizeLow);
Debug.Assert(!mInitialized);
if (!MiniZ.ZipReaderInitMem(&mFile, mMappedData.Ptr, mMappedData.Length, .None))
return .Err;
mInitialized = true;
return .Ok;
#else
return Open(fileName);
#endif
}
public Result<void> OpenMapped(StringView fileName, Range range)
{
#if ALLOW_FILE_MAPPING
mShareFileHandle = Windows.CreateFileA(fileName.ToScopeCStr!(), Windows.GENERIC_READ, .Read, null, .Open, 0, default);
uint32 sizeHigh = 0;
uint32 sizeLow = (.)range.End;
mShareFileMapping = Windows.CreateFileMappingA(mShareFileHandle, null, Windows.PAGE_READONLY, sizeHigh, sizeLow, null);
uint8* ptr = (.)Windows.MapViewOfFile(mShareFileMapping, Windows.FILE_MAP_READ, 0, 0, sizeLow);
mMappedData = .(ptr + range.Start, range.Length);
Debug.Assert(!mInitialized);
if (!MiniZ.ZipReaderInitMem(&mFile, mMappedData.Ptr, mMappedData.Length, .None))
return .Err;
mInitialized = true;
return .Ok;
#else
return Open(fileName, range);
#endif
}
public Result<void> Init(Stream stream) public Result<void> Init(Stream stream)
{ {
Debug.Assert(!mInitialized); Debug.Assert(!mInitialized);
@ -3115,7 +3281,7 @@ namespace MiniZ
return s; return s;
} }
static bool zip_reader_init_mem(ZipArchive* pZip, void* pMem, int size, ZipFlags flags) public static bool ZipReaderInitMem(ZipArchive* pZip, void* pMem, int size, ZipFlags flags)
{ {
if (!zip_reader_init_internal(pZip, flags)) if (!zip_reader_init_internal(pZip, flags))
return false; return false;

View file

@ -97,7 +97,7 @@ namespace System
} }
} }
struct AllocWrapper<T> where T : new, delete struct AllocWrapper<T> where T : new where alloctype(T) : delete
{ {
alloctype(T) mVal; alloctype(T) mVal;
public alloctype(T) Val public alloctype(T) Val

View file

@ -372,7 +372,7 @@ namespace System
[AttributeUsage(.Constructor)] [AttributeUsage(.Constructor)]
public struct AllowAppendAttribute : Attribute public struct AllowAppendAttribute : Attribute
{ {
public bool ZeroGap;
} }
[AttributeUsage(.Class | .Struct)] [AttributeUsage(.Class | .Struct)]

View file

@ -1245,7 +1245,7 @@ namespace System.Collections
public int32 GetHashKey(int hashCode) public int32 GetHashKey(int hashCode)
{ {
if (sizeof(int) == 4) if (sizeof(int) == 4)
return (int32)hashCode; return (int32)hashCode & 0x7FFFFFFF;
#unwarn #unwarn
return (int32)(hashCode ^ ((hashCode >> 31) * 1171)) & 0x7FFFFFFF; return (int32)(hashCode ^ ((hashCode >> 31) * 1171)) & 0x7FFFFFFF;
} }

View file

@ -63,7 +63,7 @@ namespace System
mCmdInfo.Append("\n"); mCmdInfo.Append("\n");
} }
public void AddEdit(StringView dataName, StringView label, StringView defaultValue) public void AddEdit(StringView dataName, StringView label, StringView defaultValue, bool focus = false)
{ {
mCmdInfo.AppendF($"addEdit\t"); mCmdInfo.AppendF($"addEdit\t");
dataName.QuoteString(mCmdInfo); dataName.QuoteString(mCmdInfo);
@ -71,7 +71,7 @@ namespace System
label.QuoteString(mCmdInfo); label.QuoteString(mCmdInfo);
mCmdInfo.Append("\t"); mCmdInfo.Append("\t");
defaultValue.QuoteString(mCmdInfo); defaultValue.QuoteString(mCmdInfo);
mCmdInfo.Append("\n"); mCmdInfo.AppendF($"\t{focus}\n");
} }
public void AddFilePath(StringView dataName, StringView label, StringView defaultValue) public void AddFilePath(StringView dataName, StringView label, StringView defaultValue)
@ -216,7 +216,7 @@ namespace System
public override void InitUI() public override void InitUI()
{ {
AddEdit("name", "Class Name", ""); AddEdit("name", "Class Name", "", true);
} }
public override void Generate(String outFileName, String outText, ref Flags generateFlags) public override void Generate(String outFileName, String outText, ref Flags generateFlags)
@ -225,10 +225,12 @@ namespace System
if (name.EndsWith(".bf", .OrdinalIgnoreCase)) if (name.EndsWith(".bf", .OrdinalIgnoreCase))
name.RemoveFromEnd(3); name.RemoveFromEnd(3);
outFileName.Append(name); outFileName.Append(name);
var ns = Namespace..Trim();
if (!ns.IsEmpty)
outText.AppendF($"namespace {Namespace};\n\n");
outText.AppendF( outText.AppendF(
$""" $"""
namespace {Namespace};
class {name} class {name}
{{ {{
}} }}
@ -334,6 +336,7 @@ namespace System
static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text); static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text);
static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text); static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text);
static extern void Comptime_EmitMixin(StringView text); static extern void Comptime_EmitMixin(StringView text);
static extern String Comptime_GetStringById(int32 id);
[Comptime(OnlyFromComptime=true)] [Comptime(OnlyFromComptime=true)]
public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags) public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags)

View file

@ -396,6 +396,7 @@ namespace System
{ {
sForegroundColor = sOriginalForegroundColor; sForegroundColor = sOriginalForegroundColor;
sBackgroundColor = sOriginalBackgroundColor; sBackgroundColor = sOriginalBackgroundColor;
SetColors();
#if !BF_PLATFORM_WINDOWS #if !BF_PLATFORM_WINDOWS
Write("\x1B[0m"); Write("\x1B[0m");

View file

@ -25,7 +25,7 @@ namespace System.Diagnostics
#if !DEBUG #if !DEBUG
[SkipCall] [SkipCall]
#endif #endif
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) public static void FatalError(StringView msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{ {
String failStr = scope .()..Append(msg, " at line "); String failStr = scope .()..Append(msg, " at line ");
line.ToString(failStr); line.ToString(failStr);
@ -44,10 +44,19 @@ namespace System.Diagnostics
#endif #endif
} }
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Write(char8* str, int strLen); static extern void Write(char8* str, int strLen);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Write(int val); static extern void Write(int val);
#else
static void Write(char8* str, int strLen)
{
}
static void Write(int val)
{
}
#endif
public static void Write(String line) public static void Write(String line)
{ {
@ -59,7 +68,7 @@ namespace System.Diagnostics
Write(sv.[Friend]mPtr, sv.[Friend]mLength); Write(sv.[Friend]mPtr, sv.[Friend]mLength);
} }
public static void Write(String fmt, params Span<Object> args) public static void Write(StringView fmt, params Span<Object> args)
{ {
String str = scope String(4096); String str = scope String(4096);
str.AppendF(fmt, params args); str.AppendF(fmt, params args);
@ -86,7 +95,7 @@ namespace System.Diagnostics
Write(lineStr.Ptr, lineStr.Length); Write(lineStr.Ptr, lineStr.Length);
} }
public static void WriteLine(StringView strFormat, params Object[] args) public static void WriteLine(StringView strFormat, params Span<Object> args)
{ {
String paramStr = scope String(4096); String paramStr = scope String(4096);
paramStr.AppendF(strFormat, params args); paramStr.AppendF(strFormat, params args);

View file

@ -1,6 +1,6 @@
namespace System.FFI namespace System.FFI
{ {
[CRepr, StaticInitPriority(100)] [CRepr, StaticInitPriority(200)]
struct FFIType struct FFIType
{ {
public enum TypeKind : uint16 public enum TypeKind : uint16

View file

@ -108,6 +108,8 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
private extern static void Init(); private extern static void Init();
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public extern static void Disable();
[CallingConvention(.Cdecl)]
public extern static void Collect(bool async = true); public extern static void Collect(bool async = true);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
private extern static void StopCollecting(); private extern static void StopCollecting();
@ -136,6 +138,7 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public extern static void ExcludeThreadId(int thereadId); public extern static void ExcludeThreadId(int thereadId);
#else #else
public static void Disable() {}
public static void Collect(bool async = true) {} public static void Collect(bool async = true) {}
private static void MarkAllStaticMembers() {} private static void MarkAllStaticMembers() {}
public static void DebugDumpLeaks() {} public static void DebugDumpLeaks() {}

View file

@ -38,7 +38,7 @@ namespace System.IO
public ~this() public ~this()
{ {
Flush(); FlushBuffer();
} }
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute) public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
@ -84,7 +84,7 @@ namespace System.IO
data.RemoveFromStart((.)spaceLeft); data.RemoveFromStart((.)spaceLeft);
} }
Try!(Flush()); Try!(FlushBuffer());
if ((mBuffer == null) || (data.Length > mBuffer.Count)) if ((mBuffer == null) || (data.Length > mBuffer.Count))
{ {
@ -114,7 +114,7 @@ namespace System.IO
if ((mWriteDirtyEnd >= 0) && (mWriteDirtyEnd != mPos)) if ((mWriteDirtyEnd >= 0) && (mWriteDirtyEnd != mPos))
{ {
Try!(Flush()); Try!(FlushBuffer());
} }
int writeCount = 0; int writeCount = 0;
@ -138,7 +138,7 @@ namespace System.IO
} }
} }
Try!(Flush()); Try!(FlushBuffer());
if ((mBuffer == null) || (data.Length > mBuffer.Count)) if ((mBuffer == null) || (data.Length > mBuffer.Count))
{ {
@ -158,7 +158,7 @@ namespace System.IO
return writeCount; return writeCount;
} }
public override Result<void> Flush() protected Result<void> FlushBuffer()
{ {
if (mWriteDirtyPos >= 0) if (mWriteDirtyPos >= 0)
{ {
@ -170,9 +170,14 @@ namespace System.IO
return .Ok; return .Ok;
} }
public override Result<void> Flush()
{
return FlushBuffer();
}
public override Result<void> Close() public override Result<void> Close()
{ {
let ret = Flush(); let ret = FlushBuffer();
mPos = 0; mPos = 0;
mBufferPos = -Int32.MinValue; mBufferPos = -Int32.MinValue;

View file

@ -135,7 +135,7 @@ namespace System.IO
bfpFlags |= .Directories; bfpFlags |= .Directories;
if (flags.HasFlag(.Files)) if (flags.HasFlag(.Files))
bfpFlags |= .Files; bfpFlags |= .Files;
let findFileData = Platform.BfpFindFileData_FindFirstFile(useStr, bfpFlags, null); let findFileData = Platform.Hook.BfpFindFileData_FindFirstFile(useStr, bfpFlags, null);
return FileEnumerator(useStr, findFileData); return FileEnumerator(useStr, findFileData);
} }
@ -206,7 +206,7 @@ namespace System.IO
{ {
get get
{ {
return Platform.BfpFindFileData_GetFileAttributes(mFindFileData).HasFlag(.Directory); return Platform.Hook.BfpFindFileData_GetFileAttributes(mFindFileData).HasFlag(.Directory);
} }
} }
@ -214,7 +214,7 @@ namespace System.IO
{ {
Platform.GetStrHelper(outFileName, scope (outPtr, outSize, outResult) => Platform.GetStrHelper(outFileName, scope (outPtr, outSize, outResult) =>
{ {
Platform.BfpFindFileData_GetFileName(mFindFileData, outPtr, outSize, (Platform.BfpFileResult*)outResult); Platform.Hook.BfpFindFileData_GetFileName(mFindFileData, outPtr, outSize, (Platform.BfpFileResult*)outResult);
}); });
} }
@ -228,43 +228,45 @@ namespace System.IO
public DateTime GetLastWriteTime() public DateTime GetLastWriteTime()
{ {
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_LastWrite(mFindFileData)); return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_LastWrite(mFindFileData));
} }
public DateTime GetLastWriteTimeUtc() public DateTime GetLastWriteTimeUtc()
{ {
return DateTime.FromFileTimeUtc((int64)Platform.BfpFindFileData_GetTime_LastWrite(mFindFileData)); return DateTime.FromFileTimeUtc((int64)Platform.Hook.BfpFindFileData_GetTime_LastWrite(mFindFileData));
} }
public DateTime GetCreatedTime() public DateTime GetCreatedTime()
{ {
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_Created(mFindFileData)); return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_Created(mFindFileData));
} }
public DateTime GetCreatedTimeUtc() public DateTime GetCreatedTimeUtc()
{ {
return DateTime.FromFileTimeUtc((int64)Platform.BfpFindFileData_GetTime_Created(mFindFileData)); return DateTime.FromFileTimeUtc((int64)Platform.Hook.BfpFindFileData_GetTime_Created(mFindFileData));
} }
public DateTime GetAccessedTime() public DateTime GetAccessedTime()
{ {
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_Access(mFindFileData)); return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_Access(mFindFileData));
} }
public DateTime GetAccessedTimeUtc() public DateTime GetAccessedTimeUtc()
{ {
return DateTime.FromFileTimeUtc((int64)Platform.BfpFindFileData_GetTime_Access(mFindFileData)); return DateTime.FromFileTimeUtc((int64)Platform.Hook.BfpFindFileData_GetTime_Access(mFindFileData));
} }
public int64 GetFileSize() public int64 GetFileSize()
{ {
return Platform.BfpFindFileData_GetFileSize(mFindFileData); return Platform.Hook.BfpFindFileData_GetFileSize(mFindFileData);
} }
public Platform.BfpFileAttributes GetFileAttributes() public Platform.BfpFileAttributes GetFileAttributes()
{ {
return Platform.BfpFindFileData_GetFileAttributes(mFindFileData); return Platform.Hook.BfpFindFileData_GetFileAttributes(mFindFileData);
} }
public static bool operator implicit (Self self) => self.mFindFileData != null;
} }
struct FileEnumerator : IEnumerator<FileFindEntry>, IDisposable struct FileEnumerator : IEnumerator<FileFindEntry>, IDisposable
@ -292,7 +294,7 @@ namespace System.IO
{ {
delete mSearchStr; delete mSearchStr;
if (mFindFileData != null) if (mFindFileData != null)
Platform.BfpFindFileData_Release(mFindFileData); Platform.Hook.BfpFindFileData_Release(mFindFileData);
} }
public bool MoveNext() mut public bool MoveNext() mut
@ -301,7 +303,7 @@ namespace System.IO
if (mIdx == 0) if (mIdx == 0)
return mFindFileData != null; return mFindFileData != null;
return Platform.BfpFindFileData_FindNextFile(mFindFileData); return Platform.Hook.BfpFindFileData_FindNextFile(mFindFileData);
} }
public Result<FileFindEntry> GetNext() mut public Result<FileFindEntry> GetNext() mut

View file

@ -141,13 +141,13 @@ namespace System.IO
public static bool Exists(StringView fileName) public static bool Exists(StringView fileName)
{ {
return Platform.BfpFile_Exists(fileName.ToScopeCStr!()); return Platform.Hook.BfpFile_Exists(fileName.ToScopeCStr!());
} }
public static Result<void, Platform.BfpFileResult> Delete(StringView fileName) public static Result<void, Platform.BfpFileResult> Delete(StringView fileName)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_Delete(fileName.ToScopeCStr!(), &result); Platform.Hook.BfpFile_Delete(fileName.ToScopeCStr!(), &result);
if ((result != .Ok) && (result != .NotFound)) if ((result != .Ok) && (result != .NotFound))
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -156,7 +156,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Move(StringView fromPath, StringView toPath) public static Result<void, Platform.BfpFileResult> Move(StringView fromPath, StringView toPath)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_Rename(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), &result); Platform.Hook.BfpFile_Rename(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), &result);
if (result != .Ok) if (result != .Ok)
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -165,7 +165,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath) public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), .Always, &result); Platform.Hook.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), .Always, &result);
if (result != .Ok) if (result != .Ok)
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -174,7 +174,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> CopyIfNewer(StringView fromPath, StringView toPath) public static Result<void, Platform.BfpFileResult> CopyIfNewer(StringView fromPath, StringView toPath)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), .IfNewer, &result); Platform.Hook.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), .IfNewer, &result);
if (result != .Ok) if (result != .Ok)
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -183,7 +183,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath, bool overwrite) public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath, bool overwrite)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), overwrite ? .Always : .IfNotExists, &result); Platform.Hook.BfpFile_Copy(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), overwrite ? .Always : .IfNotExists, &result);
if (result != .Ok) if (result != .Ok)
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -192,7 +192,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> SetAttributes(StringView path, FileAttributes attr) public static Result<void, Platform.BfpFileResult> SetAttributes(StringView path, FileAttributes attr)
{ {
Platform.BfpFileResult result = default; Platform.BfpFileResult result = default;
Platform.BfpFile_SetAttributes(path.ToScopeCStr!(), (Platform.BfpFileAttributes)attr, &result); Platform.Hook.BfpFile_SetAttributes(path.ToScopeCStr!(), (Platform.BfpFileAttributes)attr, &result);
if (result != .Ok) if (result != .Ok)
return .Err(result); return .Err(result);
return .Ok; return .Ok;
@ -200,12 +200,47 @@ namespace System.IO
public static Result<DateTime> GetLastWriteTime(StringView fullPath) public static Result<DateTime> GetLastWriteTime(StringView fullPath)
{ {
return DateTime.FromFileTime((int64)Platform.BfpFile_GetTime_LastWrite(fullPath.ToScopeCStr!())); return DateTime.FromFileTime((int64)Platform.Hook.BfpFile_GetTime_LastWrite(fullPath.ToScopeCStr!()));
} }
public static Result<DateTime> GetLastWriteTimeUtc(StringView fullPath) public static Result<DateTime> GetLastWriteTimeUtc(StringView fullPath)
{ {
return DateTime.FromFileTimeUtc((int64)Platform.BfpFile_GetTime_LastWrite(fullPath.ToScopeCStr!())); return DateTime.FromFileTimeUtc((int64)Platform.Hook.BfpFile_GetTime_LastWrite(fullPath.ToScopeCStr!()));
} }
} }
class FileInfo
{
FileFindEntry mFileFindEntry;
public this(StringView path)
{
let findFileData = Platform.Hook.BfpFindFileData_FindFirstFile(path.ToScopeCStr!(), .Files, null);
if (findFileData == null)
return;
mFileFindEntry = .(new .(path), findFileData);
}
public ~this()
{
if (mFileFindEntry.[Friend]mSearchStr != null)
{
delete mFileFindEntry.[Friend]mSearchStr;
Platform.Hook.BfpFindFileData_Release(mFileFindEntry.[Friend]mFindFileData);
}
}
public bool Exists => mFileFindEntry;
public bool IsDirectory => mFileFindEntry ? mFileFindEntry.IsDirectory : default;
public void GetFileName(String outFileName) { if (mFileFindEntry) mFileFindEntry.GetFileName(outFileName); }
public void GetFilePath(String outPath) { if (mFileFindEntry) mFileFindEntry.GetFilePath(outPath); }
public DateTime GetLastWriteTime() => mFileFindEntry ? mFileFindEntry.GetLastWriteTime() : default;
public DateTime GetLastWriteTimeUtc() => mFileFindEntry ? mFileFindEntry.GetLastWriteTimeUtc() : default;
public DateTime GetCreatedTime() => mFileFindEntry ? mFileFindEntry.GetCreatedTime() : default;
public DateTime GetCreatedTimeUtc() => mFileFindEntry ? mFileFindEntry.GetCreatedTimeUtc() : default;
public DateTime GetAccessedTime() => mFileFindEntry ? mFileFindEntry.GetAccessedTime() : default;
public DateTime GetAccessedTimeUtc() => mFileFindEntry ? mFileFindEntry.GetAccessedTimeUtc() : default;
public int64 GetFileSize() => mFileFindEntry ? mFileFindEntry.GetFileSize() : default;
public Platform.BfpFileAttributes GetFileAttributes() => mFileFindEntry ? mFileFindEntry.GetFileAttributes() : default;
}
} }

View file

@ -12,12 +12,12 @@ namespace System.IO
{ {
get get
{ {
return Platform.BfpFile_Seek(mBfpFile, 0, .Relative); return Platform.Hook.BfpFile_Seek(mBfpFile, 0, .Relative);
} }
set set
{ {
Platform.BfpFile_Seek(mBfpFile, value, .Absolute); Platform.Hook.BfpFile_Seek(mBfpFile, value, .Absolute);
} }
} }
@ -25,7 +25,7 @@ namespace System.IO
{ {
get get
{ {
return Platform.BfpFile_GetFileSize(mBfpFile); return Platform.Hook.BfpFile_GetFileSize(mBfpFile);
} }
} }
@ -35,7 +35,7 @@ namespace System.IO
{ {
if (mBfpFile == null) if (mBfpFile == null)
return 0; return 0;
return Platform.BfpFile_GetSystemHandle(mBfpFile); return Platform.Hook.BfpFile_GetSystemHandle(mBfpFile);
} }
} }
@ -46,7 +46,7 @@ namespace System.IO
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute) public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
{ {
int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, (Platform.BfpFileSeekKind)seekKind); int64 newPos = Platform.Hook.BfpFile_Seek(mBfpFile, pos, (Platform.BfpFileSeekKind)seekKind);
// Ensure position is what was requested // Ensure position is what was requested
if ((seekKind == .Absolute) && (newPos != pos)) if ((seekKind == .Absolute) && (newPos != pos))
return .Err; return .Err;
@ -56,7 +56,7 @@ namespace System.IO
public override Result<int> TryRead(Span<uint8> data) public override Result<int> TryRead(Span<uint8> data)
{ {
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result); int numBytesRead = Platform.Hook.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
return .Err; return .Err;
return numBytesRead; return numBytesRead;
@ -65,7 +65,7 @@ namespace System.IO
public override Result<int, FileError> TryRead(Span<uint8> data, int timeoutMS) public override Result<int, FileError> TryRead(Span<uint8> data, int timeoutMS)
{ {
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result); int numBytesRead = Platform.Hook.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
{ {
switch (result) switch (result)
@ -84,7 +84,7 @@ namespace System.IO
public override Result<int> TryWrite(Span<uint8> data) public override Result<int> TryWrite(Span<uint8> data)
{ {
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesWritten = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result); int numBytesWritten = Platform.Hook.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
return .Err; return .Err;
return numBytesWritten; return numBytesWritten;
@ -93,7 +93,7 @@ namespace System.IO
public override Result<void> Close() public override Result<void> Close()
{ {
if (mBfpFile != null) if (mBfpFile != null)
Platform.BfpFile_Release(mBfpFile); Platform.Hook.BfpFile_Release(mBfpFile);
mBfpFile = null; mBfpFile = null;
return .Ok; return .Ok;
} }
@ -101,7 +101,7 @@ namespace System.IO
public override Result<void> Flush() public override Result<void> Flush()
{ {
if (mBfpFile != null) if (mBfpFile != null)
Platform.BfpFile_Flush(mBfpFile); Platform.Hook.BfpFile_Flush(mBfpFile);
return .Ok; return .Ok;
} }
@ -159,7 +159,7 @@ namespace System.IO
public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind) public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind)
{ {
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_GetStd(stdKind, &fileResult); mBfpFile = Platform.Hook.BfpFile_GetStd(stdKind, &fileResult);
mFileAccess = .ReadWrite; mFileAccess = .ReadWrite;
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
@ -218,7 +218,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal; Platform.BfpFileAttributes fileFlags = .Normal;
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_Create(path.ToScopeCStr!(128), createKind, createFlags, fileFlags, &fileResult); mBfpFile = Platform.Hook.BfpFile_Create(path.ToScopeCStr!(128), createKind, createFlags, fileFlags, &fileResult);
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
{ {
@ -261,7 +261,7 @@ namespace System.IO
Seek(length); Seek(length);
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result); Platform.Hook.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok) if (result != .Ok)
{ {
Seek(pos); Seek(pos);
@ -297,7 +297,7 @@ namespace System.IO
{ {
if (mBfpFile == null) if (mBfpFile == null)
return 0; return 0;
return Platform.BfpFile_GetSystemHandle(mBfpFile); return Platform.Hook.BfpFile_GetSystemHandle(mBfpFile);
} }
} }
@ -321,7 +321,7 @@ namespace System.IO
{ {
set set
{ {
// Matches the behavior of Platform.BfpFile_Seek(mBfpFile, value, .Absolute); // Matches the behavior of Platform.Hook.BfpFile_Seek(mBfpFile, value, .Absolute);
mPos = Math.Max(value, 0); mPos = Math.Max(value, 0);
} }
} }
@ -355,7 +355,7 @@ namespace System.IO
public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind) public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind)
{ {
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_GetStd(stdKind, &fileResult); mBfpFile = Platform.Hook.BfpFile_GetStd(stdKind, &fileResult);
mFileAccess = .ReadWrite; mFileAccess = .ReadWrite;
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
@ -413,7 +413,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal; Platform.BfpFileAttributes fileFlags = .Normal;
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_Create(path.ToScopeCStr!(128), createKind, createFlags, fileFlags, &fileResult); mBfpFile = Platform.Hook.BfpFile_Create(path.ToScopeCStr!(128), createKind, createFlags, fileFlags, &fileResult);
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
{ {
@ -467,7 +467,7 @@ namespace System.IO
newPos = mPos + pos; newPos = mPos + pos;
} }
// Matches the behaviour of Platform.BfpFile_Seek(mBfpFile, value, .Absolute); // Matches the behaviour of Platform.Hook.BfpFile_Seek(mBfpFile, value, .Absolute);
mPos = Math.Max(newPos, 0); mPos = Math.Max(newPos, 0);
if (seekKind == .Absolute && newPos < 0) if (seekKind == .Absolute && newPos < 0)
return .Err; return .Err;
@ -479,7 +479,7 @@ namespace System.IO
{ {
let ret = base.Close(); let ret = base.Close();
if (mBfpFile != null) if (mBfpFile != null)
Platform.BfpFile_Release(mBfpFile); Platform.Hook.BfpFile_Release(mBfpFile);
mBfpFile = null; mBfpFile = null;
mFileAccess = default; mFileAccess = default;
@ -489,12 +489,12 @@ namespace System.IO
protected override void UpdateLength() protected override void UpdateLength()
{ {
mUnderlyingLength = Platform.BfpFile_GetFileSize(mBfpFile); mUnderlyingLength = Platform.Hook.BfpFile_GetFileSize(mBfpFile);
} }
protected Result<void, FileError> SeekUnderlying(int64 offset, Platform.BfpFileSeekKind seekKind = .Absolute) protected Result<void, FileError> SeekUnderlying(int64 offset, Platform.BfpFileSeekKind seekKind = .Absolute)
{ {
int64 newPos = Platform.BfpFile_Seek(mBfpFile, offset, seekKind); int64 newPos = Platform.Hook.BfpFile_Seek(mBfpFile, offset, seekKind);
Result<void, FileError> result = ((seekKind == .Absolute) && (newPos != offset)) ? .Err(.SeekError) : .Ok; Result<void, FileError> result = ((seekKind == .Absolute) && (newPos != offset)) ? .Err(.SeekError) : .Ok;
if (result case .Ok) if (result case .Ok)
mBfpFilePos = newPos; mBfpFilePos = newPos;
@ -507,7 +507,7 @@ namespace System.IO
Try!(SeekUnderlying(pos)); Try!(SeekUnderlying(pos));
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result); int numBytesRead = Platform.Hook.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
return .Err; return .Err;
mBfpFilePos += numBytesRead; mBfpFilePos += numBytesRead;
@ -520,7 +520,7 @@ namespace System.IO
Try!(SeekUnderlying(pos)); Try!(SeekUnderlying(pos));
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result); int numBytesRead = Platform.Hook.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
return .Err; return .Err;
mBfpFilePos += numBytesRead; mBfpFilePos += numBytesRead;
@ -533,7 +533,7 @@ namespace System.IO
Try!(SeekUnderlying(mPos)); Try!(SeekUnderlying(mPos));
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result); int numBytesRead = Platform.Hook.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result);
if ((result != .Ok) && (result != .PartialData)) if ((result != .Ok) && (result != .PartialData))
{ {
switch (result) switch (result)
@ -560,7 +560,7 @@ namespace System.IO
} }
Platform.BfpFileResult result = .Ok; Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result); Platform.Hook.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok) if (result != .Ok)
{ {
Try!(SeekUnderlying(pos)); Try!(SeekUnderlying(pos));
@ -585,7 +585,7 @@ namespace System.IO
{ {
var result = base.Flush(); var result = base.Flush();
if (mBfpFile != null) if (mBfpFile != null)
Platform.BfpFile_Flush(mBfpFile); Platform.Hook.BfpFile_Flush(mBfpFile);
return result; return result;
} }
} }

View file

@ -116,4 +116,98 @@ namespace System.IO
mPosition = 0; mPosition = 0;
} }
} }
class FixedMemoryStream : Stream
{
Span<uint8> mMemory;
int mPosition = 0;
public override int64 Position
{
get
{
return mPosition;
}
set
{
mPosition = (.)value;
}
}
public override int64 Length
{
get
{
return mMemory.Length;
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public this(Span<uint8> memory)
{
mMemory = memory;
}
public Span<uint8> Memory => mMemory;
public override Result<int> TryRead(Span<uint8> data)
{
let count = data.Length;
if (count == 0)
return .Ok(0);
int readBytes = Math.Min(count, mMemory.Length - mPosition);
if (readBytes <= 0)
return .Ok(readBytes);
Internal.MemCpy(data.Ptr, &mMemory[mPosition], readBytes);
mPosition += readBytes;
return .Ok(readBytes);
}
public override Result<int> TryWrite(Span<uint8> data)
{
let count = data.Length;
if (count == 0)
return .Ok(0);
int growSize = mPosition + count - mMemory.Length;
if (growSize > 0)
return .Err;
Internal.MemCpy(&mMemory[mPosition], data.Ptr, count);
mPosition += count;
return .Ok(count);
}
public override Result<void> Close()
{
return .Ok;
}
public override Result<void> SetLength(int64 length)
{
return .Err;
}
public void Clear()
{
mMemory.Clear();
mPosition = 0;
}
}
} }

View file

@ -46,7 +46,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal; Platform.BfpFileAttributes fileFlags = .Normal;
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_Create(path, createKind, createFlags, fileFlags, &fileResult); mBfpFile = Platform.Hook.BfpFile_Create(path, createKind, createFlags, fileFlags, &fileResult);
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
{ {
@ -76,6 +76,9 @@ namespace System.IO
Platform.BfpFileCreateKind createKind = .CreateAlways; Platform.BfpFileCreateKind createKind = .CreateAlways;
Platform.BfpFileCreateFlags createFlags = .Pipe; Platform.BfpFileCreateFlags createFlags = .Pipe;
if (options.HasFlag(.AllowTimeouts))
createFlags |= .AllowTimeouts;
createKind = .OpenExisting; createKind = .OpenExisting;
createFlags |= .Read; createFlags |= .Read;
createFlags |= .Write; createFlags |= .Write;
@ -83,7 +86,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal; Platform.BfpFileAttributes fileFlags = .Normal;
Platform.BfpFileResult fileResult = .Ok; Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_Create(path, createKind, createFlags, fileFlags, &fileResult); mBfpFile = Platform.Hook.BfpFile_Create(path, createKind, createFlags, fileFlags, &fileResult);
if ((mBfpFile == null) || (fileResult != .Ok)) if ((mBfpFile == null) || (fileResult != .Ok))
{ {

View file

@ -23,6 +23,7 @@ namespace System.IO
mString = appendStr; mString = appendStr;
} }
[DisableChecks]
public ~this() public ~this()
{ {
if (mStringKind == .Append) if (mStringKind == .Append)

View file

@ -1,5 +1,6 @@
using System.Threading; using System.Threading;
using System.Diagnostics; using System.Diagnostics;
using System.Collections;
namespace System namespace System
{ {
@ -105,6 +106,8 @@ namespace System
{ {
String emitStr = scope .(); String emitStr = scope .();
HashSet<String> foundSigs = scope .();
for (var methodInfo in typeof(T).GetMethods(.Public | .DeclaredOnly)) for (var methodInfo in typeof(T).GetMethods(.Public | .DeclaredOnly))
{ {
if (methodInfo.IsStatic) if (methodInfo.IsStatic)
@ -112,11 +115,15 @@ namespace System
if (!methodInfo.IsConstructor) if (!methodInfo.IsConstructor)
continue; continue;
var sig = methodInfo.GetMethodSig(.. new .());
if (!foundSigs.Add(sig))
continue;
emitStr.AppendF("public static RefCounted<T> Create("); emitStr.AppendF("public static RefCounted<T> Create(");
methodInfo.GetParamsDecl(emitStr); methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF(")\n"); emitStr.AppendF(")\n");
emitStr.AppendF("{{\n"); emitStr.AppendF("{{\n");
emitStr.AppendF("\treturn new [Friend] RefCountedAppend<T>("); emitStr.AppendF("\treturn new [Friend]RefCountedAppend<T>(");
methodInfo.GetArgsList(emitStr); methodInfo.GetArgsList(emitStr);
emitStr.AppendF(");\n}}\n"); emitStr.AppendF(");\n}}\n");
} }
@ -207,7 +214,16 @@ namespace System
if (!methodInfo.IsConstructor) if (!methodInfo.IsConstructor)
continue; continue;
emitStr.AppendF("[AllowAppend]\nprotected this("); if (methodInfo.AllowAppendKind == .Yes)
emitStr.AppendF("[AllowAppend]\n");
if (methodInfo.AllowAppendKind == .ZeroGap)
emitStr.AppendF("[AllowAppend(ZeroGap=true)]\n");
if (methodInfo.CheckedKind == .Checked)
emitStr.AppendF("[Checked]\n");
if (methodInfo.CheckedKind == .Unchecked)
emitStr.AppendF("[Unchecked]\n");
emitStr.AppendF("protected this(");
methodInfo.GetParamsDecl(emitStr); methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF(")\n"); emitStr.AppendF(")\n");
emitStr.AppendF("{{\n"); emitStr.AppendF("{{\n");

View file

@ -66,7 +66,7 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
// Dumb, make better. // Dumb, make better.
char8[] strChars = scope:: char8[16]; char8[16] strChars = ?;
int32 char8Idx = 14; int32 char8Idx = 14;
int32 valLeft = (int32)this; int32 valLeft = (int32)this;
bool isNeg = true; bool isNeg = true;
@ -86,7 +86,7 @@ namespace System
if (isNeg) if (isNeg)
strChars[char8Idx--] = '-'; strChars[char8Idx--] = '-';
char8* char8Ptr = &strChars[char8Idx + 1]; char8* char8Ptr = &strChars[char8Idx + 1];
strBuffer.Append(char8Ptr); strBuffer.Append(char8Ptr, 14 - char8Idx);
} }
void ToString(String strBuffer, int minNumerals) void ToString(String strBuffer, int minNumerals)

View file

@ -78,29 +78,27 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
// Dumb, make better. // Dumb, make better.
char8[] strChars = scope:: char8[22]; char8[22] strChars = ?;
int32 char8Idx = 20; int32 char8Idx = 20;
int64 valLeft = (int64)this; int64 valLeft = (int64)this;
bool isNeg = true; bool isNeg = true;
int minNumeralsLeft = 0;
if (valLeft >= 0) if (valLeft >= 0)
{ {
valLeft = -valLeft; valLeft = -valLeft;
isNeg = false; isNeg = false;
} }
while ((valLeft < 0) || (minNumeralsLeft > 0)) while (valLeft < 0)
{ {
strChars[char8Idx] = (char8)('0' &- (valLeft % 10)); strChars[char8Idx] = (char8)('0' &- (valLeft % 10));
valLeft /= 10; valLeft /= 10;
char8Idx--; char8Idx--;
minNumeralsLeft--;
} }
if (char8Idx == 20) if (char8Idx == 20)
strChars[char8Idx--] = '0'; strChars[char8Idx--] = '0';
if (isNeg) if (isNeg)
strChars[char8Idx--] = '-'; strChars[char8Idx--] = '-';
char8* char8Ptr = &strChars[char8Idx + 1]; char8* char8Ptr = &strChars[char8Idx + 1];
strBuffer.Append(char8Ptr); strBuffer.Append(char8Ptr, 20 - char8Idx);
} }
public static Result<int64, ParseError> Parse(StringView val, NumberStyles style = .Number, CultureInfo cultureInfo = null) public static Result<int64, ParseError> Parse(StringView val, NumberStyles style = .Number, CultureInfo cultureInfo = null)

View file

@ -78,6 +78,33 @@ namespace System
[AlwaysInclude] [AlwaysInclude]
static class Internal static class Internal
{ {
enum BfObjectFlags : uint8
{
None = 0,
Mark1 = 0x01,
Mark2 = 0x02,
Mark3 = 0x03,
Allocated = 0x04,
StackAlloc = 0x08,
AppendAlloc = 0x10,
AllocInfo = 0x20,
AllocInfo_Short = 0x40,
Deleted = 0x80
};
struct AppendAllocEntry
{
public enum Kind
{
case None;
case Object(Object obj);
case Raw(void* ptr, DbgRawAllocData* allocData);
}
public Kind mKind;
public AppendAllocEntry* mNext;
}
[Intrinsic("cast")] [Intrinsic("cast")]
public static extern Object UnsafeCastToObject(void* ptr); public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")] [Intrinsic("cast")]
@ -234,8 +261,20 @@ namespace System
public static extern void BfDelegateTargetCheck(void* target); public static extern void BfDelegateTargetCheck(void* target);
[CallingConvention(.Cdecl), AlwaysInclude] [CallingConvention(.Cdecl), AlwaysInclude]
public static extern void* LoadSharedLibrary(char8* filePath); public static extern void* LoadSharedLibrary(char8* filePath);
[CallingConvention(.Cdecl), AlwaysInclude] [AlwaysInclude, LinkName("Beef_LoadSharedLibraryInto")]
public static extern void LoadSharedLibraryInto(char8* filePath, void** libDest); public static void LoadSharedLibraryInto(char8* filePath, void** libDest)
{
if (*libDest == null)
{
if (Runtime.LibraryLoadCallback != null)
*libDest = Runtime.LibraryLoadCallback(filePath);
}
if (*libDest == null)
{
*libDest = LoadSharedLibrary(filePath);
}
}
[CallingConvention(.Cdecl), AlwaysInclude] [CallingConvention(.Cdecl), AlwaysInclude]
public static extern void* GetSharedProcAddress(void* libHandle, char8* procName); public static extern void* GetSharedProcAddress(void* libHandle, char8* procName);
[CallingConvention(.Cdecl), AlwaysInclude] [CallingConvention(.Cdecl), AlwaysInclude]
@ -261,11 +300,11 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth); public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData); public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData, int size, uint8 allocFlags);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size); public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth); public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth, uint8 flags);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_ObjectPreDelete(Object obj); public static extern void Dbg_ObjectPreDelete(Object obj);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
@ -281,6 +320,186 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_RawFree(void* ptr); public static extern void Dbg_RawFree(void* ptr);
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
static void AddAppendInfo(Object rootObj, AppendAllocEntry.Kind kind)
{
Compiler.Assert(sizeof(AppendAllocEntry) <= sizeof(int)*4);
void Handle(AppendAllocEntry* headAllocEntry)
{
if (headAllocEntry.mKind case .None)
{
headAllocEntry.mKind = kind;
}
else
{
AppendAllocEntry* newAppendAllocEntry = (.)new uint8[sizeof(AppendAllocEntry)]*;
newAppendAllocEntry.mKind = kind;
newAppendAllocEntry.mNext = headAllocEntry.mNext;
headAllocEntry.mNext = newAppendAllocEntry;
}
}
if (rootObj.[Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
Debug.Assert(allocFlag == 1);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
Debug.Assert(allocFlag == 1);
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
}
#endif
public static void Dbg_ObjectAppended(Object rootObj, Object appendObj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
AddAppendInfo(rootObj, .Object(appendObj));
#endif
}
public static void Dbg_RawAppended(Object rootObj, void* ptr, DbgRawAllocData* rawAllocData)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
AddAppendInfo(rootObj, .Raw(ptr, rawAllocData));
#endif
}
public static void Dbg_MarkAppended(Object rootObj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
void Handle(AppendAllocEntry* checkAllocEntry)
{
var checkAllocEntry;
while (checkAllocEntry != null)
{
switch (checkAllocEntry.mKind)
{
case .Object(let obj):
obj.[Friend]GCMarkMembers();
case .Raw(let rawPtr, let allocData):
((function void(void*))allocData.mMarkFunc)(rawPtr);
default:
}
checkAllocEntry = checkAllocEntry.mNext;
}
}
if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
#endif
}
public static void Dbg_AppendDeleted(Object rootObj, bool doChecks)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
void Handle(AppendAllocEntry* headAllocEntry)
{
AppendAllocEntry* checkAllocEntry = headAllocEntry;
while (checkAllocEntry != null)
{
switch (checkAllocEntry.mKind)
{
case .Object(let obj):
if (doChecks)
{
#unwarn
if (!obj.[DisableObjectAccessChecks]IsDeleted())
{
if (obj.GetType().HasDestructor)
Debug.FatalError("Appended object not deleted with 'delete:append'");
}
}
case .Raw(let rawPtr, let allocData):
default:
}
var nextAllocEntry = checkAllocEntry.mNext;
if (checkAllocEntry == headAllocEntry)
*checkAllocEntry = default;
else
delete (uint8*)checkAllocEntry;
checkAllocEntry = nextAllocEntry;
}
}
if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
#endif
}
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Shutdown_Internal(); static extern void Shutdown_Internal();
@ -292,19 +511,7 @@ namespace System
} }
#else #else
enum BfObjectFlags : uint8
{
None = 0,
Mark1 = 0x01,
Mark2 = 0x02,
Mark3 = 0x03,
Allocated = 0x04,
StackAlloc = 0x08,
AppendAlloc = 0x10,
AllocInfo = 0x20,
AllocInfo_Short = 0x40,
Deleted = 0x80
};
[NoReturn] [NoReturn]
static void Crash() static void Crash()
@ -446,7 +653,7 @@ namespace System
} }
[DisableChecks, DisableObjectAccessChecks] [DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectStackInit(Object obj, ClassVData* classVData) public static void Dbg_ObjectStackInit(Object obj, ClassVData* classVData, int size, uint8 allocFlags)
{ {
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj.[Friend]mClassVData = (.)(void*)classVData; obj.[Friend]mClassVData = (.)(void*)classVData;
@ -462,7 +669,7 @@ namespace System
return null; return null;
} }
public static Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth) public static Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth, uint8 flags)
{ {
return null; return null;
} }

View file

@ -392,8 +392,11 @@ namespace System.Net
service.sin_addr = address; service.sin_addr = address;
service.sin_port = (uint16)htons((int16)port); service.sin_port = (uint16)htons((int16)port);
if (bind(mHandle, &service, sizeof(SockAddr_in)) == SOCKET_ERROR) int32 size = sizeof(SockAddr_in);
if (bind(mHandle, &service, size) == SOCKET_ERROR)
{ {
int err = WSAGetLastError();
Close(); Close();
return .Err; return .Err;
} }

View file

@ -35,7 +35,7 @@ namespace System
return (int32)mClassVData & 0x80 != 0; return (int32)mClassVData & 0x80 != 0;
} }
#else #else
[SkipCall] [SkipCall, NoShow]
public bool IsDeleted() public bool IsDeleted()
{ {
return false; return false;
@ -132,6 +132,12 @@ namespace System
} }
#endif #endif
[NoShow]
public virtual Object DynamicCastToSignature(int32 sig)
{
return null;
}
int IHashable.GetHashCode() int IHashable.GetHashCode()
{ {
return (int)Internal.UnsafeCastToPtr(this); return (int)Internal.UnsafeCastToPtr(this);

View file

@ -67,6 +67,11 @@ namespace System
} }
#if !BF_RUNTIME_DISABLE #if !BF_RUNTIME_DISABLE
[StaticHook(typeof(SelfOuter))]
public static struct Hook
{
}
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern uint32 BfpSystem_TickCount(); public static extern uint32 BfpSystem_TickCount();
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -124,6 +129,7 @@ namespace System
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void* BfpTLS_GetValue(BfpTLS* tls); public static extern void* BfpTLS_GetValue(BfpTLS* tls);
#else #else
public typealias Hook = Self;
public static uint32 BfpSystem_TickCount() => Runtime.NotImplemented(); public static uint32 BfpSystem_TickCount() => Runtime.NotImplemented();
@ -565,47 +571,47 @@ namespace System
} }
#if !BF_RUNTIME_DISABLE #if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult); public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult); public static extern BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int BfpFile_GetSystemHandle(BfpFile* file); public static extern int BfpFile_GetSystemHandle(BfpFile* file);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Release(BfpFile* file); public static extern void BfpFile_Release(BfpFile* file);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult); public static extern int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int BfpFile_Read(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult); public static extern int BfpFile_Read(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Flush(BfpFile* file); public static extern void BfpFile_Flush(BfpFile* file);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int64 BfpFile_GetFileSize(BfpFile* file); public static extern int64 BfpFile_GetFileSize(BfpFile* file);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind); public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult); public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path); public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFileAttributes BfpFile_GetAttributes(char8* path, BfpFileResult* outResult); public static extern BfpFileAttributes BfpFile_GetAttributes(char8* path, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_SetAttributes(char8* path, BfpFileAttributes attribs, BfpFileResult* outResult); public static extern void BfpFile_SetAttributes(char8* path, BfpFileAttributes attribs, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Copy(char8* oldPath, char8* newPath, BfpFileCopyKind copyKind, BfpFileResult* outResult); public static extern void BfpFile_Copy(char8* oldPath, char8* newPath, BfpFileCopyKind copyKind, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Rename(char8* oldPath, char8* newPath, BfpFileResult* outResult); public static extern void BfpFile_Rename(char8* oldPath, char8* newPath, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_Delete(char8* path, BfpFileResult* outResult); public static extern void BfpFile_Delete(char8* path, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern bool BfpFile_Exists(char8* path); public static extern bool BfpFile_Exists(char8* path);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_GetTempPath(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult); public static extern void BfpFile_GetTempPath(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_GetTempFileName(char8* outName, int32* inOutNameSize, BfpFileResult* outResult); public static extern void BfpFile_GetTempFileName(char8* outName, int32* inOutNameSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult); public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult); public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
#else #else
@ -660,23 +666,23 @@ namespace System
}; };
#if !BF_RUNTIME_DISABLE #if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult); public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern bool BfpFindFileData_FindNextFile(BfpFindFileData* findData); public static extern bool BfpFindFileData_FindNextFile(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFindFileData_GetFileName(BfpFindFileData* findData, char8* outName, int32* inOutNameSize, BfpFileResult* outResult); public static extern void BfpFindFileData_GetFileName(BfpFindFileData* findData, char8* outName, int32* inOutNameSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpTimeStamp BfpFindFileData_GetTime_LastWrite(BfpFindFileData* findData); public static extern BfpTimeStamp BfpFindFileData_GetTime_LastWrite(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpTimeStamp BfpFindFileData_GetTime_Created(BfpFindFileData* findData); public static extern BfpTimeStamp BfpFindFileData_GetTime_Created(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpTimeStamp BfpFindFileData_GetTime_Access(BfpFindFileData* findData); public static extern BfpTimeStamp BfpFindFileData_GetTime_Access(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData); public static extern BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData); public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFindFileData_Release(BfpFindFileData* findData); public static extern void BfpFindFileData_Release(BfpFindFileData* findData);
#else #else
@ -714,6 +720,20 @@ namespace System
Documents Documents
} }
public static bool SetStrHelper(StringView str, char8* outStr, int32* inOutSize, Result* outResult)
{
if (str.Length > *inOutSize + 1)
{
*inOutSize = (.)str.Length + 1;
*outResult = .InsufficientBuffer;
return false;
}
*inOutSize = (.)str.Length + 1;
Internal.MemCpy(outStr, str.Ptr, str.Length);
outStr[str.Length] = 0;
return true;
}
public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func) public static Result<void, Platform.Result> GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func)
{ {
let initSize = 4096; let initSize = 4096;

View file

@ -18,7 +18,8 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
strBuffer.AppendF("0x{0:A}", (UInt.Simple)(uint)(void*)mVal); strBuffer.Append("0x");
NumberFormatter.AddrToString((uint)(void*)mVal, strBuffer);
} }
} }
@ -35,7 +36,8 @@ namespace System
{ {
strBuffer.Append("("); strBuffer.Append("(");
typeof(T).ToString(strBuffer); typeof(T).ToString(strBuffer);
strBuffer.AppendF("*)0x{0:A}", (UInt.Simple)(uint)(void*)mVal); strBuffer.Append("*)0x");
NumberFormatter.AddrToString((uint)(void*)mVal, strBuffer);
} }
} }
} }

View file

@ -21,7 +21,7 @@ namespace System
using System.Threading; using System.Threading;
// This class is thread-safe for random results, but not deterministically thread-safe // This class is thread-safe for random results, but not deterministically thread-safe
[StaticInitPriority(100)] [StaticInitPriority(200)]
public class Random public class Random
{ {
// //
@ -39,7 +39,11 @@ namespace System
private int32 inextp; private int32 inextp;
private int32[] SeedArray = new int32[56] ~ delete _; private int32[] SeedArray = new int32[56] ~ delete _;
#if !BF_RUNTIME_DISABLE
private static int32 sSeed = (int32)Platform.BfpSystem_GetTimeStamp(); private static int32 sSeed = (int32)Platform.BfpSystem_GetTimeStamp();
#else
private static int32 sSeed = 0;
#endif
// //
// Public Constants // Public Constants

View file

@ -104,7 +104,7 @@ namespace System.Reflection
case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf
let argTypeId = Decode!<int32>(data); let argTypeId = Decode!<int32>(data);
args[argIdx] = Type.[Friend]GetType((.)argTypeId); args[argIdx] = Type.[Friend]GetType((.)argTypeId);
case (TypeCode)typeof(TypeCode).MaxValue + 18: // BfConstType_Box case (TypeCode)typeof(TypeCode).MaxValue + 19: // BfConstType_Box
let boxedTypeId = Decode!<int32>(data); let boxedTypeId = Decode!<int32>(data);
var boxedType = Type.[Friend]GetType_(boxedTypeId); var boxedType = Type.[Friend]GetType_(boxedTypeId);
int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset; int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset;
@ -216,7 +216,7 @@ namespace System.Reflection
case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf
let argTypeId = AttributeInfo.Decode!<int32>(mData); let argTypeId = AttributeInfo.Decode!<int32>(mData);
args[argIdx] = Variant.Create(Type.[Friend]GetType((.)argTypeId)); args[argIdx] = Variant.Create(Type.[Friend]GetType((.)argTypeId));
case (TypeCode)typeof(TypeCode).MaxValue + 18: // BfConstType_Box case (TypeCode)typeof(TypeCode).MaxValue + 19: // BfConstType_Box
let boxedTypeId = AttributeInfo.Decode!<int32>(mData); let boxedTypeId = AttributeInfo.Decode!<int32>(mData);
var boxedType = Type.[Friend]GetType_(boxedTypeId); var boxedType = Type.[Friend]GetType_(boxedTypeId);
int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset; int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset;

View file

@ -454,6 +454,38 @@ namespace System.Reflection
return value; return value;
} }
public Result<T*> GetValueReference<T>(void* startTargetDataAddr, Type tTarget)
{
void* targetDataAddr = startTargetDataAddr;
if (targetDataAddr == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return (T*)&mFieldData.mData;
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
targetDataAddr = null;
}
else
{
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type;
}
targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
TypeCode typeCode = fieldType.[Friend]mTypeCode;
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
return (T*)targetDataAddr;
}
public Result<Variant> GetValue(Object target) public Result<Variant> GetValue(Object target)
{ {
void* targetDataAddr; void* targetDataAddr;
@ -498,6 +530,44 @@ namespace System.Reflection
} }
} }
Result<T*> DoGetValueReference<T>(Object target)
{
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return (T*)&mFieldData.mData;
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference<T>(null, null);
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
return GetValueReference<T>(targetDataAddr, tTarget);
}
}
public Result<T*> GetValueReference<T>(Object target)
{
if (FieldType != typeof(T))
return .Err;
return DoGetValueReference<T>(target);
}
public Result<T> GetValue<T>(Object target)
{
if ((FieldType != typeof(T)) && (!FieldType.IsSubtypeOf(typeof(T))))
return .Err;
T* result = Try!(DoGetValueReference<T>(target));
return *result;
}
public Result<Variant> GetValueReference(Object target) public Result<Variant> GetValueReference(Object target)
{ {
void* targetDataAddr; void* targetDataAddr;
@ -542,6 +612,30 @@ namespace System.Reflection
} }
} }
public Result<T*> GetValueReference<T>(Variant target)
{
if (FieldType != typeof(T))
return .Err;
if (!target.HasValue)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return (T*)&mFieldData.mData;
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference<T>(null, null);
}
else
{
var target;
return GetValueReference<T>(target.DataPtr, target.VariantType);
}
}
public struct Enumerator : IEnumerator<FieldInfo> public struct Enumerator : IEnumerator<FieldInfo>
{ {
BindingFlags mBindingFlags; BindingFlags mBindingFlags;

View file

@ -59,6 +59,9 @@ namespace System.Reflection
public bool IsMixin => Compiler.IsComptime ? public bool IsMixin => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.Mixin) : Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.Mixin) :
mData.mMethodData.[Friend]mFlags.HasFlag(.Mixin); mData.mMethodData.[Friend]mFlags.HasFlag(.Mixin);
public bool IsMutating => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.HasFlag(.Mutating) :
mData.mMethodData.[Friend]mFlags.HasFlag(.Mutating);
public StringView Name => Compiler.IsComptime ? public StringView Name => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetName(mData.mComptimeMethodInstance) : Type.[Friend]Comptime_Method_GetName(mData.mComptimeMethodInstance) :
@ -82,6 +85,13 @@ namespace System.Reflection
Name == "~this" : Name == "~this" :
mData.mMethodData.mName === "~this"; mData.mMethodData.mName === "~this";
public AllowAppendKind AllowAppendKind => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.AllowAppendKind :
mData.mMethodData.[Friend]mFlags.AllowAppendKind;
public CheckedKind CheckedKind => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.CheckedKind :
mData.mMethodData.[Friend]mFlags.CheckedKind;
public Type ReturnType => Compiler.IsComptime ? public Type ReturnType => Compiler.IsComptime ?
Type.[Friend]GetType((.)Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mReturnTypeId) : Type.[Friend]GetType((.)Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mReturnTypeId) :
Type.[Friend]GetType(mData.mMethodData.mReturnType); Type.[Friend]GetType(mData.mMethodData.mReturnType);
@ -1017,6 +1027,25 @@ namespace System.Reflection
strBuffer.Append(')'); strBuffer.Append(')');
} }
public void GetMethodSig(String strBuffer)
{
strBuffer.Append('(');
int useParamIdx = 0;
for (int paramIdx < ParamCount)
{
var flag = GetParamFlags(paramIdx);
if (flag.HasFlag(.Implicit))
continue;
if (useParamIdx > 0)
strBuffer.Append(", ");
if (flag.HasFlag(.Params))
strBuffer.Append("params ");
strBuffer.Append(GetParamType(paramIdx));
useParamIdx++;
}
strBuffer.Append(')');
}
public void GetParamsDecl(String strBuffer) public void GetParamsDecl(String strBuffer)
{ {
int useParamIdx = 0; int useParamIdx = 0;

View file

@ -178,7 +178,7 @@ namespace System.Reflection
int32 stackCount = Compiler.Options.AllocStackCount; int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0) if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride; stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount); obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount, 0);
#else #else
void* mem = new [Align(16)] uint8[allocSize]* (?); void* mem = new [Align(16)] uint8[allocSize]* (?);
obj = Internal.UnsafeCastToObject(mem); obj = Internal.UnsafeCastToObject(mem);

View file

@ -14,7 +14,7 @@ namespace System
public bool AVX, AVX2, AVX512; public bool AVX, AVX2, AVX512;
} }
[StaticInitPriority(101)] [StaticInitPriority(201)]
static class Runtime static class Runtime
{ {
const int32 cVersion = 10; const int32 cVersion = 10;
@ -111,7 +111,7 @@ namespace System
function void* (int size) mAlloc; function void* (int size) mAlloc;
function void (void* ptr) mFree; function void (void* ptr) mFree;
function void (Object obj) mObject_Delete; function void (Object obj) mObject_Delete;
void* mUnused0; function void* (ClassVData* vdataPtr) mClassVData_GetTypeData;
function Type (Object obj) mObject_GetType; function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers; function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId; function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
@ -152,6 +152,16 @@ namespace System
delete obj; delete obj;
} }
static void* ClassVData_GetTypeData(ClassVData* classVData)
{
#if BF_32_BIT
Type type = Type.[Friend]GetType_(classVData.mType2);
#else
Type type = Type.[Friend]GetType_((.)(classVData.mType >> 32));
#endif
return &type.[Friend]mSize;
}
static Type Object_GetType(Object obj) static Type Object_GetType(Object obj)
{ {
#if BF_DBG_RUNTIME #if BF_DBG_RUNTIME
@ -259,6 +269,7 @@ namespace System
mAlloc = => Alloc; mAlloc = => Alloc;
mFree = => Free; mFree = => Free;
mObject_Delete = => Object_Delete; mObject_Delete = => Object_Delete;
mClassVData_GetTypeData = => ClassVData_GetTypeData;
mObject_GetType = => Object_GetType; mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers; mObject_GCMarkMembers = => Object_GCMarkMembers;
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId; mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
@ -484,6 +495,7 @@ namespace System
public static function ErrorHandlerResult(AssertError.Kind kind, String error, String filePath, int lineNum) CheckAssertError; public static function ErrorHandlerResult(AssertError.Kind kind, String error, String filePath, int lineNum) CheckAssertError;
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;
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)
{ {
@ -638,7 +650,7 @@ namespace System
} }
} }
#if BF_RUNTIME_DISABLE #if BF_RUNTIME_DISABLE && !BF_CRT_DISABLE
namespace System namespace System
{ {
[AlwaysInclude, StaticInitPriority(1000)] [AlwaysInclude, StaticInitPriority(1000)]
@ -734,8 +746,8 @@ namespace System
return 0; return 0;
} }
[LinkName(.C), AlwaysInclude] /*[LinkName(.C), AlwaysInclude]
static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd); static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd);*/
[LinkName(.C), AlwaysInclude] [LinkName(.C), AlwaysInclude]
static extern int32 main(int argc, char8** argv); static extern int32 main(int argc, char8** argv);

View file

@ -0,0 +1,90 @@
namespace System;
[AttributeUsage(.Types | .Method)]
public struct StaticHookAttribute : Attribute, IOnTypeInit
{
Type mSrcType;
Type mDestType;
public this()
{
mSrcType = null;
mDestType = null;
}
public this(Type srcType)
{
mSrcType = srcType;
mDestType = null;
}
public this(Type srcType, Type destType)
{
mSrcType = srcType;
mDestType = destType;
}
[Comptime]
public void OnTypeInit(Type type, Self* prev)
{
var emitStr = scope String();
if (mDestType != null)
{
var hookAttr = mSrcType.GetCustomAttribute<Self>().Value;
for (var methodInfo in mDestType.GetMethods(.Static))
{
if (!methodInfo.HasCustomAttribute<StaticHookAttribute>())
continue;
emitStr.AppendF($"public static function {methodInfo.ReturnType}");
emitStr.Append("(");
methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF($") s{methodInfo.Name};\n");
}
emitStr.Append("\n");
emitStr.Append("static this\n{\n");
for (var methodInfo in mDestType.GetMethods(.Static))
{
if (!methodInfo.HasCustomAttribute<StaticHookAttribute>())
continue;
emitStr.AppendF($"\ts{methodInfo.Name} = {mSrcType}.s{methodInfo.Name} ?? => {hookAttr.mSrcType}.{methodInfo.Name};\n");
emitStr.AppendF($"\t{mSrcType}.s{methodInfo.Name} = => {mDestType}.{methodInfo.Name};\n");
}
emitStr.Append("}\n");
}
else
{
if (mSrcType == null)
return;
emitStr.Append("#pragma warning disable\n");
for (var methodInfo in mSrcType.GetMethods(.Static))
{
if (!methodInfo.HasCustomAttribute<StaticHookAttribute>())
continue;
emitStr.AppendF($"public static function {methodInfo.ReturnType}");
emitStr.Append("(");
methodInfo.GetParamsDecl(emitStr);
emitStr.AppendF($") s{methodInfo.Name};\n");
emitStr.AppendF($"public static {methodInfo.ReturnType} {methodInfo.Name}");
emitStr.Append("(");
methodInfo.GetParamsDecl(emitStr);
emitStr.Append(")\n");
emitStr.Append("{\n");
emitStr.AppendF($"\tif (s{methodInfo.Name} != null)\n");
emitStr.AppendF($"\t\treturn s{methodInfo.Name}(");
methodInfo.GetArgsList(emitStr);
emitStr.AppendF($");\n\treturn {mSrcType}.{methodInfo.Name}(");
methodInfo.GetArgsList(emitStr);
emitStr.Append(");\n}\n\n");
}
}
Compiler.EmitTypeBody(type, emitStr);
}
}

View file

@ -74,42 +74,86 @@ namespace System
const uint32 cStrPtrFlag = 0x40000000; const uint32 cStrPtrFlag = 0x40000000;
#endif #endif
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(int count) // 0 public this(int count) // 0
{ {
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn #unwarn
char8* addlPtr = append char8[bufferSize]*(?); char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*); mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
mLength = 0; mLength = 0;
} }
[AllowAppend] [AllowAppend]
public this(int count) // 0
{
int bufferSize = count;
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
mPtrOrBuffer = addlPtr;
mAllocSizeAndFlags = (uint_strsize)bufferSize | cStrPtrFlag;
mLength = 0;
}
[AllowAppend(ZeroGap=true)]
public this() public this()
{ {
let bufferSize = 16 - sizeof(char8*); let bufferSize = 16 - sizeof(char8*);
#unwarn #unwarn
char8* addlPtr = append char8[bufferSize]*(?); char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*); mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
mLength = 0; mLength = 0;
} }
[AllowAppend] [AllowAppend]
public this()
{
let bufferSize = 8;
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
mPtrOrBuffer = addlPtr;
mAllocSizeAndFlags = (uint_strsize)bufferSize | cStrPtrFlag;
mLength = 0;
}
[AllowAppend(ZeroGap=true)]
public this(String str) public this(String str)
{ {
let count = str.mLength; let count = str.mLength;
/*int a = __appendIdx;
int b = offsetof(String, mPtrOrBuffer);
if (__appendIdx == offsetof(String, mPtrOrBuffer))
{
}*/
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn #unwarn
char8* addlPtr = append char8[bufferSize]*(?); char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
Internal.MemCpy(Ptr, str.Ptr, count); Internal.MemCpy(Ptr, str.Ptr, count);
mLength = count; mLength = count;
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*); mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
} }
[AllowAppend] [AllowAppend]
public this(String str)
{
let count = str.mLength;
/*int a = __appendIdx;
int b = offsetof(String, mPtrOrBuffer);
if (__appendIdx == offsetof(String, mPtrOrBuffer))
{
}*/
int bufferSize = count;
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
mPtrOrBuffer = addlPtr;
Internal.MemCpy(Ptr, str.Ptr, count);
mLength = count;
mAllocSizeAndFlags = (uint_strsize)bufferSize | cStrPtrFlag;
}
[AllowAppend(ZeroGap=true)]
public this(String str, int offset) public this(String str, int offset)
{ {
Debug.Assert((uint)offset <= (uint)str.Length); Debug.Assert((uint)offset <= (uint)str.Length);
@ -126,7 +170,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(String str, int offset, int count) public this(String str, int offset, int count)
{ {
Debug.Assert((uint)offset <= (uint)str.Length); Debug.Assert((uint)offset <= (uint)str.Length);
@ -144,7 +188,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(char8 c, int count) public this(char8 c, int count)
{ {
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -158,7 +202,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(char8* char8Ptr) public this(char8* char8Ptr)
{ {
let count = Internal.CStrLen(char8Ptr); let count = Internal.CStrLen(char8Ptr);
@ -173,7 +217,7 @@ namespace System
mLength = count; mLength = count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(char8* char8Ptr, int count) public this(char8* char8Ptr, int count)
{ {
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -187,7 +231,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(char16* char16Ptr) public this(char16* char16Ptr)
{ {
let count = UTF16.GetLengthAsUTF8(char16Ptr); let count = UTF16.GetLengthAsUTF8(char16Ptr);
@ -200,7 +244,7 @@ namespace System
UTF16.Decode(char16Ptr, this); UTF16.Decode(char16Ptr, this);
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(Span<char16> chars) public this(Span<char16> chars)
{ {
let count = UTF16.GetLengthAsUTF8(chars); let count = UTF16.GetLengthAsUTF8(chars);
@ -213,14 +257,13 @@ namespace System
UTF16.Decode(chars, this); UTF16.Decode(chars, this);
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(StringView strView) public this(StringView strView)
{ {
let count = strView.Length; let count = strView.Length;
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn #unwarn
char8* addlPtr = append char8[bufferSize]*(?); char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
let ptr = Ptr; let ptr = Ptr;
Internal.MemCpy(ptr, strView.Ptr, strView.Length); Internal.MemCpy(ptr, strView.Ptr, strView.Length);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*); mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
@ -228,6 +271,20 @@ namespace System
} }
[AllowAppend] [AllowAppend]
public this(StringView strView)
{
let count = strView.Length;
int bufferSize = count;
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
mPtrOrBuffer = addlPtr;
let ptr = Ptr;
Internal.MemCpy(ptr, strView.Ptr, strView.Length);
mAllocSizeAndFlags = (uint_strsize)bufferSize | cStrPtrFlag;
mLength = (int_strsize)strView.Length;
}
[AllowAppend(ZeroGap=true)]
public this(StringView strView, CreateFlags flags) public this(StringView strView, CreateFlags flags)
{ {
let count = strView.Length + (flags.HasFlag(.NullTerminate) ? 1 : 0); let count = strView.Length + (flags.HasFlag(.NullTerminate) ? 1 : 0);
@ -243,7 +300,7 @@ namespace System
mLength = (int32)strView.Length; mLength = (int32)strView.Length;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(StringView strView, int offset) public this(StringView strView, int offset)
{ {
Debug.Assert((uint)offset <= (uint)strView.Length); Debug.Assert((uint)offset <= (uint)strView.Length);
@ -261,7 +318,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(StringView strView, int offset, int count) public this(StringView strView, int offset, int count)
{ {
Debug.Assert((uint)offset <= (uint)strView.Length); Debug.Assert((uint)offset <= (uint)strView.Length);
@ -279,7 +336,7 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
[AllowAppend] [AllowAppend(ZeroGap=true)]
public this(char8[] chars, int offset, int count) public this(char8[] chars, int offset, int count)
{ {
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -293,7 +350,15 @@ namespace System
mLength = (int_strsize)count; mLength = (int_strsize)count;
} }
static int StrLengths(String[] strs) static int StrLengths(Span<StringView> strs)
{
int count = 0;
for (var str in strs)
count += str.Length;
return count;
}
static int StrLengths(Span<String> strs)
{ {
int count = 0; int count = 0;
for (var str in strs) for (var str in strs)
@ -302,7 +367,7 @@ namespace System
} }
[AllowAppend] [AllowAppend]
public this(params String[] strs) public this(params Span<StringView> strs)
{ {
int count = StrLengths(strs); int count = StrLengths(strs);
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1); int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -313,7 +378,27 @@ namespace System
int curIdx = 0; int curIdx = 0;
for (var str in strs) for (var str in strs)
{ {
Internal.MemCpy(ptr + curIdx, str.Ptr, str.mLength); Internal.MemCpy(ptr + curIdx, str.Ptr, str.Length);
curIdx += str.Length;
}
mLength = (int_strsize)count;
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
}
[AllowAppend]
public this(Span<String> strs)
{
int count = StrLengths(strs);
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
let ptr = Ptr;
int curIdx = 0;
for (var str in strs)
{
Internal.MemCpy(ptr + curIdx, str.Ptr, str.Length);
curIdx += str.Length; curIdx += str.Length;
} }
@ -642,7 +727,7 @@ namespace System
public static implicit operator Span<char8>(String str) public static implicit operator Span<char8>(String str)
{ {
if (str == null) if (str == null)
return .(null, 0); return .((char8*)null, 0);
return .(str.Ptr, str.Length); return .(str.Ptr, str.Length);
} }
@ -966,7 +1051,7 @@ namespace System
Append(str.Ptr + offset, length); Append(str.Ptr + offset, length);
} }
public void Append(params String[] strings) public void Append(params Span<StringView> strings)
{ {
for (var str in strings) for (var str in strings)
Append(str); Append(str);
@ -1307,6 +1392,10 @@ namespace System
while (true) while (true)
{ {
int charsLeft = len - pos;
Reserve(mLength + charsLeft);
char8* ptr = Ptr;
int p = pos; int p = pos;
int i = pos; int i = pos;
while (pos < len) while (pos < len)
@ -1333,7 +1422,8 @@ namespace System
} }
} }
Append(ch); //Append(ch);
ptr[mLength++] = ch;
} }
if (pos == len) break; if (pos == len) break;
@ -1434,25 +1524,36 @@ namespace System
} }
if (ch != '}') return FormatError(); if (ch != '}') return FormatError();
pos++; pos++;
if (s == null)
s = scope:: String(128); if ((provider == null) && (fmt.IsEmpty) && (width == 0))
{
s.Clear(); if (arg == null)
IFormattable formattableArg = arg as IFormattable; Append("null");
if (formattableArg != null) else
formattableArg.ToString(s, fmt, provider); arg.ToString(this);
else if (arg != null) }
arg.ToString(s);
else else
s.Append("null"); {
if (fmt != (Object)"") if (s == null)
fmt.Clear(); s = scope:: String(128);
if (s == null) s = String.Empty; s.Clear();
int pad = width - s.Length; IFormattable formattableArg = arg as IFormattable;
if (!leftJustify && pad > 0) Append(' ', pad); if (formattableArg != null)
Append(s); formattableArg.ToString(s, fmt, provider);
if (leftJustify && pad > 0) Append(' ', pad); else if (arg != null)
arg.ToString(s);
else
s.Append("null");
if (fmt != (Object)"")
fmt.Clear();
if (s == null) s = String.Empty;
int pad = width - s.Length;
if (!leftJustify && pad > 0) Append(' ', pad);
Append(s);
if (leftJustify && pad > 0) Append(' ', pad);
}
} }
return .Ok; return .Ok;
@ -2514,9 +2615,9 @@ namespace System
} }
} }
public void Join(String separator, params String[] values) public void Join(StringView separator, Span<String> values)
{ {
for (int i = 0; i < values.Count; i++) for (int i = 0; i < values.Length; i++)
{ {
if (i > 0) if (i > 0)
Append(separator); Append(separator);
@ -2524,6 +2625,17 @@ namespace System
} }
} }
public void Join(StringView separator, params Span<StringView> values)
{
for (int i = 0; i < values.Length; i++)
{
if (i > 0)
Append(separator);
values[i].ToString(this);
}
}
public StringSplitEnumerator Split(char8 c) public StringSplitEnumerator Split(char8 c)
{ {
return StringSplitEnumerator(Ptr, Length, c, Int32.MaxValue, StringSplitOptions.None); return StringSplitEnumerator(Ptr, Length, c, Int32.MaxValue, StringSplitOptions.None);
@ -2544,27 +2656,27 @@ namespace System
return StringSplitEnumerator(Ptr, Length, separator, count, options); return StringSplitEnumerator(Ptr, Length, separator, count, options);
} }
public StringSplitEnumerator Split(params char8[] separators) public StringSplitEnumerator Split(params Span<char8> separators)
{ {
return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None); return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None);
} }
public StringSplitEnumerator Split(char8[] separators) public StringSplitEnumerator Split(Span<char8> separators)
{ {
return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None); return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None);
} }
public StringSplitEnumerator Split(char8[] separators, int count) public StringSplitEnumerator Split(Span<char8> separators, int count)
{ {
return StringSplitEnumerator(Ptr, Length, separators, count, StringSplitOptions.None); return StringSplitEnumerator(Ptr, Length, separators, count, StringSplitOptions.None);
} }
public StringSplitEnumerator Split(char8[] separators, int count, StringSplitOptions options) public StringSplitEnumerator Split(Span<char8> separators, int count, StringSplitOptions options)
{ {
return StringSplitEnumerator(Ptr, Length, separators, count, options); return StringSplitEnumerator(Ptr, Length, separators, count, options);
} }
public StringSplitEnumerator Split(char8[] separators, StringSplitOptions options) public StringSplitEnumerator Split(Span<char8> separators, StringSplitOptions options)
{ {
return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, options); return StringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, options);
} }
@ -2903,6 +3015,16 @@ namespace System
} }
} }
public static String GetById(int id)
{
if (Compiler.IsComptime)
{
return Compiler.[Friend]Comptime_GetStringById((.)id);
}
else
return sIdStringLiterals[id];
}
public struct RawEnumerator : IRefEnumerator<char8*>, IEnumerator<char8> public struct RawEnumerator : IRefEnumerator<char8*>, IEnumerator<char8>
{ {
char8* mPtr; char8* mPtr;
@ -3079,15 +3201,15 @@ namespace System
int_strsize mPos; int_strsize mPos;
int_strsize mMatchPos; int_strsize mMatchPos;
public this(char8* ptr, int strLength, char8[] separators, int count, StringSplitOptions splitOptions) public this(char8* ptr, int strLength, Span<char8> separators, int count, StringSplitOptions splitOptions)
{ {
mPtr = ptr; mPtr = ptr;
mStrLen = (int_strsize)strLength; mStrLen = (int_strsize)strLength;
if (separators?.Count > 0) if (separators.Length > 0)
{ {
mFirstSeparator = separators[0]; mFirstSeparator = separators[0];
mSeparatorPtr = &separators[0]; mSeparatorPtr = &separators[0];
mSeparatorCount = (.)separators.Count; mSeparatorCount = (.)separators.Length;
} }
else else
{ {
@ -3281,7 +3403,7 @@ namespace System
{ {
StringSplitOptions mSplitOptions; StringSplitOptions mSplitOptions;
StringView mFirstSeparator; StringView mFirstSeparator;
StringView[] mSeparators; Span<StringView> mSeparators;
char8* mPtr; char8* mPtr;
int_strsize mStrLen; int_strsize mStrLen;
int32 mCurCount; int32 mCurCount;
@ -3290,11 +3412,11 @@ namespace System
int_strsize mMatchPos; int_strsize mMatchPos;
int_strsize mMatchLen; int_strsize mMatchLen;
public this(char8* ptr, int strLength, StringView[] separators, int count, StringSplitOptions splitOptions) public this(char8* ptr, int strLength, Span<StringView> separators, int count, StringSplitOptions splitOptions)
{ {
mPtr = ptr; mPtr = ptr;
mStrLen = (int_strsize)strLength; mStrLen = (int_strsize)strLength;
if (separators?.Count > 0) if (separators.Length > 0)
mFirstSeparator = separators[0]; mFirstSeparator = separators[0];
else else
mFirstSeparator = .(); mFirstSeparator = .();
@ -3414,7 +3536,7 @@ namespace System
} }
else else
{ {
if (mFirstSeparator.IsNull && (mSeparators == null || mSeparators.IsEmpty) && mPtr[mMatchPos].IsWhiteSpace) if (mFirstSeparator.IsNull && (mSeparators.IsEmpty) && mPtr[mMatchPos].IsWhiteSpace)
{ {
foundMatch = true; foundMatch = true;
mMatchLen = 1; mMatchLen = 1;
@ -3424,9 +3546,9 @@ namespace System
foundMatch = true; foundMatch = true;
mMatchLen = (int_strsize)mFirstSeparator.Length; mMatchLen = (int_strsize)mFirstSeparator.Length;
} }
else if (mSeparators != null) else if (!mSeparators.IsEmpty)
{ {
for (int i = 1; i < mSeparators.Count; i++) for (int i = 1; i < mSeparators.Length; i++)
{ {
if (mSeparators[i].Length <= mStrLen - mMatchPos && StringView(&mPtr[mMatchPos], mSeparators[i].Length) == mSeparators[i]) if (mSeparators[i].Length <= mStrLen - mMatchPos && StringView(&mPtr[mMatchPos], mSeparators[i].Length) == mSeparators[i])
{ {
@ -4273,27 +4395,27 @@ namespace System
return StringStringSplitEnumerator(Ptr, Length, separator, count, options); return StringStringSplitEnumerator(Ptr, Length, separator, count, options);
} }
public StringStringSplitEnumerator Split(params StringView[] separators) public StringStringSplitEnumerator Split(params Span<StringView> separators)
{ {
return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None); return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None);
} }
public StringStringSplitEnumerator Split(StringView[] separators) public StringStringSplitEnumerator Split(Span<StringView> separators)
{ {
return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None); return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, StringSplitOptions.None);
} }
public StringStringSplitEnumerator Split(StringView[] separators, int count) public StringStringSplitEnumerator Split(Span<StringView> separators, int count)
{ {
return StringStringSplitEnumerator(Ptr, Length, separators, count, StringSplitOptions.None); return StringStringSplitEnumerator(Ptr, Length, separators, count, StringSplitOptions.None);
} }
public StringStringSplitEnumerator Split(StringView[] separators, int count, StringSplitOptions options) public StringStringSplitEnumerator Split(Span<StringView> separators, int count, StringSplitOptions options)
{ {
return StringStringSplitEnumerator(Ptr, Length, separators, count, options); return StringStringSplitEnumerator(Ptr, Length, separators, count, options);
} }
public StringStringSplitEnumerator Split(StringView[] separators, StringSplitOptions options) public StringStringSplitEnumerator Split(Span<StringView> separators, StringSplitOptions options)
{ {
return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, options); return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, options);
} }

View file

@ -108,6 +108,7 @@ static
str.AppendF(format, args); str.AppendF(format, args);
}*/ }*/
[Warn("StackStringFormat has been deprecated and will be removed in the future. Consider switching to string interpolation or 'scope:: String()..AppendF'.")]
public static mixin StackStringFormat(String format, var arg1) public static mixin StackStringFormat(String format, var arg1)
{ {
var str = scope:: String(); var str = scope:: String();
@ -115,6 +116,7 @@ static
str str
} }
[Warn("StackStringFormat has been deprecated and will be removed in the future. Consider switching to string interpolation or 'scope:: String()..AppendF'.")]
public static mixin StackStringFormat(String format, var arg1, var arg2) public static mixin StackStringFormat(String format, var arg1, var arg2)
{ {
var str = scope:: String(); var str = scope:: String();
@ -122,6 +124,7 @@ static
str str
} }
[Warn("StackStringFormat has been deprecated and will be removed in the future. Consider switching to string interpolation or 'scope:: String()..AppendF'.")]
public static mixin StackStringFormat(String format, var arg1, var arg2, var arg3) public static mixin StackStringFormat(String format, var arg1, var arg2, var arg3)
{ {
var str = scope:: String(); var str = scope:: String();

View file

@ -2,7 +2,7 @@ using System.Diagnostics;
using System.Threading; using System.Threading;
namespace System.Text namespace System.Text
{ {
[StaticInitPriority(100)] [StaticInitPriority(200)]
abstract class Encoding abstract class Encoding
{ {
public enum DecodeError public enum DecodeError

View file

@ -8,7 +8,7 @@ namespace System.Threading
public delegate void ThreadStart(); public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(Object obj); public delegate void ParameterizedThreadStart(Object obj);
[StaticInitPriority(100)] [StaticInitPriority(200)]
public sealed class Thread public sealed class Thread
{ {
private int mInternalThread; private int mInternalThread;
@ -21,14 +21,15 @@ namespace System.Threading
bool mAutoDelete = true; bool mAutoDelete = true;
bool mJoinOnDelete; bool mJoinOnDelete;
bool mIsBackground;
static Monitor sMonitor = new .() ~ delete _; static Monitor sMonitor = new .() ~ DeleteAndNullify!(_);
static Event<delegate void()> sOnExit ~ _.Dispose(); static Event<delegate void()> sOnExit ~ _.Dispose();
Event<delegate void()> mOnExit ~ _.Dispose(); Event<delegate void()> mOnExit ~ _.Dispose();
public static Thread sMainThread ~ delete _; public static Thread sMainThread ~ delete _;
[StaticInitPriority(102)] [StaticInitPriority(202)]
struct RuntimeThreadInit struct RuntimeThreadInit
{ {
static Object Thread_Alloc() static Object Thread_Alloc()
@ -86,6 +87,8 @@ namespace System.Threading
thread.InformThreadNameChange(thread.mName); thread.InformThreadNameChange(thread.mName);
if (thread.mPriority != .Normal) if (thread.mPriority != .Normal)
thread.SetPriorityNative((.)thread.mPriority); thread.SetPriorityNative((.)thread.mPriority);
if (thread.mIsBackground)
thread.SetBackgroundNative(thread.mIsBackground);
int32 stackStart = 0; int32 stackStart = 0;
thread.SetStackStart((void*)&stackStart); thread.SetStackStart((void*)&stackStart);
@ -239,27 +242,27 @@ namespace System.Threading
} }
} }
public void Start() public void Start()
{ {
StartInternal(); StartInternal();
} }
public void Start(bool autoDelete) public void Start(bool autoDelete)
{ {
mAutoDelete = autoDelete; mAutoDelete = autoDelete;
Start(); Start();
} }
public void Start(Object parameter) public void Start(Object parameter)
{
if (mDelegate is ThreadStart)
{ {
Runtime.FatalError(); if (mDelegate is ThreadStart)
{
Runtime.FatalError();
}
mThreadStartArg = parameter;
StartInternal();
} }
mThreadStartArg = parameter;
StartInternal();
}
public void Start(Object parameter, bool autoDelete) public void Start(Object parameter, bool autoDelete)
{ {
mAutoDelete = autoDelete; mAutoDelete = autoDelete;
@ -384,10 +387,13 @@ namespace System.Threading
public ~this() public ~this()
{ {
using (sMonitor.Enter()) if (sMonitor != null)
{ {
mOnExit(); using (sMonitor.Enter())
sOnExit(); {
mOnExit();
sOnExit();
}
} }
if (mJoinOnDelete) if (mJoinOnDelete)
@ -403,8 +409,13 @@ namespace System.Threading
public bool IsBackground public bool IsBackground
{ {
get { return IsBackgroundNative(); } get { return mIsBackground; }
set { SetBackgroundNative(value); } set
{
mIsBackground = value;
if (mInternalThread != 0)
SetBackgroundNative(mIsBackground);
}
} }
public void SetJoinOnDelete(bool joinOnDelete) public void SetJoinOnDelete(bool joinOnDelete)

View file

@ -53,7 +53,7 @@ namespace System {
NoThrowOnInvalidTime = 2 NoThrowOnInvalidTime = 2
} }
[StaticInitPriority(100)] [StaticInitPriority(200)]
sealed public class TimeZoneInfo : IEquatable<TimeZoneInfo> sealed public class TimeZoneInfo : IEquatable<TimeZoneInfo>
{ {
// ---- SECTION: members supporting exposed properties -------------* // ---- SECTION: members supporting exposed properties -------------*
@ -2423,8 +2423,8 @@ namespace System {
if (dynamicKey.GetValue(c_firstEntryValue) case .Ok(let val)) if (dynamicKey.GetValue(c_firstEntryValue) case .Ok(let val))
first = val.Get<int32>(); first = val.Get<int32>();
int32 last = -1; int32 last = -1;
if (dynamicKey.GetValue(c_lastEntryValue) case .Ok(let val)) if (dynamicKey.GetValue(c_lastEntryValue) case .Ok(let val2))
last = val.Get<int32>(); last = val2.Get<int32>();
if ((first == -1) || (last == -1) || (first > last)) { if ((first == -1) || (last == -1) || (first > last)) {
rules = null; rules = null;

View file

@ -0,0 +1,5 @@
namespace System;
struct Tuple
{
}

View file

@ -5,6 +5,195 @@ using System.Diagnostics;
namespace System namespace System
{ {
public class TypeDeclaration
{
protected enum Flags : uint8
{
DeclaredInDependency = 1,
DeclaredInDependent = 2,
DeclaredInCurrent = 4,
AlwaysVisible = 8,
SometimesVisible = 0x10
}
protected TypeId mTypeId;
protected TypeId mOuterTypeId;
protected TypeFlags mTypeFlags;
protected Flags mFlags;
protected TypeCode mTypeCode;
public static TypeDeclaration.Enumerator TypeDeclarations
{
get
{
return .();
}
}
public TypeCode TypeCode => mTypeCode;
public TypeId TypeId => mTypeId;
public TypeDeclaration BaseType
{
get
{
if (Compiler.IsComptime)
{
int32 baseTypeId = Type.[Friend]Comptime_Type_GetBaseType((.)mTypeId);
return Type.[Friend]Comptime_GetTypeDeclarationById(baseTypeId);
}
return null;
}
}
public TypeDeclaration OuterType
{
get
{
if (Compiler.IsComptime)
return Type.[Friend]Comptime_GetTypeDeclarationById((.)mOuterTypeId);
return null;
}
}
public bool DeclaredInDependency => mFlags.HasFlag(.DeclaredInDependency);
public bool DeclaredInDependent => mFlags.HasFlag(.DeclaredInDependent);
public bool DeclaredInCurrent => mFlags.HasFlag(.DeclaredInCurrent);
public bool AlwaysVisible => mFlags.HasFlag(.AlwaysVisible);
public bool SometimesVisible => mFlags.HasFlag(.SometimesVisible);
public Type ResolvedType => Compiler.IsComptime ? Type.[Friend]Comptime_GetTypeById((.)mTypeId) : null;
public void GetFullName(String strBuffer)
{
if (Compiler.IsComptime)
strBuffer.Append(Type.[Friend]Comptime_Type_ToString((.)mTypeId));
}
public void GetName(String strBuffer)
{
if (Compiler.IsComptime)
strBuffer.Append(Type.[Friend]Comptime_TypeName_ToString((.)mTypeId));
}
public void GetNamespace(String strBuffer)
{
if (Compiler.IsComptime)
strBuffer.Append(Type.[Friend]Comptime_Namespace_ToString((.)mTypeId));
}
public bool HasCustomAttribute<T>() where T : Attribute
{
if (Compiler.IsComptime)
{
int32 attrIdx = -1;
Type attrType = null;
repeat
{
attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType((int32)TypeId, ++attrIdx);
if (attrType == typeof(T))
return true;
}
while (attrType != null);
return false;
}
return false;
}
public Result<T> GetCustomAttribute<T>() where T : Attribute
{
if (Compiler.IsComptime)
{
int32 attrIdx = -1;
Type attrType = null;
repeat
{
attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType((int32)TypeId, ++attrIdx);
if (attrType == typeof(T))
{
T val = ?;
if (Type.[Friend]Comptime_Type_GetCustomAttribute((int32)TypeId, attrIdx, &val))
return val;
}
}
while (attrType != null);
return .Err;
}
return .Err;
}
[Comptime]
public AttributeInfo.ComptimeTypeCustomAttributeEnumerator GetCustomAttributes()
{
return .((int32)TypeId);
}
public struct Enumerator : IEnumerator<TypeDeclaration>
{
int32 mCurId;
public Result<TypeDeclaration> GetNext() mut
{
while (true)
{
if (!Compiler.IsComptime)
{
Runtime.FatalError("Runtime type declarations are not supported");
}
else
{
var typeDecl = Type.[Friend]Comptime_GetNextTypeDeclaration(mCurId);
if (typeDecl != null)
{
mCurId = (.)typeDecl.TypeId;
return .Ok(typeDecl);
}
return .Err;
}
}
}
}
public static TypeDeclaration GetById(TypeId typeId) => Type.[Friend]Comptime_GetTypeDeclarationById((.)typeId);
public static Result<TypeDeclaration> GetByName(StringView typeName)
{
if (Compiler.IsComptime)
{
var type = Type.[Friend]Comptime_GetTypeDeclarationByName(typeName);
if (type == null)
return .Err;
return type;
}
return .Err;
}
public override void ToString(String strBuffer)
{
GetFullName(strBuffer);
}
public bool HasDeclaredField(StringView fieldName)
{
if (Compiler.IsComptime)
return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 0, fieldName);
return false;
}
public bool HasDeclaredMethod(StringView fieldName)
{
if (Compiler.IsComptime)
return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 1, fieldName);
return false;
}
public bool HasDeclaredProperty(StringView fieldName)
{
if (Compiler.IsComptime)
return Type.[Friend]Comptime_Type_HasDeclaredMember((.)mTypeId, 2, fieldName);
return false;
}
}
struct ClassVData struct ClassVData
{ {
public int mType; public int mType;
@ -32,6 +221,21 @@ namespace System
protected uint8 mAlign; protected uint8 mAlign;
protected uint8 mAllocStackCountOverride; protected uint8 mAllocStackCountOverride;
public TypeDeclaration TypeDeclaration
{
get
{
if (!Compiler.IsComptime)
{
Runtime.FatalError("Runtime type declarations are not supported");
}
else
{
return Comptime_GetTypeDeclarationById((.)mTypeId);
}
}
}
public static TypeId TypeIdEnd public static TypeId TypeIdEnd
{ {
get get
@ -48,6 +252,14 @@ namespace System
} }
} }
public static TypeDeclaration.Enumerator TypeDeclarations
{
get
{
return .();
}
}
public int32 Size public int32 Size
{ {
get get
@ -453,6 +665,17 @@ namespace System
} }
} }
public virtual TypeInstance WrappedType
{
get
{
if (Compiler.IsComptime)
return Comptime_GetWrappedType((.)mTypeId) as TypeInstance;
return null;
}
}
public virtual TypeInstance.InterfaceEnumerator Interfaces public virtual TypeInstance.InterfaceEnumerator Interfaces
{ {
get get
@ -551,9 +774,17 @@ namespace System
public int64 mData; public int64 mData;
} }
static extern TypeDeclaration Comptime_GetTypeDeclarationById(int32 typeId);
static extern TypeDeclaration Comptime_GetTypeDeclarationByName(StringView name);
static extern TypeDeclaration Comptime_GetNextTypeDeclaration(int32 lastTypeId);
static extern int32 Comptime_Type_GetBaseType(int32 typeId);
static extern bool Comptime_Type_HasDeclaredMember(int32 typeId, int32 kind, StringView name);
static extern Type Comptime_GetTypeById(int32 typeId); static extern Type Comptime_GetTypeById(int32 typeId);
static extern Type Comptime_GetWrappedType(int32 typeId);
static extern Type Comptime_GetTypeByName(StringView name); static extern Type Comptime_GetTypeByName(StringView name);
static extern String Comptime_Type_ToString(int32 typeId); static extern String Comptime_Type_ToString(int32 typeId);
static extern String Comptime_TypeName_ToString(int32 typeId);
static extern String Comptime_Namespace_ToString(int32 typeId);
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs); static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeIdx, void* dataPtr); static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeIdx, void* dataPtr);
static extern bool Comptime_Field_GetCustomAttribute(int32 typeId, int32 fieldIdx, int32 attributeIdx, void* dataPtr); static extern bool Comptime_Field_GetCustomAttribute(int32 typeId, int32 fieldIdx, int32 attributeIdx, void* dataPtr);
@ -660,6 +891,15 @@ namespace System
return type == this || (type.IsTypedPrimitive && type.UnderlyingType == this); return type == this || (type.IsTypedPrimitive && type.UnderlyingType == this);
} }
public virtual bool ImplementsInterface(Type checkInterface)
{
var wrappedType = WrappedType;
if (wrappedType != null)
return wrappedType.ImplementsInterface(checkInterface);
return false;
}
public virtual Result<FieldInfo> GetField(String fieldName) public virtual Result<FieldInfo> GetField(String fieldName)
{ {
return .Err; return .Err;
@ -752,8 +992,9 @@ namespace System
#if !BF_REFLECT_MINIMAL #if !BF_REFLECT_MINIMAL
GetFullName(strBuffer); GetFullName(strBuffer);
#else #else
strBuffer.Append("Type#"); strBuffer.Append("comptype(");
mTypeId.ToString(strBuffer); ((int32)mTypeId).ToString(strBuffer);
strBuffer.Append(")");
#endif #endif
} }
@ -766,7 +1007,7 @@ namespace System
while (true) while (true)
{ {
if (Compiler.IsComptime) if (Compiler.IsComptime)
Runtime.FatalError("Comptime type enumeration not supported"); Runtime.FatalError("Comptime type enumeration not supported. Consider enumerating over TypeDeclaration.Types");
if (mCurId >= sTypeCount) if (mCurId >= sTypeCount)
return .Err; return .Err;
@ -838,7 +1079,13 @@ namespace System
namespace System.Reflection namespace System.Reflection
{ {
public struct TypeId : int32 {} public struct TypeId : int32
{
public override void ToString(String strBuffer)
{
strBuffer.AppendF($"TypeId#{(int32)this}");
}
}
[Ordered, AlwaysInclude(AssumeInstantiated=true)] [Ordered, AlwaysInclude(AssumeInstantiated=true)]
public class TypeInstance : Type public class TypeInstance : Type
@ -1036,6 +1283,19 @@ namespace System.Reflection
} }
} }
public override bool ImplementsInterface(Type checkInterface)
{
for (int ifaceIdx < mInterfaceCount)
{
if (mInterfaceDataPtr[ifaceIdx].mInterfaceType == checkInterface.TypeId)
return true;
}
var baseType = BaseType;
if (baseType != null)
return baseType.ImplementsInterface(checkInterface);
return false;
}
public override void GetFullName(String strBuffer) public override void GetFullName(String strBuffer)
{ {
if (mTypeFlags.HasFlag(TypeFlags.Tuple)) if (mTypeFlags.HasFlag(TypeFlags.Tuple))
@ -1317,7 +1577,8 @@ namespace System.Reflection
public override void GetFullName(String strBuffer) public override void GetFullName(String strBuffer)
{ {
strBuffer.Append("const "); strBuffer.Append("const ");
switch (GetType(mValueType)) var type = GetType(mValueType);
switch (type)
{ {
case typeof(float): case typeof(float):
(*(float*)&mValue).ToString(strBuffer); (*(float*)&mValue).ToString(strBuffer);
@ -1332,6 +1593,10 @@ namespace System.Reflection
strBuffer.Append('\''); strBuffer.Append('\'');
case typeof(uint64), typeof(uint): case typeof(uint64), typeof(uint):
(*(uint64*)&mValue).ToString(strBuffer); (*(uint64*)&mValue).ToString(strBuffer);
case typeof(String):
int32 stringId = *(int32*)&mValue;
String str = String.GetById(stringId);
str.Quote(strBuffer);
default: default:
mValue.ToString(strBuffer); mValue.ToString(strBuffer);
} }
@ -1409,7 +1674,11 @@ namespace System.Reflection
{ {
if (i > 0) if (i > 0)
strBuffer.Append(", "); strBuffer.Append(", ");
Type.GetType(mResolvedTypeRefs[i]).GetFullName(strBuffer); var genericArg = Type.GetType(mResolvedTypeRefs[i]);
if (genericArg != null)
genericArg.GetFullName(strBuffer);
else
strBuffer.Append("???");
} }
strBuffer.Append('>'); strBuffer.Append('>');
} }
@ -1445,7 +1714,7 @@ namespace System.Reflection
int32 stackCount = Compiler.Options.AllocStackCount; int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0) if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride; stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount); obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount, 0);
#else #else
void* mem = new [Align(16)] uint8[arraySize]* (?); void* mem = new [Align(16)] uint8[arraySize]* (?);
obj = Internal.UnsafeCastToObject(mem); obj = Internal.UnsafeCastToObject(mem);
@ -1505,6 +1774,7 @@ namespace System.Reflection
Static = 0x200000, Static = 0x200000,
Abstract = 0x400000, Abstract = 0x400000,
HasAppendWantMark = 0x800000,
} }
public enum FieldFlags : uint16 public enum FieldFlags : uint16
@ -1527,9 +1797,9 @@ namespace System.Reflection
Appended = 0x1000, Appended = 0x1000,
} }
public enum MethodFlags : uint16 public enum MethodFlags : uint32
{ {
MethodAccessMask = 0x0007, case MethodAccessMask = 0x0007,
Protected = 0x0003, Protected = 0x0003,
Public = 0x0006, Public = 0x0006,
@ -1547,5 +1817,26 @@ namespace System.Reflection
ThisCall = 0x3000, // Purposely resuing StdCall|FastCall ThisCall = 0x3000, // Purposely resuing StdCall|FastCall
Mutating = 0x4000, Mutating = 0x4000,
Constructor = 0x8000, Constructor = 0x8000,
AppendBit0 = 0x10000,
AppendBit1 = 0x20000,
CheckedBit0 = 0x40000,
CheckedBit1 = 0x80000;
public AllowAppendKind AllowAppendKind => (.)(int32)(this / AppendBit0);
public CheckedKind CheckedKind => (.)(int32)(this / CheckedBit0);
}
public enum AllowAppendKind
{
No,
Yes,
ZeroGap
}
public enum CheckedKind
{
NotSet,
Checked,
Unchecked
} }
} }

View file

@ -61,7 +61,7 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
// Dumb, make better. // Dumb, make better.
char8[] strChars = scope:: char8[16]; char8[16] strChars = ?;
int32 char8Idx = 14; int32 char8Idx = 14;
uint32 valLeft = (uint32)this; uint32 valLeft = (uint32)this;
while (valLeft > 0) while (valLeft > 0)
@ -73,7 +73,7 @@ namespace System
if (char8Idx == 14) if (char8Idx == 14)
strChars[char8Idx--] = '0'; strChars[char8Idx--] = '0';
char8* char8Ptr = &strChars[char8Idx + 1]; char8* char8Ptr = &strChars[char8Idx + 1];
strBuffer.Append(char8Ptr); strBuffer.Append(char8Ptr, 14 - char8Idx);
} }
void ToString(String strBuffer, int minNumerals) void ToString(String strBuffer, int minNumerals)

View file

@ -73,7 +73,7 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
// Dumb, make better. // Dumb, make better.
char8[] strChars = scope:: char8[22]; char8[22] strChars = ?;
int32 char8Idx = 20; int32 char8Idx = 20;
uint64 valLeft = (uint64)this; uint64 valLeft = (uint64)this;
while (valLeft > 0) while (valLeft > 0)
@ -85,7 +85,7 @@ namespace System
if (char8Idx == 20) if (char8Idx == 20)
strChars[char8Idx--] = '0'; strChars[char8Idx--] = '0';
char8* char8Ptr = &strChars[char8Idx + 1]; char8* char8Ptr = &strChars[char8Idx + 1];
strBuffer.Append(char8Ptr); strBuffer.Append(char8Ptr, 20 - char8Idx);
} }
public static Result<uint64, ParseError> Parse(StringView val, NumberStyles style = .Number, CultureInfo cultureInfo = null) public static Result<uint64, ParseError> Parse(StringView val, NumberStyles style = .Number, CultureInfo cultureInfo = null)

View file

@ -1,10 +1,15 @@
namespace System namespace System
{ {
struct Void : void struct Void : void, IHashable
{ {
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
strBuffer.Append("void"); strBuffer.Append("void");
} }
public int GetHashCode()
{
return 0;
}
} }
} }

View file

@ -107,6 +107,11 @@ namespace System
public int32 Height => bottom - top; public int32 Height => bottom - top;
} }
public struct Point : this(int32 x, int32 y)
{
}
[CRepr] [CRepr]
public struct OpenFileName public struct OpenFileName
{ {
@ -364,11 +369,15 @@ namespace System
return .Ok; return .Ok;
} }
public Result<void> GetValue(StringView name, String outData) public Result<void> GetValue(StringView name, String outData, bool* isExpanded = null)
{ {
if (isExpanded != null)
*isExpanded = false;
bool gotData = false; bool gotData = false;
GetValue(name, scope [?] (regType, regData) => GetValue(name, scope [?] (regType, regData) =>
{ {
if (isExpanded != null)
*isExpanded = regType == Windows.REG_EXPAND_SZ;
if ((regType == Windows.REG_SZ) || (regType == Windows.REG_EXPAND_SZ)) if ((regType == Windows.REG_SZ) || (regType == Windows.REG_EXPAND_SZ))
{ {
gotData = true; gotData = true;
@ -469,7 +478,7 @@ namespace System
public Result<void> SetValueExpand(StringView name, StringView strValue) public Result<void> SetValueExpand(StringView name, StringView strValue)
{ {
let result = Windows.RegSetValueExA(this, name.ToScopeCStr!(), 0, Windows.REG_EXPAND_SZ, strValue.ToScopeCStr!(), (uint32)strValue.Length + 1); let result = Windows.RegSetValueExA(this, name.ToScopeCStr!(), 0, Windows.REG_EXPAND_SZ, strValue.ToScopeCStr!(), (uint32)strValue.Length + 1);
if (result != 0) if (result != 0)
return .Err; return .Err;
return .Ok; return .Ok;
@ -1703,6 +1712,12 @@ namespace System
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)] [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern HWnd SetActiveWindow(HWnd wnd); public static extern HWnd SetActiveWindow(HWnd wnd);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern HWnd SetForegroundWindow(HWnd wnd);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern HWnd GetForegroundWindow();
[CLink, CallingConvention(.Stdcall)] [CLink, CallingConvention(.Stdcall)]
public static extern int CallWindowProcA(int wndProc, HWnd hWnd, int32 msg, int wParam, int lParam); public static extern int CallWindowProcA(int wndProc, HWnd hWnd, int32 msg, int wParam, int lParam);
@ -1749,6 +1764,12 @@ namespace System
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)] [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern IntBool SetWindowPos(HWnd hWnd, HWnd hWndAfter, int x, int y, int cx, int cy, int flags); public static extern IntBool SetWindowPos(HWnd hWnd, HWnd hWndAfter, int x, int y, int cx, int cy, int flags);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern IntBool GetClientRect(HWnd hWnd, out Rect rect);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern IntBool ClientToScreen(HWnd hWnd, ref Point rect);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)] [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern IntBool PostMessageW(HWnd hWnd, int32 msg, int wParam, int lParam); public static extern IntBool PostMessageW(HWnd hWnd, int32 msg, int wParam, int lParam);
@ -1756,7 +1777,7 @@ namespace System
public static extern int32 SendMessageW(HWnd hWnd, int32 msg, int wParam, int lParam); public static extern int32 SendMessageW(HWnd hWnd, int32 msg, int wParam, int lParam);
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)] [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
public static extern int32 SendMessageTimeoutW(HWnd hWnd, int32 msg, int wParam, int lParam, int32 flags, int32 timeout, int32* result); public static extern int32 SendMessageTimeoutW(HWnd hWnd, int32 msg, int wParam, int lParam, int32 flags, int32 timeout, int* result);
[Import("user32.lib "), CLink, CallingConvention(.Stdcall)] [Import("user32.lib "), CLink, CallingConvention(.Stdcall)]
public static extern HWnd SetFocus(HWnd hWnd); public static extern HWnd SetFocus(HWnd hWnd);

View file

@ -49,10 +49,10 @@ namespace bf
BFRT_EXPORT static void Dbg_ObjectCreatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData); BFRT_EXPORT static void Dbg_ObjectCreatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static void Dbg_ObjectAllocated(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData); BFRT_EXPORT static void Dbg_ObjectAllocated(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static void Dbg_ObjectAllocatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData); BFRT_EXPORT static void Dbg_ObjectAllocatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::Reflection::TypeInstance* typeInst, intptr size); BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::Reflection::TypeInstance* typeInst, intptr size);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDept); BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDept, uint8 allocFlags);
BFRT_EXPORT static void Dbg_MarkObjectDeleted(bf::System::Object* obj); BFRT_EXPORT static void Dbg_MarkObjectDeleted(bf::System::Object* obj);
BFRT_EXPORT static void Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData); BFRT_EXPORT static void Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData, intptr size, uint8 allocFlags);
BFRT_EXPORT static void Dbg_ObjectPreDelete(bf::System::Object* obj); BFRT_EXPORT static void Dbg_ObjectPreDelete(bf::System::Object* obj);
BFRT_EXPORT static void Dbg_ObjectPreCustomDelete(bf::System::Object* obj); BFRT_EXPORT static void Dbg_ObjectPreCustomDelete(bf::System::Object* obj);
@ -315,19 +315,20 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::Reflection::TypeInstan
//#define DBG_OBJECTEND //#define DBG_OBJECTEND
bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDepth) bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDepth, uint8 allocFlags)
{ {
void* stackTrace[1024]; void* stackTrace[1024];
int capturedTraceCount = 0; int capturedTraceCount = 0;
intptr allocSize = size; intptr allocSize = size;
bool largeAllocInfo = false; bool largeAllocInfo = false;
if ((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0) if ((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0)
{ {
if (maxStackTraceDepth > 1) if (maxStackTraceDepth > 1)
{ {
capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024)); capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024));
const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1; const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1;
if ((capturedTraceCount > 255) || (size >= maxSmallObjectSize)) if ((capturedTraceCount > 255) || (size >= maxSmallObjectSize))
{ {
largeAllocInfo = true; largeAllocInfo = true;
@ -336,6 +337,12 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
else else
allocSize += capturedTraceCount * sizeof(intptr); allocSize += capturedTraceCount * sizeof(intptr);
} }
// Append want mark
if ((allocFlags & 1) != 0)
{
allocSize += 4 * sizeof(intptr);
}
} }
#ifdef DBG_OBJECTEND #ifdef DBG_OBJECTEND
@ -385,7 +392,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
intptr dbgAllocInfo; intptr dbgAllocInfo;
auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated; auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated;
if (maxStackTraceDepth <= 1) if ((maxStackTraceDepth <= 1) && (allocFlags == 0))
dbgAllocInfo = (intptr)BF_RETURN_ADDRESS; dbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
else else
{ {
@ -393,13 +400,13 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{ {
classVDataVal |= (intptr)BfObjectFlag_AllocInfo; classVDataVal |= (intptr)BfObjectFlag_AllocInfo;
dbgAllocInfo = size; dbgAllocInfo = size;
*(intptr*)((uint8*)result + size) = capturedTraceCount; *(intptr*)((uint8*)result + size) = (capturedTraceCount << 8) | allocFlags;
memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr)); memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr));
} }
else else
{ {
classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short; classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short;
dbgAllocInfo = (size << 16) | capturedTraceCount; dbgAllocInfo = (size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr)); memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr));
} }
} }
@ -424,13 +431,27 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
return result; return result;
} }
void Internal::Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData) void Internal::Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData, intptr totalSize, uint8 allocFlags)
{ {
BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0); BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0);
result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc; result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc;
#ifndef BFRT_NODBGFLAGS #ifndef BFRT_NODBGFLAGS
result->mDbgAllocInfo = (intptr)BF_RETURN_ADDRESS; if ((allocFlags & 1) == 0)
{
result->mDbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
}
else
{
int size = (int)(totalSize - sizeof(intptr) - sizeof(intptr) * 4);
int capturedTraceCount = 1;
*(intptr*)((uint8*)result + size) = (intptr)BF_RETURN_ADDRESS;
memset((uint8*)result + size + sizeof(intptr), 0, sizeof(intptr) * 4);
result->mDbgAllocInfo = ((intptr)size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
BF_FULL_MEMORY_FENCE();
result->mClassVData |= (intptr)BfObjectFlag_AllocInfo_Short;
}
#endif #endif
} }

View file

@ -2180,6 +2180,12 @@ void BFGC::AddPendingThread(BfInternalThread* internalThread)
mPendingThreads.TryAdd(internalThread->mThreadId, internalThread); mPendingThreads.TryAdd(internalThread->mThreadId, internalThread);
} }
void BFGC::Disable()
{
StopCollecting();
mGracelessShutdown = true;
}
void BFGC::Shutdown() void BFGC::Shutdown()
{ {
if (mShutdown) if (mShutdown)
@ -2664,10 +2670,13 @@ void BFGC::WriteDebugDumpState()
{ {
//const bf::System::Type* bfTypeRootData = ((bf::System::Type*)obj->GetTypeSafe())->mTypeRootData; //const bf::System::Type* bfTypeRootData = ((bf::System::Type*)obj->GetTypeSafe())->mTypeRootData;
bf::System::Type* bfType = obj->GetTypeSafe(); bf::System::Type* bfType = obj->GetTypeSafe();
while ((int) debugInfoVector.size() <= bfType->mTypeId)
auto typeData = bfType->GetTypeData();
while ((int) debugInfoVector.size() <= typeData->mTypeId)
debugInfoVector.push_back(DebugInfo()); debugInfoVector.push_back(DebugInfo());
DebugInfo* debugInfo = &debugInfoVector[bfType->mTypeId]; DebugInfo* debugInfo = &debugInfoVector[typeData->mTypeId];
debugInfo->mType = obj->GetTypeSafe(); debugInfo->mType = obj->GetTypeSafe();
debugInfo->mCount++; debugInfo->mCount++;
int objSize = BFGetObjectSize(obj); int objSize = BFGetObjectSize(obj);
@ -2896,6 +2905,11 @@ void GC::RemoveStackMarkableObject(Object* obj)
gBFGC.RemoveStackMarkableObject(obj); gBFGC.RemoveStackMarkableObject(obj);
} }
void GC::Disable()
{
gBFGC.Disable();
}
void GC::Shutdown() void GC::Shutdown()
{ {
gBFGC.Shutdown(); gBFGC.Shutdown();

View file

@ -397,6 +397,7 @@ public:
void AddStackMarkableObject(bf::System::Object* obj); void AddStackMarkableObject(bf::System::Object* obj);
void RemoveStackMarkableObject(bf::System::Object* obj); void RemoveStackMarkableObject(bf::System::Object* obj);
void AddPendingThread(BfInternalThread* internalThread); void AddPendingThread(BfInternalThread* internalThread);
void Disable();
void Shutdown(); void Shutdown();
void InitDebugDump(); void InitDebugDump();
void EndDebugDump(); void EndDebugDump();
@ -474,7 +475,8 @@ namespace bf
BFRT_EXPORT static void AddPendingThread(void* internalThreadInfo); BFRT_EXPORT static void AddPendingThread(void* internalThreadInfo);
public: public:
BFRT_EXPORT static void Shutdown(); BFRT_EXPORT static void Disable();
BFRT_EXPORT static void Shutdown();
BFRT_EXPORT static void Collect(bool async); BFRT_EXPORT static void Collect(bool async);
BFRT_EXPORT static void Report(); BFRT_EXPORT static void Report();
BFRT_EXPORT static void Mark(Object* obj); BFRT_EXPORT static void Mark(Object* obj);

View file

@ -115,16 +115,18 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
if (rawAllocData != NULL) if (rawAllocData != NULL)
{ {
if (rawAllocData->mMarkFunc != NULL) if (rawAllocData->mMarkFunc != NULL)
{ {
intptr extraDataSize = sizeof(intptr); intptr extraDataSize = sizeof(intptr);
if (rawAllocData->mMaxStackTrace == 1) if (rawAllocData->mMaxStackTrace == 1)
{ {
extraDataSize += sizeof(intptr); extraDataSize += sizeof(intptr) + 2;
extraDataSize += *(uint16*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr) - 2);
} }
else if (rawAllocData->mMaxStackTrace > 1) else if (rawAllocData->mMaxStackTrace > 1)
{ {
intptr stackTraceCount = *(intptr*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr)); intptr stackTraceCount = *(intptr*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr));
extraDataSize += (1 + stackTraceCount) * sizeof(intptr); extraDataSize += (1 + stackTraceCount) * sizeof(intptr) + 2;
extraDataSize += *(uint16*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
} }
struct MarkTarget struct MarkTarget
@ -132,17 +134,21 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
}; };
typedef void(MarkTarget::*MarkFunc)(); typedef void(MarkTarget::*MarkFunc)();
MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc; MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc;
// It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem auto typeData = rawAllocData->mType->GetTypeData();
// because we can safely mark on complete random memory -- pointer values are always validated before being followed if (typeData != NULL)
intptr elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
if (elemStride > 0)
{ {
intptr dataSize = elementSize - extraDataSize; // It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem
intptr elemCount = dataSize / elemStride; // because we can safely mark on complete random memory -- pointer values are always validated before being followed
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++) intptr elemStride = BF_ALIGN(typeData->mSize, typeData->mAlign);
if (elemStride > 0)
{ {
(((MarkTarget*)((uint8*)spanPtr + elemIdx * elemStride))->*markFunc)(); intptr dataSize = elementSize - extraDataSize;
intptr elemCount = dataSize / elemStride;
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++)
{
(((MarkTarget*)((uint8*)spanPtr + elemIdx * elemStride))->*markFunc)();
}
} }
} }
} }
@ -282,13 +288,13 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
if (rawAllocData->mType != NULL) if (rawAllocData->mType != NULL)
{ {
intptr typeSize; bf::System::Type_NOFLAGS* typeData = rawAllocData->mType->GetTypeData();
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0) if (typeData != NULL)
typeSize = rawAllocData->mType->mSize; {
else intptr typeSize = typeData->mSize;
typeSize = ((bf::System::Type_NOFLAGS*)rawAllocData->mType)->mSize; if (typeSize > 0)
if (typeSize > 0) rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize;
rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize; }
} }
else else
rawLeakInfo.mDataCount = 1; rawLeakInfo.mDataCount = 1;
@ -558,8 +564,8 @@ void* BfRawAllocate(intptr size, bf::System::DbgRawAllocData* rawAllocData, void
markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - 2); markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - 2);
} }
else if (rawAllocData->mMaxStackTrace > 1) else if (rawAllocData->mMaxStackTrace > 1)
{ {
memcpy((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr), &stackTraceCount, sizeof(intptr)); *(intptr*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr)) = stackTraceCount;
memcpy((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount*sizeof(intptr), stackTraceInfo, stackTraceCount*sizeof(intptr)); memcpy((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount*sizeof(intptr), stackTraceInfo, stackTraceCount*sizeof(intptr));
markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2); markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
} }

View file

@ -59,6 +59,8 @@ namespace bf
{ {
namespace System namespace System
{ {
class Type_NOFLAGS;
struct DbgRawAllocData struct DbgRawAllocData
{ {
Type* mType; Type* mType;
@ -84,7 +86,7 @@ namespace bf
void*(*Alloc)(intptr size); void*(*Alloc)(intptr size);
void(*Free)(void* ptr); void(*Free)(void* ptr);
void(*Object_Delete)(bf::System::Object* obj); void(*Object_Delete)(bf::System::Object* obj);
void* mUnused0; Type_NOFLAGS*(*ClassVData_GetTypeDataPtr)(bf::System::ClassVData* classVData);
bf::System::Type* (*Object_GetType)(bf::System::Object* obj); bf::System::Type* (*Object_GetType)(bf::System::Object* obj);
void(*Object_GCMarkMembers)(bf::System::Object* obj); void(*Object_GCMarkMembers)(bf::System::Object* obj);
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId); bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
@ -196,28 +198,25 @@ namespace bf
typedef int32 TypeId; typedef int32 TypeId;
enum BfTypeFlags : uint32
{
BfTypeFlag_HasAppendWantMark = 0x800000
};
class Type : public Object class Type : public Object
{ {
public: public:
int32 mSize;
TypeId mTypeId;
TypeId mBoxedId;
uint16 mTypeFlags;
int32 mMemberDataOffset;
uint8 mTypeCode;
uint8 mAlign;
Beefy::String GetFullName(); Beefy::String GetFullName();
Type_NOFLAGS* GetTypeData();
}; };
class Type_NOFLAGS class Type_NOFLAGS
{ {
public: public:
intptr mClassVData;
int32 mSize; int32 mSize;
TypeId mTypeId; TypeId mTypeId;
TypeId mBoxedId; TypeId mBoxedId;
uint16 mTypeFlags; BfTypeFlags mTypeFlags;
int32 mMemberDataOffset; int32 mMemberDataOffset;
uint8 mTypeCode; uint8 mTypeCode;
uint8 mAlign; uint8 mAlign;

View file

@ -306,6 +306,7 @@ void bf::System::Console::PutChars(char* ptr, int len)
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
putchar(ptr[i]); putchar(ptr[i]);
fflush(stdout);
} }
void bf::System::Console::ReopenHandles() void bf::System::Console::ReopenHandles()

View file

@ -20,3 +20,11 @@ Beefy::String bf::System::Type::GetFullName()
BFRTCALLBACKS.Object_Delete(strObj); BFRTCALLBACKS.Object_Delete(strObj);
return str; return str;
} }
bf::System::Type_NOFLAGS* bf::System::Type::GetTypeData()
{
if ((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0)
return BFRTCALLBACKS.ClassVData_GetTypeDataPtr((bf::System::ClassVData*)(mClassVData & ~0xFF));
else
return BFRTCALLBACKS.ClassVData_GetTypeDataPtr((bf::System::ClassVData*)(mClassVData));
}

View file

@ -17,6 +17,7 @@ BF_TLS_DECLSPEC Thread* Thread::sCurrentThread;
#endif #endif
static volatile int gLiveThreadCount; static volatile int gLiveThreadCount;
static volatile int gBackgroundThreadCount;
static Beefy::SyncEvent gThreadsDoneEvent; static Beefy::SyncEvent gThreadsDoneEvent;
#ifdef BF_PLATFORM_WINDOWS #ifdef BF_PLATFORM_WINDOWS
@ -132,8 +133,12 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread); bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
gBfRtCallbacks.Thread_ThreadProc(thread); gBfRtCallbacks.Thread_ThreadProc(thread);
bool isLastThread = BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) == 1;
if (internalThread->mIsBackground)
BfpSystem_InterlockedExchangeAdd32((uint32*)&gBackgroundThreadCount, -1);
bool isLastThread = (int32)BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) <= gBackgroundThreadCount + 1;
//printf("Stopping thread\n"); //printf("Stopping thread\n");
bool wantsDelete = false; bool wantsDelete = false;
@ -158,7 +163,7 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
delete internalThread; delete internalThread;
if (isLastThread) if (isLastThread)
gThreadsDoneEvent.Set(false); gThreadsDoneEvent.Set(false);
//printf("Thread stopped\n"); //printf("Thread stopped\n");
} }
@ -168,7 +173,7 @@ void BfInternalThread::WaitForAllDone()
if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0) if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
return; return;
while (gLiveThreadCount != 0) while (gLiveThreadCount > gBackgroundThreadCount)
{ {
// Clear out any old done events // Clear out any old done events
gThreadsDoneEvent.WaitFor(); gThreadsDoneEvent.WaitFor();
@ -303,12 +308,23 @@ void Thread::InternalFinalize()
bool Thread::IsBackgroundNative() bool Thread::IsBackgroundNative()
{ {
return false; auto internalThread = GetInternalThread();
if (internalThread == NULL)
return false;
return internalThread->mIsBackground;
} }
void Thread::SetBackgroundNative(bool isBackground) void Thread::SetBackgroundNative(bool isBackground)
{ {
auto internalThread = GetInternalThread();
if (internalThread == NULL)
return;
if (isBackground != internalThread->mIsBackground)
{
internalThread->mIsBackground = isBackground;
BfpSystem_InterlockedExchangeAdd32((uint32*)&gBackgroundThreadCount, isBackground ? 1 : -1);
}
} }
int Thread::GetThreadStateNative() int Thread::GetThreadStateNative()

View file

@ -111,6 +111,7 @@ public:
bool mStarted; bool mStarted;
bool mJoinOnDelete; bool mJoinOnDelete;
bool mIsManualInit; bool mIsManualInit;
bool mIsBackground;
BfpThread* mThreadHandle; BfpThread* mThreadHandle;
intptr mThreadId; intptr mThreadId;
Beefy::CritSect mCritSect; Beefy::CritSect mCritSect;
@ -126,6 +127,7 @@ public:
mIsSuspended = false; mIsSuspended = false;
mJoinOnDelete = true; mJoinOnDelete = true;
mIsManualInit = false; mIsManualInit = false;
mIsBackground = false;
mStackStart = 0; mStackStart = 0;
mThreadId = 0; mThreadId = 0;
} }

View file

@ -48,7 +48,7 @@ class Program
{ {
while (true) while (true)
{ {
switch (mPipe.ReadMessage(-1)) switch (mPipe.ReadMessage(20))
{ {
case .Ok(let msg): case .Ok(let msg):
uint8* ptr = msg.Ptr + 1; uint8* ptr = msg.Ptr + 1;

View file

@ -1,3 +1,4 @@
using System;
using Beefy.widgets; using Beefy.widgets;
using Beefy.gfx; using Beefy.gfx;
@ -16,8 +17,8 @@ namespace LogViewer
g.FillRect(0, 0, mWidth, mHeight); g.FillRect(0, 0, mWidth, mHeight);
var lineAndColumn = gApp.mBoard.mDocEdit.mEditWidgetContent.CursorLineAndColumn; var lineAndColumn = gApp.mBoard.mDocEdit.mEditWidgetContent.CursorLineAndColumn;
g.DrawString(StackStringFormat!("Ln {0}", lineAndColumn.mLine + 1), mWidth - 160, 2); g.DrawString(scope $"Ln {lineAndColumn.mLine + 1}", mWidth - 160, 2);
g.DrawString(StackStringFormat!("Col {0}", lineAndColumn.mColumn + 1), mWidth - 80, 2); g.DrawString(scope $"Col {lineAndColumn.mColumn + 1}", mWidth - 80, 2);
if ((gApp.mBoard.mFilterDirtyCountdown != 0) || (gApp.mBoard.mRefreshing)) if ((gApp.mBoard.mFilterDirtyCountdown != 0) || (gApp.mBoard.mRefreshing))
g.DrawString("Refreshing", 8, 2); g.DrawString("Refreshing", 8, 2);

View file

@ -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 "img/ImgEffects.h"
#include "util/AllocDebug.h" #include "util/AllocDebug.h"
@ -445,10 +446,11 @@ BF_EXPORT int BF_CALLTYPE BFWindow_GetDPI(BFWindow* window)
BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateRenderTarget(int width, int height, int destAlpha) BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateRenderTarget(int width, int height, int destAlpha)
{ {
Texture* texture = gBFApp->mRenderDevice->CreateRenderTarget(width, height, destAlpha != 0); Texture* texture = gBFApp->mRenderDevice->CreateRenderTarget(width, height, destAlpha != 0);
texture->mResetClear = true;
TextureSegment* aTextureSegment = new TextureSegment(); TextureSegment* aTextureSegment = new TextureSegment();
aTextureSegment->InitFromTexture(texture); aTextureSegment->InitFromTexture(texture);
return aTextureSegment; return aTextureSegment;
} }
@ -474,12 +476,12 @@ BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_LoadTexture(const char* fileName, int
BF_EXPORT void BF_CALLTYPE Gfx_Texture_SetBits(TextureSegment* textureSegment, int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits) BF_EXPORT void BF_CALLTYPE Gfx_Texture_SetBits(TextureSegment* textureSegment, int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{ {
textureSegment->mTexture->SetBits(destX, destY, destWidth, destHeight, srcPitch, bits); textureSegment->SetBits(destX, destY, destWidth, destHeight, srcPitch, bits);
} }
BF_EXPORT void BF_CALLTYPE Gfx_Texture_GetBits(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits) BF_EXPORT void BF_CALLTYPE Gfx_Texture_GetBits(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits)
{ {
textureSegment->mTexture->GetBits(srcX, srcY, srcWidth, srcHeight, destPitch, bits); textureSegment->GetBits(srcX, srcY, srcWidth, srcHeight, destPitch, bits);
} }
BF_EXPORT void BF_CALLTYPE Gfx_Texture_Delete(TextureSegment* textureSegment) BF_EXPORT void BF_CALLTYPE Gfx_Texture_Delete(TextureSegment* textureSegment)
@ -516,6 +518,93 @@ BF_EXPORT void BF_CALLTYPE Gfx_ModifyTextureSegment(TextureSegment* destTextureS
destTextureSegment->mScaleY = (float)abs(srcHeight); destTextureSegment->mScaleY = (float)abs(srcHeight);
} }
int32 FormatI32(const StringView& str)
{
String val = String(str);
if (val.StartsWith('#'))
{
return (int32)strtoll(val.c_str() + 1, NULL, 16);
}
if (val.StartsWith("0x"))
{
return (int32)strtoll(val.c_str() + 2, NULL, 16);
}
return atoi(val.c_str());
}
BF_EXPORT void BF_CALLTYPE Gfx_ApplyEffect(TextureSegment* destTextureSegment, TextureSegment* srcTextureSegment, char* optionsPtr)
{
BaseImageEffect* effect = NULL;
defer({
delete effect;
});
bool needsPremultiply = false;
String options = optionsPtr;
for (auto line : options.Split('\n'))
{
int eqPos = (int)line.IndexOf('=');
if (eqPos != -1)
{
StringView cmd = StringView(line, 0, eqPos);
StringView value = StringView(line, eqPos + 1);
if (cmd == "Effect")
{
if (value == "Stroke")
{
auto strokeEffect = new ImageStrokeEffect();
effect = strokeEffect;
strokeEffect->mPosition = 'OutF';
strokeEffect->mSize = 1;
strokeEffect->mColorFill.mColor = 0xFF000000;
}
}
if (cmd == "Size")
{
int32 size = FormatI32(value);
if (auto strokeEffect = dynamic_cast<ImageStrokeEffect*>(effect))
{
strokeEffect->mSize = size;
}
}
if (cmd == "Color")
{
uint32 color = (uint32)FormatI32(value);
if (auto strokeEffect = dynamic_cast<ImageStrokeEffect*>(effect))
{
strokeEffect->mColorFill.mColor = color;
if ((color & 0x00FFFFFF) != 0)
needsPremultiply = true;
}
}
}
}
if (effect != NULL)
{
ImageData destImageData;
ImageData srcImageData;
RectF srcRect = srcTextureSegment->GetRect();
RectF destRect = destTextureSegment->GetRect();
destTextureSegment->GetImageData(destImageData);
srcImageData.CreateNew(destImageData.mWidth, destImageData.mHeight);
srcTextureSegment->GetImageData(srcImageData,
(int)(destRect.width - srcRect.width) / 2,
(int)(destRect.height - srcRect.height) / 2);
effect->Apply(NULL, &srcImageData, &destImageData);
if (needsPremultiply)
destImageData.PremultiplyAlpha();
destTextureSegment->SetImageData(destImageData);
}
}
BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateTextureSegment(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight) BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateTextureSegment(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight)
{ {
Texture* texture = textureSegment->mTexture; Texture* texture = textureSegment->mTexture;
@ -742,10 +831,10 @@ BF_EXPORT void BF_CALLTYPE RenderState_SetWireframe(RenderState* renderState, bo
BF_EXPORT void BF_CALLTYPE RenderState_SetClip(RenderState* renderState, float x, float y, float width, float height) BF_EXPORT void BF_CALLTYPE RenderState_SetClip(RenderState* renderState, float x, float y, float width, float height)
{ {
BF_ASSERT((width >= 0) && (height >= 0)); BF_ASSERT((width >= 0) && (height >= 0));
renderState->mClipRect.mX = x; renderState->mClipRect.x = x;
renderState->mClipRect.mY = y; renderState->mClipRect.y = y;
renderState->mClipRect.mWidth = width; renderState->mClipRect.width = width;
renderState->mClipRect.mHeight = height; renderState->mClipRect.height = height;
if (!renderState->mClipped) if (!renderState->mClipped)
renderState->SetClipped(true); renderState->SetClipped(true);
} }

View file

@ -177,6 +177,7 @@
<LibraryPath>third_party\AK\lib\release;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(FrameworkSDKDir)\lib</LibraryPath> <LibraryPath>third_party\AK\lib\release;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(FrameworkSDKDir)\lib</LibraryPath>
<IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2007)\Include;C:\temp\wx\wxMSW-2.8.12\include;C:\temp\wx\wxMSW-2.8.12\include\msvc</IncludePath> <IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2007)\Include;C:\temp\wx\wxMSW-2.8.12\include;C:\temp\wx\wxMSW-2.8.12\include\msvc</IncludePath>
<OutDir>$(SolutionDir)\IDE\dist\</OutDir> <OutDir>$(SolutionDir)\IDE\dist\</OutDir>
<TargetName>$(ProjectName)64_Static</TargetName>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
@ -414,11 +415,12 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<PrecompiledHeader> <PrecompiledHeader>
</PrecompiledHeader> </PrecompiledHeader>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;BFSYSLIB_DYNAMIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;BFSYSLIB_DYNAMIC;BF_NO_FBX;FT2_BUILD_LIBRARY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>./; ./platform/win/; third_party/agg-2.4/include; third_party/agg-2.4/include/platform/win32; third_party/; third_party/libffi/i686-pc-cygwin; third_party/libffi/i686-pc-cygwin/include; third_party/libffi/include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>./;./platform/win/;./platform/sdl/;third_party/agg-2.4/include;third_party/agg-2.4/include/platform/win32;third_party/;third_party/libffi/i686-pc-cygwin;third_party/libffi/i686-pc-cygwin/include;third_party/libffi/include;third_party/SDL2-2.0.1/include;../extern/fbxsdk/include;third_party/freetype/include;../BeefLibs/SDL2/include</AdditionalIncludeDirectories>
<WholeProgramOptimization>false</WholeProgramOptimization>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -461,6 +463,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ClCompile Include="gfx\Texture.cpp" /> <ClCompile Include="gfx\Texture.cpp" />
<ClCompile Include="HeadlessApp.cpp" /> <ClCompile Include="HeadlessApp.cpp" />
<ClCompile Include="img\BFIData.cpp" /> <ClCompile Include="img\BFIData.cpp" />
<ClCompile Include="img\BMPData.cpp" />
<ClCompile Include="img\ImageAdjustments.cpp" /> <ClCompile Include="img\ImageAdjustments.cpp" />
<ClCompile Include="img\ImageData.cpp" /> <ClCompile Include="img\ImageData.cpp" />
<ClCompile Include="img\ImageUtils.cpp" /> <ClCompile Include="img\ImageUtils.cpp" />
@ -482,7 +485,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="platform\sdl\SdlBFApp.cpp"> <ClCompile Include="platform\sdl\SdlBFApp.cpp">
@ -492,7 +495,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="platform\win\CrashCatcher.cpp" /> <ClCompile Include="platform\win\CrashCatcher.cpp" />
@ -1947,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\MTRand.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" />
@ -1982,6 +1986,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ClInclude Include="gfx\Texture.h" /> <ClInclude Include="gfx\Texture.h" />
<ClInclude Include="HeadlessApp.h" /> <ClInclude Include="HeadlessApp.h" />
<ClInclude Include="img\BFIData.h" /> <ClInclude Include="img\BFIData.h" />
<ClInclude Include="img\BMPData.h" />
<ClInclude Include="img\ImageAdjustments.h" /> <ClInclude Include="img\ImageAdjustments.h" />
<ClInclude Include="img\ImageData.h" /> <ClInclude Include="img\ImageData.h" />
<ClInclude Include="img\ImageUtils.h" /> <ClInclude Include="img\ImageUtils.h" />
@ -2000,7 +2005,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClInclude> </ClInclude>
<ClInclude Include="platform\sdl\SdlBFApp.h"> <ClInclude Include="platform\sdl\SdlBFApp.h">
@ -2009,7 +2014,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClInclude> </ClInclude>
<ClInclude Include="platform\win\CrashCatcher.h" /> <ClInclude Include="platform\win\CrashCatcher.h" />
@ -2184,6 +2189,8 @@ 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\MTRand.h" />
<ClInclude Include="util\MultiDictionary.h" />
<ClInclude Include="util\MultiHashSet.h" /> <ClInclude Include="util\MultiHashSet.h" />
<ClInclude Include="util\PerfTimer.h" /> <ClInclude Include="util\PerfTimer.h" />
<ClInclude Include="util\Point.h" /> <ClInclude Include="util\Point.h" />

View file

@ -737,6 +737,12 @@
<ClCompile Include="third_party\putty\wildcard.c"> <ClCompile Include="third_party\putty\wildcard.c">
<Filter>src\third_party\putty</Filter> <Filter>src\third_party\putty</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="util\MTRand.cpp">
<Filter>src\util</Filter>
</ClCompile>
<ClCompile Include="img\BMPData.cpp">
<Filter>src\img</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Common.h"> <ClInclude Include="Common.h">
@ -1132,6 +1138,15 @@
<ClInclude Include="third_party\putty\wildcard.h"> <ClInclude Include="third_party\putty\wildcard.h">
<Filter>src\third_party\putty</Filter> <Filter>src\third_party\putty</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="util\MultiDictionary.h">
<Filter>src\util</Filter>
</ClInclude>
<ClInclude Include="util\MTRand.h">
<Filter>src\util</Filter>
</ClInclude>
<ClInclude Include="img\BMPData.h">
<Filter>src\img</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">

View file

@ -199,6 +199,7 @@
<ClCompile Include="gfx\Shader.cpp" /> <ClCompile Include="gfx\Shader.cpp" />
<ClCompile Include="gfx\Texture.cpp" /> <ClCompile Include="gfx\Texture.cpp" />
<ClCompile Include="img\BFIData.cpp" /> <ClCompile Include="img\BFIData.cpp" />
<ClCompile Include="img\BMPData.cpp" />
<ClCompile Include="img\ImageAdjustments.cpp" /> <ClCompile Include="img\ImageAdjustments.cpp" />
<ClCompile Include="img\ImageData.cpp" /> <ClCompile Include="img\ImageData.cpp" />
<ClCompile Include="img\ImageUtils.cpp" /> <ClCompile Include="img\ImageUtils.cpp" />
@ -908,6 +909,7 @@
<ClInclude Include="gfx\Shader.h" /> <ClInclude Include="gfx\Shader.h" />
<ClInclude Include="gfx\Texture.h" /> <ClInclude Include="gfx\Texture.h" />
<ClInclude Include="img\BFIData.h" /> <ClInclude Include="img\BFIData.h" />
<ClInclude Include="img\BMPData.h" />
<ClInclude Include="img\ImageAdjustments.h" /> <ClInclude Include="img\ImageAdjustments.h" />
<ClInclude Include="img\ImageData.h" /> <ClInclude Include="img\ImageData.h" />
<ClInclude Include="img\ImageUtils.h" /> <ClInclude Include="img\ImageUtils.h" />

View file

@ -590,6 +590,9 @@
<ClCompile Include="third_party\putty\wildcard.c"> <ClCompile Include="third_party\putty\wildcard.c">
<Filter>src\third_party\putty</Filter> <Filter>src\third_party\putty</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="img\BMPData.cpp">
<Filter>src\img</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Common.h"> <ClInclude Include="Common.h">
@ -907,6 +910,9 @@
<ClInclude Include="third_party\putty\wildcard.h"> <ClInclude Include="third_party\putty\wildcard.h">
<Filter>src\third_party\putty</Filter> <Filter>src\third_party\putty</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="img\BMPData.h">
<Filter>src\img</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">

View file

@ -142,6 +142,7 @@ file(GLOB SRC_FILES
img/ImageUtils.cpp img/ImageUtils.cpp
img/ImgEffects.cpp img/ImgEffects.cpp
img/JPEGData.cpp img/JPEGData.cpp
img/BMPData.cpp
img/PNGData.cpp img/PNGData.cpp
img/PSDReader.cpp img/PSDReader.cpp
img/PVRData.cpp img/PVRData.cpp

View file

@ -36,13 +36,13 @@ int CachedDataStream::GetSize()
return mStream->GetSize(); return mStream->GetSize();
} }
void CachedDataStream::Read(void* ptr, int size) int CachedDataStream::Read(void* ptr, int size)
{ {
Flush(); Flush();
mStream->Read(ptr, size); return mStream->Read(ptr, size);
} }
void CachedDataStream::Write(void* ptr, int size) int CachedDataStream::Write(void* ptr, int size)
{ {
while (size > 0) while (size > 0)
{ {
@ -59,6 +59,7 @@ void CachedDataStream::Write(void* ptr, int size)
size -= writeBytes; size -= writeBytes;
mDataPtr += writeBytes; mDataPtr += writeBytes;
} }
return size;
} }
int CachedDataStream::GetPos() int CachedDataStream::GetPos()

View file

@ -24,8 +24,8 @@ public:
virtual bool Eof() override; virtual bool Eof() override;
virtual int GetSize() override; virtual int GetSize() override;
virtual void Read(void* ptr, int size) override; virtual int Read(void* ptr, int size) override;
virtual void Write(void* ptr, int size) override; virtual int Write(void* ptr, int size) override;
virtual int GetPos() override; virtual int GetPos() override;
virtual void Seek(int size) override; virtual void Seek(int size) override;

View file

@ -1380,6 +1380,35 @@ void Beefy::BFFatalError(const char* message, const char* file, int line)
BFFatalError(String(message), String(file), line); BFFatalError(String(message), String(file), line);
} }
void MakeUpper(const StringImpl& theString) bool Beefy::ParseMemorySpan(const StringImpl& str, void*& outPtr, int& outSize, StringImpl* outKey)
{ {
#ifndef BF_SMALL
static int anonymousIdx = 0;
if (str.StartsWith("@"))
{
int colon = (int)str.IndexOf(':');
String addrStr = str.Substring(1, colon - 1);
String lenStr = str.Substring(colon + 1);
outPtr = (void*)(intptr)strtoll(addrStr.c_str(), NULL, 16);
outSize = (int)strtol(lenStr.c_str(), NULL, 10);
if (outKey != NULL)
{
int nextColon = (int)str.IndexOf(':', colon + 1);
if (nextColon > 0)
{
*outKey = str.Substring(nextColon + 1);
}
else
{
int dotPos = (int)str.IndexOf('.', colon + 1);
*outKey = StrFormat("ANON_%d", anonymousIdx++) + str.Substring(dotPos);
}
}
return true;
}
#endif
return false;
} }

Some files were not shown because too many files have changed in this diff Show more