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
*/llvm-*
*/llvm_*
*/_llvm*
*/x64/*
**/Debug/*
**/Debug */*

View file

@ -108,7 +108,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<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>
<SupportJustMyCode>false</SupportJustMyCode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -152,7 +152,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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>
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>

View file

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

View file

@ -7,7 +7,7 @@ StartupObject = "BeefBuild.Program"
[Platform.Windows]
Description = "BeefBuild"
FileVersion = "0.43.5"
FileVersion = "0.43.6"
[Configs.Debug.Win32]
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"
CLibType = "Dynamic"
BeefLibType = "DynamicDebug"
DebugCommandArguments = "-proddir=c:\\proj\\BeefTest update BeefProj1"
DebugWorkingDirectory = "c:\\beef\\ide"
DebugCommandArguments = "-run"
DebugWorkingDirectory = "c:\\proj\\BeefTest"
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
PreprocessorMacros = ["DEBUG", "CLI"]

View file

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

View file

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

View file

@ -1,4 +1,5 @@
FileVersion = 1
Dependencies = {corlib = "*", MiniZ = "*"}
[Project]
Name = "Beefy2D"
@ -50,3 +51,7 @@ OtherLinkFlags = "$(LinkFlags) \"$(ProjectDir)/dist/BeefySysLib64.lib\""
CLibType = "Static"
BeefLibType = "Static"
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)
{
/*string[] newArgs = new string[args.Length + 1];

View file

@ -5,6 +5,7 @@ using System.Diagnostics;
using Beefy.gfx;
using Beefy.sys;
using System.IO;
using Beefy.geom;
#if MONOTOUCH
using MonoTouch;
@ -327,6 +328,9 @@ namespace Beefy
static void Static_NativeDragDropFileDelegate(void* window, char8* filePath) { GetBFWindow(window).DragDropFile(StringView(filePath)); }
#endif
public Rect<int32> ClientRect => .(mClientX, mClientY, mClientWidth, mClientHeight);
public Rect<int32> WindowRect => .(mX, mY, mWindowWidth, mWindowHeight);
public this()
{
}
@ -480,6 +484,11 @@ namespace Beefy
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()
{
BFWindow_SetForeground(mNativeWindow);

View file

@ -6,6 +6,7 @@ using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;
using Beefy.gfx;
namespace Beefy
{
@ -21,8 +22,6 @@ namespace Beefy
public static float Deg2Rad = Math.PI_f / 180.0f;
public static int32 Rand()
{
return mRandom.NextI32();
@ -33,6 +32,12 @@ namespace Beefy
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)
{
return left + (right - left) * pct;
@ -472,5 +477,12 @@ namespace Beefy
{
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)
{
str.AppendF($"{Normal:{Normal} D:{D}}");
str.AppendF($"{{Normal:{Normal} D:{D}}}");
}
#endregion

View file

@ -97,6 +97,14 @@ namespace Beefy.geom
public T CenterX => mX + mWidth / 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)
{
mX = x;
@ -236,6 +244,11 @@ namespace Beefy.geom
mHeight *= scaleY;
}
public void Scale(T scale) mut
{
Scale(scale, scale);
}
public void ScaleFrom(T scaleX, T scaleY, T centerX, T centerY) mut
{
Offset(-centerX, -centerY);
@ -249,6 +262,7 @@ namespace Beefy.geom
}
}
typealias RectI32 = Rect<int32>;
typealias Rect = Rect<float>;
typealias RectD = Rect<double>;
}

View file

@ -46,6 +46,11 @@ namespace Beefy.geom
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)
{
Vector2 newVec;
@ -104,6 +109,11 @@ namespace Beefy.geom
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)
{
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);
}
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)
{
mX = x;
@ -306,5 +308,7 @@ namespace Beefy.geom
{
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
public class DrawLayer
{
public static List<DrawLayer> sDrawLayers = new .() ~ delete _;
[CallingConvention(.Stdcall), CLink]
static extern void* DrawLayer_Create(void* window);
@ -33,10 +35,12 @@ namespace Beefy.gfx
public this(BFWindow window)
{
mNativeDrawLayer = DrawLayer_Create((window != null) ? (window.mNativeWindow) : null);
sDrawLayers.Add(this);
}
public ~this()
{
sDrawLayers.Remove(this);
DrawLayer_Delete(mNativeDrawLayer);
}

View file

@ -6,6 +6,7 @@ using Beefy.geom;
using Beefy.utils;
using System.Diagnostics;
using System.Threading;
using res;
namespace Beefy.gfx
{
@ -36,6 +37,104 @@ namespace Beefy.gfx
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
{
[CallingConvention(.Stdcall), CLink]
@ -89,6 +188,24 @@ namespace Beefy.gfx
public int32 mYOffset;
public int32 mXAdvance;
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
@ -139,6 +256,9 @@ namespace Beefy.gfx
//BitmapFont mBMFont ~ delete _;
public StringView mEllipsis = "...";
List<FontEffect> mFontEffectStack ~ delete _;
DisposeProxy mFontEffectDisposeProxy = new .(new () => { PopFontEffect(); }) ~ delete _;
public this()
{
}
@ -153,6 +273,19 @@ namespace Beefy.gfx
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()
{
#if BF_PLATFORM_WINDOWS
@ -383,6 +516,14 @@ namespace Beefy.gfx
void GetFontPath(StringView fontName, String path)
{
if (fontName.StartsWith('['))
{
path.Set(fontName);
if (FilePackManager.TryMakeMemoryString(path))
return;
path.Clear();
}
if (fontName.Contains('.'))
{
Path.GetAbsolutePath(fontName, BFApp.sApp.mInstallDir, path);
@ -666,13 +807,23 @@ namespace Beefy.gfx
mLowCharData[(int)checkChar] = charData;
else
mCharData[checkChar] = charData;
return charData;
break;
}
}
if (charData == null)
{
if (checkChar == (char32)'?')
return null;
return GetCharData((char32)'?');
}
if (mFontEffectStack?.IsEmpty == false)
{
var fontEffect = mFontEffectStack.Back;
charData = fontEffect.Apply(this, 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 curY = 0;
float curX = x;
float curY = y;
Matrix newMatrix = Matrix();
bool hasClipRect = g.mClipRect.HasValue;
@ -839,6 +990,9 @@ namespace Beefy.gfx
uint32 color = g.mColor;
bool usingTextRenderState = mFontEffectStack?.IsEmpty != false;
if (usingTextRenderState)
g.PushTextRenderState();
float markTopOfs = 0;
@ -869,6 +1023,8 @@ namespace Beefy.gfx
}
CharData charData = GetCharData(c);
if (charData == null)
continue;
float drawX = curX + charData.mXOffset;
float drawY = curY + charData.mYOffset;
@ -943,7 +1099,11 @@ namespace Beefy.gfx
prevChar = c;
}
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)
@ -1060,14 +1220,11 @@ namespace Beefy.gfx
if (g != null)
{
using (g.PushTranslate(useX, useY))
Draw(g, workingStr, fontMetrics);
Draw(g, useX, useY, workingStr, fontMetrics);
}
else
{
if (fontMetrics != null)
fontMetrics.mMaxWidth = Math.Max(fontMetrics.mMaxWidth, GetWidth(workingStr));
}
drawHeight += GetLineSpacing();
if (fontMetrics != null)

View file

@ -547,6 +547,11 @@ namespace Beefy.gfx
(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 DrawButton(Image image, float x, float y, float width)
@ -924,6 +929,11 @@ namespace Beefy.gfx
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,
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));
}
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)
{
Image img = GetBorderedWhiteSquare(Math.Max((int)width, 1));

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Text;
using Beefy.utils;
using System.Diagnostics;
using res;
#if STUDIO_CLIENT
using Beefy.ipc;
@ -70,6 +71,9 @@ namespace Beefy.gfx
[CallingConvention(.Stdcall), CLink]
static extern int32 Gfx_Texture_GetHeight(void* textureSegment);
[CallingConvention(.Stdcall), CLink]
static extern void Gfx_ApplyEffect(void* destTextureSegment, void* srcTextureSegment, char8* options);
public this()
{
}
@ -94,11 +98,13 @@ namespace Beefy.gfx
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");
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 (flags.HasFlag(.FatalError))
@ -186,6 +192,11 @@ namespace Beefy.gfx
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)
{
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);
}
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
{
float _a = a;

View file

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Text;
using res;
namespace Beefy.gfx
{
@ -28,9 +29,22 @@ namespace Beefy.gfx
[CallingConvention(.Stdcall), CLink]
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)
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;
[DesignEditable(DefaultEditString=true)]
public String Label
public StringView Label
{
get
{

View file

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

View file

@ -119,6 +119,7 @@ namespace Beefy.theme.dark
g.SetFont(mFont);
if (mText != null)
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 float mLineHeightScale = 1.0f;
public uint32[] mTextColors = sDefaultColors;
public uint32 mHiliteColor = 0xFF2f5c88;
public uint32 mUnfocusedHiliteColor = 0x00000000;
@ -68,6 +69,8 @@ namespace Beefy.theme.dark
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)
{
//mTextInsets.Set(-3, 2, 0, 2);
@ -79,6 +82,8 @@ namespace Beefy.theme.dark
mHeight = GS!(24);
mHorzJumpSize = GS!(40);
mFont = DarkTheme.sDarkTheme?.mSmallFont;
mTextColors[0] = DarkTheme.COLOR_TEXT;
mHiliteColor = DarkTheme.COLOR_TEXT_SELECTED;
}
protected override EditWidgetContent.Data CreateEditData()
@ -102,7 +107,7 @@ namespace Beefy.theme.dark
mLineCoords.GrowUninitialized(mData.mLineStarts.Count);
mLineCoordJumpTable.Clear();
float fontHeight = mFont.GetLineSpacing();
float fontHeight = LineHeight;
int prevJumpIdx = -1;
float jumpCoordSpacing = GetJumpCoordSpacing();
@ -212,6 +217,13 @@ namespace Beefy.theme.dark
return defaultVal;
}
public float GetTextOffset()
{
float baseLineSpacing = mFont.GetLineSpacing();
float lineSpacing = LineHeight;
return lineSpacing / 2.0f - baseLineSpacing / 2.0f;
}
public int FindUncollapsedLine(int line)
{
var line;
@ -507,7 +519,7 @@ namespace Beefy.theme.dark
((embed.mKind == .HideLine) && (!hideLine)))
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)
rect.mY = 0;
return rect;
@ -524,7 +536,9 @@ namespace Beefy.theme.dark
#unwarn
int lineCount = GetLineCount();
float lineSpacing = mFont.GetLineSpacing();
float lineSpacing = LineHeight;
float fontLineSpacing = mFont.GetLineSpacing();
float textYOffset = GetTextOffset();
float offsetY = mTextInsets.mTop;
if (mHeight < lineSpacing)
@ -563,7 +577,7 @@ namespace Beefy.theme.dark
{
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
// to properly highlight the whole line without getting cut off - this works well for now.
float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness;
@ -594,18 +608,18 @@ namespace Beefy.theme.dark
if (mCharWidth <= 2)
{
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
{
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
{
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;
}
@ -699,7 +713,7 @@ namespace Beefy.theme.dark
}
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);
//int32 lineDrawStartColumn = lineDrawStart - lineStart;

View file

@ -978,7 +978,7 @@ namespace Beefy.theme.dark
public float mDragOffset = 0;
public bool mShowColumnGrid;
public bool mShowGridLines;
public Color mGridLinesColor = 0x0CFFFFFF;
public Color mGridLinesColor;
public bool mShowHeader = true;
public bool mEndInEllipsis;
public bool mWordWrap;
@ -1002,6 +1002,7 @@ namespace Beefy.theme.dark
{
mFont = DarkTheme.sDarkTheme.mSmallFont;
mBoldFont = DarkTheme.sDarkTheme.mSmallBoldFont;
mGridLinesColor = DarkTheme.COLOR_GRID;
SetShowHeader(true);
}
@ -1028,6 +1029,12 @@ namespace Beefy.theme.dark
mScrollContentInsets.mBottom += GS!(2);
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()
@ -1087,7 +1094,7 @@ namespace Beefy.theme.dark
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;
@ -1146,7 +1153,7 @@ namespace Beefy.theme.dark
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;
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 rightStr = default;
@ -43,13 +43,10 @@ namespace Beefy.theme.dark
leftStr.RemoveToEnd(barIdx);
}
using (g.PushColor(DarkTheme.COLOR_TEXT))
{
g.DrawString(leftStr, GS!(36), 0);
if (!rightStr.IsEmpty)
g.DrawString(rightStr, mWidth - GS!(8), 0, .Right);
}
}
if (mMenuItem.mIconImage != null)
g.Draw(mMenuItem.mIconImage, GS!(4), 0);
@ -57,7 +54,7 @@ namespace Beefy.theme.dark
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);
}
}
@ -239,6 +236,20 @@ namespace Beefy.theme.dark
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

View file

@ -197,7 +197,12 @@ namespace Beefy.theme.dark
};
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_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_SELECTED_OUTLINE = 0xFFCFAE11;
public static uint32 COLOR_MENU_FOCUSED = 0xFFE5A910;

View file

@ -33,7 +33,7 @@ namespace Beefy.theme.dark
public bool mAllowResize;
public bool mHasClosed;
public Insets mRelWidgetMouseInsets ~ delete _;
public bool mAllowMouseInsideSelf;
public Insets mAllowMouseInsideInsets ~ delete _;
public bool mAllowMouseOutside;
public int mAutoCloseDelay;
public bool mIsClipped;
@ -96,6 +96,21 @@ namespace Beefy.theme.dark
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)
{
if (mRelWidget != null)
@ -162,7 +177,7 @@ namespace Beefy.theme.dark
int32 relX = x - mWidgetWindow.mX;
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.Client;
}
@ -178,10 +193,13 @@ namespace Beefy.theme.dark
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Menu), 0, 0, mWidth, mHeight);
g.SetFont(mFont);
using (g.PushColor(DarkTheme.COLOR_TEXT))
{
if (mIsClipped)
g.DrawString(mText, GS!(8), GS!(5), .Left, mWidth - GS!(16), .Ellipsis);
else
g.DrawString(mText, 0, GS!(5), .Centered, mWidth);
}
if (mAllowResize)
g.Draw(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.ResizeGrabber), mWidth - GS!(22), mHeight - GS!(22));
@ -248,22 +266,43 @@ namespace Beefy.theme.dark
if (mAllowMouseOutside)
return;
Rect widgetRect = .(0, 0, mRelWidget.mWidth, mRelWidget.mHeight);
mRelWidgetMouseInsets?.ApplyTo(ref widgetRect);
float rootX;
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, widgetRect.mWidth, widgetRect.mHeight);
Rect checkRect = Rect(rootX, rootY, mRelWidget.mWidth, mRelWidget.mHeight);
mRelWidgetMouseInsets?.ApplyTo(ref checkRect);
if ((mRelWidget.mWidgetWindow != null) && (mRelWidget.mWidgetWindow.mHasMouseInside))
{
//checkRect.Inflate(8, 8);
if (checkRect.Contains(mRelWidget.mWidgetWindow.mClientMouseX, mRelWidget.mWidgetWindow.mClientMouseY))
return;
}
if ((mWidgetWindow.mHasMouseInside) && (mAllowMouseInsideSelf))
if (mAllowMouseInsideInsets != null)
{
if (mWidgetWindow.mHasMouseInside)
return;
Rect<float> clientRect = mWidgetWindow.ClientRect;
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;
if ((checkWindow != null) && (checkWindow.HasParent(mWidgetWindow)))
return;
@ -423,15 +462,6 @@ namespace Beefy.theme.dark
SetLastMouseWidget(null);
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);
}
public virtual void GenerateClipboardText(String outText)
{
outText.AppendF("{}\n{}", mTitle, mText);
}
void WindowKeyDown(KeyDownEvent evt)
{
if ((evt.mKeyCode != .Alt) && (mWidgetWindow.IsKeyDown(.Alt)) && (!mWidgetWindow.IsKeyDown(.Control)))
@ -387,6 +392,29 @@ namespace Beefy.widgets
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;
}
if (hi < GetLineCount())
if ((hi >= 0) && (hi < GetLineCount()))
{
line = (int32)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;
if (selfSelected)
@ -907,6 +907,9 @@ namespace Beefy.widgets
{
base.KeyDown(keyCode, isRepeat);
if (mWidgetWindow == null)
return;
switch (keyCode)
{
case (KeyCode)'A':

View file

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

View file

@ -69,6 +69,7 @@ namespace Beefy.widgets
public bool mWantsUpdateF;
public bool mTempWantsUpdateF;
public Image mContentRenderTarget ~ delete _;
public int32 mContentClientWidth;
public int32 mContentClientHeight;
@ -230,10 +231,30 @@ namespace Beefy.widgets
{
base.PreDraw(g);
if (mContentRenderTarget != null)
{
g.mMatrix.Set(Matrix.IdentityMatrix);
}
else
{
g.mMatrix.Set(mScaleMatrix);
}
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()
{
base.RehupSize();
@ -880,8 +901,14 @@ namespace Beefy.widgets
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;
mContentClientHeight = (.)height;
RehupSize();

View file

@ -2012,14 +2012,14 @@ namespace FMOD
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;
exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO);
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);
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.IO;
using System.Diagnostics;
using System.Collections;
#define TINFL_USE_64BIT_BITBUF
#define MINIZ_HAS_64BIT_REGISTERS
#define MINIZ_LITTLE_ENDIAN
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES
#if BF_PLATFORM_WINDOWS
#define ALLOW_FILE_MAPPING
#endif
namespace MiniZ
{
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
{
ZipFile mZipFile;
MiniZ.ZipArchiveFileStat mFileStat;
int32 mFileIdx;
Span<uint8> mAllocatedData ~ delete mAllocatedData.Ptr;
public bool IsDirectory
{
@ -65,6 +135,17 @@ namespace MiniZ
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 i = 0;
@ -97,10 +178,27 @@ namespace MiniZ
outComment.Append(&mFileStat.mComment, GetStrLen(&mFileStat.mComment, mFileStat.mComment.Count));
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;
bool mInitialized;
#if ALLOW_FILE_MAPPING
Windows.FileHandle mShareFileHandle ~ _.Close();
Windows.Handle mShareFileMapping ~ _.Close();
Span<uint8> mMappedData;
#endif
Stream mOwnedStream ~ delete _;
public ~this()
{
@ -117,6 +215,74 @@ namespace MiniZ
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)
{
Debug.Assert(!mInitialized);
@ -3115,7 +3281,7 @@ namespace MiniZ
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))
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;
public alloctype(T) Val

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,7 @@ namespace System.Diagnostics
#if !DEBUG
[SkipCall]
#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 ");
line.ToString(failStr);
@ -44,10 +44,19 @@ namespace System.Diagnostics
#endif
}
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Cdecl)]
static extern void Write(char8* str, int strLen);
[CallingConvention(.Cdecl)]
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)
{
@ -59,7 +68,7 @@ namespace System.Diagnostics
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);
str.AppendF(fmt, params args);
@ -86,7 +95,7 @@ namespace System.Diagnostics
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);
paramStr.AppendF(strFormat, params args);

View file

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

View file

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

View file

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

View file

@ -135,7 +135,7 @@ namespace System.IO
bfpFlags |= .Directories;
if (flags.HasFlag(.Files))
bfpFlags |= .Files;
let findFileData = Platform.BfpFindFileData_FindFirstFile(useStr, bfpFlags, null);
let findFileData = Platform.Hook.BfpFindFileData_FindFirstFile(useStr, bfpFlags, null);
return FileEnumerator(useStr, findFileData);
}
@ -206,7 +206,7 @@ namespace System.IO
{
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.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()
{
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_LastWrite(mFindFileData));
return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_LastWrite(mFindFileData));
}
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()
{
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_Created(mFindFileData));
return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_Created(mFindFileData));
}
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()
{
return DateTime.FromFileTime((int64)Platform.BfpFindFileData_GetTime_Access(mFindFileData));
return DateTime.FromFileTime((int64)Platform.Hook.BfpFindFileData_GetTime_Access(mFindFileData));
}
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()
{
return Platform.BfpFindFileData_GetFileSize(mFindFileData);
return Platform.Hook.BfpFindFileData_GetFileSize(mFindFileData);
}
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
@ -292,7 +294,7 @@ namespace System.IO
{
delete mSearchStr;
if (mFindFileData != null)
Platform.BfpFindFileData_Release(mFindFileData);
Platform.Hook.BfpFindFileData_Release(mFindFileData);
}
public bool MoveNext() mut
@ -301,7 +303,7 @@ namespace System.IO
if (mIdx == 0)
return mFindFileData != null;
return Platform.BfpFindFileData_FindNextFile(mFindFileData);
return Platform.Hook.BfpFindFileData_FindNextFile(mFindFileData);
}
public Result<FileFindEntry> GetNext() mut

View file

@ -141,13 +141,13 @@ namespace System.IO
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)
{
Platform.BfpFileResult result = default;
Platform.BfpFile_Delete(fileName.ToScopeCStr!(), &result);
Platform.Hook.BfpFile_Delete(fileName.ToScopeCStr!(), &result);
if ((result != .Ok) && (result != .NotFound))
return .Err(result);
return .Ok;
@ -156,7 +156,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Move(StringView fromPath, StringView toPath)
{
Platform.BfpFileResult result = default;
Platform.BfpFile_Rename(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), &result);
Platform.Hook.BfpFile_Rename(fromPath.ToScopeCStr!(), toPath.ToScopeCStr!(), &result);
if (result != .Ok)
return .Err(result);
return .Ok;
@ -165,7 +165,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath)
{
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)
return .Err(result);
return .Ok;
@ -174,7 +174,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> CopyIfNewer(StringView fromPath, StringView toPath)
{
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)
return .Err(result);
return .Ok;
@ -183,7 +183,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath, bool overwrite)
{
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)
return .Err(result);
return .Ok;
@ -192,7 +192,7 @@ namespace System.IO
public static Result<void, Platform.BfpFileResult> SetAttributes(StringView path, FileAttributes attr)
{
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)
return .Err(result);
return .Ok;
@ -200,12 +200,47 @@ namespace System.IO
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)
{
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
{
return Platform.BfpFile_Seek(mBfpFile, 0, .Relative);
return Platform.Hook.BfpFile_Seek(mBfpFile, 0, .Relative);
}
set
{
Platform.BfpFile_Seek(mBfpFile, value, .Absolute);
Platform.Hook.BfpFile_Seek(mBfpFile, value, .Absolute);
}
}
@ -25,7 +25,7 @@ namespace System.IO
{
get
{
return Platform.BfpFile_GetFileSize(mBfpFile);
return Platform.Hook.BfpFile_GetFileSize(mBfpFile);
}
}
@ -35,7 +35,7 @@ namespace System.IO
{
if (mBfpFile == null)
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)
{
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
if ((seekKind == .Absolute) && (newPos != pos))
return .Err;
@ -56,7 +56,7 @@ namespace System.IO
public override Result<int> TryRead(Span<uint8> data)
{
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))
return .Err;
return numBytesRead;
@ -65,7 +65,7 @@ namespace System.IO
public override Result<int, FileError> TryRead(Span<uint8> data, int timeoutMS)
{
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))
{
switch (result)
@ -84,7 +84,7 @@ namespace System.IO
public override Result<int> TryWrite(Span<uint8> data)
{
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))
return .Err;
return numBytesWritten;
@ -93,7 +93,7 @@ namespace System.IO
public override Result<void> Close()
{
if (mBfpFile != null)
Platform.BfpFile_Release(mBfpFile);
Platform.Hook.BfpFile_Release(mBfpFile);
mBfpFile = null;
return .Ok;
}
@ -101,7 +101,7 @@ namespace System.IO
public override Result<void> Flush()
{
if (mBfpFile != null)
Platform.BfpFile_Flush(mBfpFile);
Platform.Hook.BfpFile_Flush(mBfpFile);
return .Ok;
}
@ -159,7 +159,7 @@ namespace System.IO
public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind)
{
Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_GetStd(stdKind, &fileResult);
mBfpFile = Platform.Hook.BfpFile_GetStd(stdKind, &fileResult);
mFileAccess = .ReadWrite;
if ((mBfpFile == null) || (fileResult != .Ok))
@ -218,7 +218,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal;
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))
{
@ -261,7 +261,7 @@ namespace System.IO
Seek(length);
Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result);
Platform.Hook.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok)
{
Seek(pos);
@ -297,7 +297,7 @@ namespace System.IO
{
if (mBfpFile == null)
return 0;
return Platform.BfpFile_GetSystemHandle(mBfpFile);
return Platform.Hook.BfpFile_GetSystemHandle(mBfpFile);
}
}
@ -321,7 +321,7 @@ namespace System.IO
{
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);
}
}
@ -355,7 +355,7 @@ namespace System.IO
public Result<void, FileOpenError> OpenStd(Platform.BfpFileStdKind stdKind)
{
Platform.BfpFileResult fileResult = .Ok;
mBfpFile = Platform.BfpFile_GetStd(stdKind, &fileResult);
mBfpFile = Platform.Hook.BfpFile_GetStd(stdKind, &fileResult);
mFileAccess = .ReadWrite;
if ((mBfpFile == null) || (fileResult != .Ok))
@ -413,7 +413,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal;
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))
{
@ -467,7 +467,7 @@ namespace System.IO
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);
if (seekKind == .Absolute && newPos < 0)
return .Err;
@ -479,7 +479,7 @@ namespace System.IO
{
let ret = base.Close();
if (mBfpFile != null)
Platform.BfpFile_Release(mBfpFile);
Platform.Hook.BfpFile_Release(mBfpFile);
mBfpFile = null;
mFileAccess = default;
@ -489,12 +489,12 @@ namespace System.IO
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)
{
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;
if (result case .Ok)
mBfpFilePos = newPos;
@ -507,7 +507,7 @@ namespace System.IO
Try!(SeekUnderlying(pos));
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))
return .Err;
mBfpFilePos += numBytesRead;
@ -520,7 +520,7 @@ namespace System.IO
Try!(SeekUnderlying(pos));
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))
return .Err;
mBfpFilePos += numBytesRead;
@ -533,7 +533,7 @@ namespace System.IO
Try!(SeekUnderlying(mPos));
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))
{
switch (result)
@ -560,7 +560,7 @@ namespace System.IO
}
Platform.BfpFileResult result = .Ok;
Platform.BfpFile_Truncate(mBfpFile, &result);
Platform.Hook.BfpFile_Truncate(mBfpFile, &result);
if (result != .Ok)
{
Try!(SeekUnderlying(pos));
@ -585,7 +585,7 @@ namespace System.IO
{
var result = base.Flush();
if (mBfpFile != null)
Platform.BfpFile_Flush(mBfpFile);
Platform.Hook.BfpFile_Flush(mBfpFile);
return result;
}
}

View file

@ -116,4 +116,98 @@ namespace System.IO
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.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))
{
@ -76,6 +76,9 @@ namespace System.IO
Platform.BfpFileCreateKind createKind = .CreateAlways;
Platform.BfpFileCreateFlags createFlags = .Pipe;
if (options.HasFlag(.AllowTimeouts))
createFlags |= .AllowTimeouts;
createKind = .OpenExisting;
createFlags |= .Read;
createFlags |= .Write;
@ -83,7 +86,7 @@ namespace System.IO
Platform.BfpFileAttributes fileFlags = .Normal;
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))
{

View file

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

View file

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

View file

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

View file

@ -78,29 +78,27 @@ namespace System
public override void ToString(String strBuffer)
{
// Dumb, make better.
char8[] strChars = scope:: char8[22];
char8[22] strChars = ?;
int32 char8Idx = 20;
int64 valLeft = (int64)this;
bool isNeg = true;
int minNumeralsLeft = 0;
if (valLeft >= 0)
{
valLeft = -valLeft;
isNeg = false;
}
while ((valLeft < 0) || (minNumeralsLeft > 0))
while (valLeft < 0)
{
strChars[char8Idx] = (char8)('0' &- (valLeft % 10));
valLeft /= 10;
char8Idx--;
minNumeralsLeft--;
}
if (char8Idx == 20)
strChars[char8Idx--] = '0';
if (isNeg)
strChars[char8Idx--] = '-';
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)

View file

@ -78,6 +78,33 @@ namespace System
[AlwaysInclude]
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")]
public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")]
@ -234,8 +261,20 @@ namespace System
public static extern void BfDelegateTargetCheck(void* target);
[CallingConvention(.Cdecl), AlwaysInclude]
public static extern void* LoadSharedLibrary(char8* filePath);
[CallingConvention(.Cdecl), AlwaysInclude]
public static extern void LoadSharedLibraryInto(char8* filePath, void** libDest);
[AlwaysInclude, LinkName("Beef_LoadSharedLibraryInto")]
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]
public static extern void* GetSharedProcAddress(void* libHandle, char8* procName);
[CallingConvention(.Cdecl), AlwaysInclude]
@ -261,11 +300,11 @@ namespace System
[CallingConvention(.Cdecl)]
public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth);
[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)]
public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size);
[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)]
public static extern void Dbg_ObjectPreDelete(Object obj);
[CallingConvention(.Cdecl)]
@ -281,6 +320,186 @@ namespace System
[CallingConvention(.Cdecl)]
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)]
static extern void Shutdown_Internal();
@ -292,19 +511,7 @@ namespace System
}
#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]
static void Crash()
@ -446,7 +653,7 @@ namespace System
}
[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
obj.[Friend]mClassVData = (.)(void*)classVData;
@ -462,7 +669,7 @@ namespace System
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;
}

View file

@ -392,8 +392,11 @@ namespace System.Net
service.sin_addr = address;
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();
return .Err;
}

View file

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

View file

@ -67,6 +67,11 @@ namespace System
}
#if !BF_RUNTIME_DISABLE
[StaticHook(typeof(SelfOuter))]
public static struct Hook
{
}
[CallingConvention(.Stdcall), CLink]
public static extern uint32 BfpSystem_TickCount();
[CallingConvention(.Stdcall), CLink]
@ -124,6 +129,7 @@ namespace System
[CallingConvention(.Stdcall), CLink]
public static extern void* BfpTLS_GetValue(BfpTLS* tls);
#else
public typealias Hook = Self;
public static uint32 BfpSystem_TickCount() => Runtime.NotImplemented();
@ -565,47 +571,47 @@ namespace System
}
#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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
#else
@ -660,23 +666,23 @@ namespace System
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
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);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
public static extern BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink]
[CallingConvention(.Stdcall), CLink, StaticHook]
public static extern void BfpFindFileData_Release(BfpFindFileData* findData);
#else
@ -714,6 +720,20 @@ namespace System
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)
{
let initSize = 4096;

View file

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

View file

@ -104,7 +104,7 @@ namespace System.Reflection
case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf
let argTypeId = Decode!<int32>(data);
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);
var boxedType = Type.[Friend]GetType_(boxedTypeId);
int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset;
@ -216,7 +216,7 @@ namespace System.Reflection
case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf
let argTypeId = AttributeInfo.Decode!<int32>(mData);
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);
var boxedType = Type.[Friend]GetType_(boxedTypeId);
int dataSize = boxedType.InstanceSize - boxedType.[Friend]mMemberDataOffset;

View file

@ -454,6 +454,38 @@ namespace System.Reflection
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)
{
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)
{
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>
{
BindingFlags mBindingFlags;

View file

@ -59,6 +59,9 @@ namespace System.Reflection
public bool IsMixin => Compiler.IsComptime ?
Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mMethodFlags.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 ?
Type.[Friend]Comptime_Method_GetName(mData.mComptimeMethodInstance) :
@ -82,6 +85,13 @@ namespace System.Reflection
Name == "~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 ?
Type.[Friend]GetType((.)Type.[Friend]Comptime_Method_GetInfo(mData.mComptimeMethodInstance).mReturnTypeId) :
Type.[Friend]GetType(mData.mMethodData.mReturnType);
@ -1017,6 +1027,25 @@ namespace System.Reflection
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)
{
int useParamIdx = 0;

View file

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

View file

@ -14,7 +14,7 @@ namespace System
public bool AVX, AVX2, AVX512;
}
[StaticInitPriority(101)]
[StaticInitPriority(201)]
static class Runtime
{
const int32 cVersion = 10;
@ -111,7 +111,7 @@ namespace System
function void* (int size) mAlloc;
function void (void* ptr) mFree;
function void (Object obj) mObject_Delete;
void* mUnused0;
function void* (ClassVData* vdataPtr) mClassVData_GetTypeData;
function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
@ -152,6 +152,16 @@ namespace System
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)
{
#if BF_DBG_RUNTIME
@ -259,6 +269,7 @@ namespace System
mAlloc = => Alloc;
mFree = => Free;
mObject_Delete = => Object_Delete;
mClassVData_GetTypeData = => ClassVData_GetTypeData;
mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers;
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 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)
{
@ -638,7 +650,7 @@ namespace System
}
}
#if BF_RUNTIME_DISABLE
#if BF_RUNTIME_DISABLE && !BF_CRT_DISABLE
namespace System
{
[AlwaysInclude, StaticInitPriority(1000)]
@ -734,8 +746,8 @@ namespace System
return 0;
}
[LinkName(.C), AlwaysInclude]
static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd);
/*[LinkName(.C), AlwaysInclude]
static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd);*/
[LinkName(.C), AlwaysInclude]
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,13 +74,33 @@ namespace System
const uint32 cStrPtrFlag = 0x40000000;
#endif
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(int count) // 0
{
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
mLength = 0;
}
[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()
{
let bufferSize = 16 - sizeof(char8*);
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
mLength = 0;
}
@ -88,28 +108,52 @@ namespace System
[AllowAppend]
public this()
{
let bufferSize = 16 - sizeof(char8*);
let bufferSize = 8;
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
mPtrOrBuffer = addlPtr;
mAllocSizeAndFlags = (uint_strsize)bufferSize | cStrPtrFlag;
mLength = 0;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(String str)
{
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);
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
Internal.MemCpy(Ptr, str.Ptr, count);
mLength = count;
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
}
[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)
{
Debug.Assert((uint)offset <= (uint)str.Length);
@ -126,7 +170,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(String str, int offset, int count)
{
Debug.Assert((uint)offset <= (uint)str.Length);
@ -144,7 +188,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(char8 c, int count)
{
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -158,7 +202,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(char8* char8Ptr)
{
let count = Internal.CStrLen(char8Ptr);
@ -173,7 +217,7 @@ namespace System
mLength = count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(char8* char8Ptr, int count)
{
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -187,7 +231,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(char16* char16Ptr)
{
let count = UTF16.GetLengthAsUTF8(char16Ptr);
@ -200,7 +244,7 @@ namespace System
UTF16.Decode(char16Ptr, this);
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(Span<char16> chars)
{
let count = UTF16.GetLengthAsUTF8(chars);
@ -213,14 +257,13 @@ namespace System
UTF16.Decode(chars, this);
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(StringView strView)
{
let count = strView.Length;
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
#unwarn
char8* addlPtr = append char8[bufferSize]*(?);
Init(bufferSize);
let ptr = Ptr;
Internal.MemCpy(ptr, strView.Ptr, strView.Length);
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
@ -228,6 +271,20 @@ namespace System
}
[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)
{
let count = strView.Length + (flags.HasFlag(.NullTerminate) ? 1 : 0);
@ -243,7 +300,7 @@ namespace System
mLength = (int32)strView.Length;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(StringView strView, int offset)
{
Debug.Assert((uint)offset <= (uint)strView.Length);
@ -261,7 +318,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(StringView strView, int offset, int count)
{
Debug.Assert((uint)offset <= (uint)strView.Length);
@ -279,7 +336,7 @@ namespace System
mLength = (int_strsize)count;
}
[AllowAppend]
[AllowAppend(ZeroGap=true)]
public this(char8[] chars, int offset, int count)
{
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -293,7 +350,15 @@ namespace System
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;
for (var str in strs)
@ -302,7 +367,7 @@ namespace System
}
[AllowAppend]
public this(params String[] strs)
public this(params Span<StringView> strs)
{
int count = StrLengths(strs);
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
@ -313,7 +378,27 @@ namespace System
int curIdx = 0;
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;
}
@ -642,7 +727,7 @@ namespace System
public static implicit operator Span<char8>(String str)
{
if (str == null)
return .(null, 0);
return .((char8*)null, 0);
return .(str.Ptr, str.Length);
}
@ -966,7 +1051,7 @@ namespace System
Append(str.Ptr + offset, length);
}
public void Append(params String[] strings)
public void Append(params Span<StringView> strings)
{
for (var str in strings)
Append(str);
@ -1307,6 +1392,10 @@ namespace System
while (true)
{
int charsLeft = len - pos;
Reserve(mLength + charsLeft);
char8* ptr = Ptr;
int p = pos;
int i = pos;
while (pos < len)
@ -1333,7 +1422,8 @@ namespace System
}
}
Append(ch);
//Append(ch);
ptr[mLength++] = ch;
}
if (pos == len) break;
@ -1434,6 +1524,16 @@ namespace System
}
if (ch != '}') return FormatError();
pos++;
if ((provider == null) && (fmt.IsEmpty) && (width == 0))
{
if (arg == null)
Append("null");
else
arg.ToString(this);
}
else
{
if (s == null)
s = scope:: String(128);
@ -1454,6 +1554,7 @@ namespace System
Append(s);
if (leftJustify && pad > 0) Append(' ', pad);
}
}
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)
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)
{
return StringSplitEnumerator(Ptr, Length, c, Int32.MaxValue, StringSplitOptions.None);
@ -2544,27 +2656,27 @@ namespace System
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);
}
public StringSplitEnumerator Split(char8[] separators)
public StringSplitEnumerator Split(Span<char8> separators)
{
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);
}
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);
}
public StringSplitEnumerator Split(char8[] separators, StringSplitOptions options)
public StringSplitEnumerator Split(Span<char8> separators, StringSplitOptions 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>
{
char8* mPtr;
@ -3079,15 +3201,15 @@ namespace System
int_strsize mPos;
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;
mStrLen = (int_strsize)strLength;
if (separators?.Count > 0)
if (separators.Length > 0)
{
mFirstSeparator = separators[0];
mSeparatorPtr = &separators[0];
mSeparatorCount = (.)separators.Count;
mSeparatorCount = (.)separators.Length;
}
else
{
@ -3281,7 +3403,7 @@ namespace System
{
StringSplitOptions mSplitOptions;
StringView mFirstSeparator;
StringView[] mSeparators;
Span<StringView> mSeparators;
char8* mPtr;
int_strsize mStrLen;
int32 mCurCount;
@ -3290,11 +3412,11 @@ namespace System
int_strsize mMatchPos;
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;
mStrLen = (int_strsize)strLength;
if (separators?.Count > 0)
if (separators.Length > 0)
mFirstSeparator = separators[0];
else
mFirstSeparator = .();
@ -3414,7 +3536,7 @@ namespace System
}
else
{
if (mFirstSeparator.IsNull && (mSeparators == null || mSeparators.IsEmpty) && mPtr[mMatchPos].IsWhiteSpace)
if (mFirstSeparator.IsNull && (mSeparators.IsEmpty) && mPtr[mMatchPos].IsWhiteSpace)
{
foundMatch = true;
mMatchLen = 1;
@ -3424,9 +3546,9 @@ namespace System
foundMatch = true;
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])
{
@ -4273,27 +4395,27 @@ namespace System
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);
}
public StringStringSplitEnumerator Split(StringView[] separators)
public StringStringSplitEnumerator Split(Span<StringView> separators)
{
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);
}
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);
}
public StringStringSplitEnumerator Split(StringView[] separators, StringSplitOptions options)
public StringStringSplitEnumerator Split(Span<StringView> separators, StringSplitOptions options)
{
return StringStringSplitEnumerator(Ptr, Length, separators, Int32.MaxValue, options);
}

View file

@ -108,6 +108,7 @@ static
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)
{
var str = scope:: String();
@ -115,6 +116,7 @@ static
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 str = scope:: String();
@ -122,6 +124,7 @@ static
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)
{
var str = scope:: String();

View file

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

View file

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

View file

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

View file

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

View file

@ -5,6 +5,195 @@ using System.Diagnostics;
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
{
public int mType;
@ -32,6 +221,21 @@ namespace System
protected uint8 mAlign;
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
{
get
@ -48,6 +252,14 @@ namespace System
}
}
public static TypeDeclaration.Enumerator TypeDeclarations
{
get
{
return .();
}
}
public int32 Size
{
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
{
get
@ -551,9 +774,17 @@ namespace System
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_GetWrappedType(int32 typeId);
static extern Type Comptime_GetTypeByName(StringView name);
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 bool Comptime_Type_GetCustomAttribute(int32 typeId, 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);
}
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)
{
return .Err;
@ -752,8 +992,9 @@ namespace System
#if !BF_REFLECT_MINIMAL
GetFullName(strBuffer);
#else
strBuffer.Append("Type#");
mTypeId.ToString(strBuffer);
strBuffer.Append("comptype(");
((int32)mTypeId).ToString(strBuffer);
strBuffer.Append(")");
#endif
}
@ -766,7 +1007,7 @@ namespace System
while (true)
{
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)
return .Err;
@ -838,7 +1079,13 @@ namespace System
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)]
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)
{
if (mTypeFlags.HasFlag(TypeFlags.Tuple))
@ -1317,7 +1577,8 @@ namespace System.Reflection
public override void GetFullName(String strBuffer)
{
strBuffer.Append("const ");
switch (GetType(mValueType))
var type = GetType(mValueType);
switch (type)
{
case typeof(float):
(*(float*)&mValue).ToString(strBuffer);
@ -1332,6 +1593,10 @@ namespace System.Reflection
strBuffer.Append('\'');
case typeof(uint64), typeof(uint):
(*(uint64*)&mValue).ToString(strBuffer);
case typeof(String):
int32 stringId = *(int32*)&mValue;
String str = String.GetById(stringId);
str.Quote(strBuffer);
default:
mValue.ToString(strBuffer);
}
@ -1409,7 +1674,11 @@ namespace System.Reflection
{
if (i > 0)
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('>');
}
@ -1445,7 +1714,7 @@ namespace System.Reflection
int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount);
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount, 0);
#else
void* mem = new [Align(16)] uint8[arraySize]* (?);
obj = Internal.UnsafeCastToObject(mem);
@ -1505,6 +1774,7 @@ namespace System.Reflection
Static = 0x200000,
Abstract = 0x400000,
HasAppendWantMark = 0x800000,
}
public enum FieldFlags : uint16
@ -1527,9 +1797,9 @@ namespace System.Reflection
Appended = 0x1000,
}
public enum MethodFlags : uint16
public enum MethodFlags : uint32
{
MethodAccessMask = 0x0007,
case MethodAccessMask = 0x0007,
Protected = 0x0003,
Public = 0x0006,
@ -1547,5 +1817,26 @@ namespace System.Reflection
ThisCall = 0x3000, // Purposely resuing StdCall|FastCall
Mutating = 0x4000,
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)
{
// Dumb, make better.
char8[] strChars = scope:: char8[16];
char8[16] strChars = ?;
int32 char8Idx = 14;
uint32 valLeft = (uint32)this;
while (valLeft > 0)
@ -73,7 +73,7 @@ namespace System
if (char8Idx == 14)
strChars[char8Idx--] = '0';
char8* char8Ptr = &strChars[char8Idx + 1];
strBuffer.Append(char8Ptr);
strBuffer.Append(char8Ptr, 14 - char8Idx);
}
void ToString(String strBuffer, int minNumerals)

View file

@ -73,7 +73,7 @@ namespace System
public override void ToString(String strBuffer)
{
// Dumb, make better.
char8[] strChars = scope:: char8[22];
char8[22] strChars = ?;
int32 char8Idx = 20;
uint64 valLeft = (uint64)this;
while (valLeft > 0)
@ -85,7 +85,7 @@ namespace System
if (char8Idx == 20)
strChars[char8Idx--] = '0';
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)

View file

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

View file

@ -107,6 +107,11 @@ namespace System
public int32 Height => bottom - top;
}
public struct Point : this(int32 x, int32 y)
{
}
[CRepr]
public struct OpenFileName
{
@ -364,11 +369,15 @@ namespace System
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;
GetValue(name, scope [?] (regType, regData) =>
{
if (isExpanded != null)
*isExpanded = regType == Windows.REG_EXPAND_SZ;
if ((regType == Windows.REG_SZ) || (regType == Windows.REG_EXPAND_SZ))
{
gotData = true;
@ -1703,6 +1712,12 @@ namespace System
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
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)]
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)]
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)]
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);
[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)]
public static extern HWnd SetFocus(HWnd hWnd);

View file

@ -50,9 +50,9 @@ namespace bf
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 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_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_ObjectPreCustomDelete(bf::System::Object* obj);
@ -315,7 +315,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::Reflection::TypeInstan
//#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];
int capturedTraceCount = 0;
@ -328,6 +328,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{
capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024));
const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1;
if ((capturedTraceCount > 255) || (size >= maxSmallObjectSize))
{
largeAllocInfo = true;
@ -336,6 +337,12 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
else
allocSize += capturedTraceCount * sizeof(intptr);
}
// Append want mark
if ((allocFlags & 1) != 0)
{
allocSize += 4 * sizeof(intptr);
}
}
#ifdef DBG_OBJECTEND
@ -385,7 +392,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
intptr dbgAllocInfo;
auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated;
if (maxStackTraceDepth <= 1)
if ((maxStackTraceDepth <= 1) && (allocFlags == 0))
dbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
else
{
@ -393,13 +400,13 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{
classVDataVal |= (intptr)BfObjectFlag_AllocInfo;
dbgAllocInfo = size;
*(intptr*)((uint8*)result + size) = capturedTraceCount;
*(intptr*)((uint8*)result + size) = (capturedTraceCount << 8) | allocFlags;
memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr));
}
else
{
classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short;
dbgAllocInfo = (size << 16) | capturedTraceCount;
dbgAllocInfo = (size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr));
}
}
@ -424,13 +431,27 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
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);
result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc;
#ifndef BFRT_NODBGFLAGS
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
}

View file

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

View file

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

View file

@ -119,12 +119,14 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
intptr extraDataSize = sizeof(intptr);
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)
{
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
@ -133,9 +135,12 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
typedef void(MarkTarget::*MarkFunc)();
MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc;
auto typeData = rawAllocData->mType->GetTypeData();
if (typeData != NULL)
{
// It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem
// because we can safely mark on complete random memory -- pointer values are always validated before being followed
intptr elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
intptr elemStride = BF_ALIGN(typeData->mSize, typeData->mAlign);
if (elemStride > 0)
{
intptr dataSize = elementSize - extraDataSize;
@ -147,6 +152,7 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
}
}
}
}
spanPtr = (void*)((intptr)spanPtr + elementSize);
}
@ -282,14 +288,14 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
if (rawAllocData->mType != NULL)
{
intptr typeSize;
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0)
typeSize = rawAllocData->mType->mSize;
else
typeSize = ((bf::System::Type_NOFLAGS*)rawAllocData->mType)->mSize;
bf::System::Type_NOFLAGS* typeData = rawAllocData->mType->GetTypeData();
if (typeData != NULL)
{
intptr typeSize = typeData->mSize;
if (typeSize > 0)
rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize;
}
}
else
rawLeakInfo.mDataCount = 1;
@ -559,7 +565,7 @@ void* BfRawAllocate(intptr size, bf::System::DbgRawAllocData* rawAllocData, void
}
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));
markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
}

View file

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

View file

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

View file

@ -20,3 +20,11 @@ Beefy::String bf::System::Type::GetFullName()
BFRTCALLBACKS.Object_Delete(strObj);
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
static volatile int gLiveThreadCount;
static volatile int gBackgroundThreadCount;
static Beefy::SyncEvent gThreadsDoneEvent;
#ifdef BF_PLATFORM_WINDOWS
@ -132,7 +133,11 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(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");
@ -168,7 +173,7 @@ void BfInternalThread::WaitForAllDone()
if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
return;
while (gLiveThreadCount != 0)
while (gLiveThreadCount > gBackgroundThreadCount)
{
// Clear out any old done events
gThreadsDoneEvent.WaitFor();
@ -303,12 +308,23 @@ void Thread::InternalFinalize()
bool Thread::IsBackgroundNative()
{
auto internalThread = GetInternalThread();
if (internalThread == NULL)
return false;
return internalThread->mIsBackground;
}
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()

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@
#include "util/Vector.h"
#include "util/PerfTimer.h"
#include "util/TLSingleton.h"
#include "img/ImgEffects.h"
#include "util/AllocDebug.h"
@ -446,6 +447,7 @@ BF_EXPORT int BF_CALLTYPE BFWindow_GetDPI(BFWindow* window)
BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateRenderTarget(int width, int height, int destAlpha)
{
Texture* texture = gBFApp->mRenderDevice->CreateRenderTarget(width, height, destAlpha != 0);
texture->mResetClear = true;
TextureSegment* aTextureSegment = new TextureSegment();
aTextureSegment->InitFromTexture(texture);
@ -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)
{
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)
{
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)
@ -516,6 +518,93 @@ BF_EXPORT void BF_CALLTYPE Gfx_ModifyTextureSegment(TextureSegment* destTextureS
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)
{
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_ASSERT((width >= 0) && (height >= 0));
renderState->mClipRect.mX = x;
renderState->mClipRect.mY = y;
renderState->mClipRect.mWidth = width;
renderState->mClipRect.mHeight = height;
renderState->mClipRect.x = x;
renderState->mClipRect.y = y;
renderState->mClipRect.width = width;
renderState->mClipRect.height = height;
if (!renderState->mClipped)
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>
<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>
<TargetName>$(ProjectName)64_Static</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -414,11 +415,12 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<FunctionLevelLinking>false</FunctionLevelLinking>
<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>
<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>
<Link>
<SubSystem>Windows</SubSystem>
@ -461,6 +463,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
<ClCompile Include="gfx\Texture.cpp" />
<ClCompile Include="HeadlessApp.cpp" />
<ClCompile Include="img\BFIData.cpp" />
<ClCompile Include="img\BMPData.cpp" />
<ClCompile Include="img\ImageAdjustments.cpp" />
<ClCompile Include="img\ImageData.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 Static|Win32'">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>
</ClCompile>
<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|x64'">false</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>
</ClCompile>
<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\MathUtils.cpp" />
<ClCompile Include="util\Matrix4.cpp" />
<ClCompile Include="util\MTRand.cpp" />
<ClCompile Include="util\PerfTimer.cpp" />
<ClCompile Include="util\Point.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="HeadlessApp.h" />
<ClInclude Include="img\BFIData.h" />
<ClInclude Include="img\BMPData.h" />
<ClInclude Include="img\ImageAdjustments.h" />
<ClInclude Include="img\ImageData.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|x64'">false</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>
</ClInclude>
<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|x64'">false</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>
</ClInclude>
<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\MathUtils.h" />
<ClInclude Include="util\Matrix4.h" />
<ClInclude Include="util\MTRand.h" />
<ClInclude Include="util\MultiDictionary.h" />
<ClInclude Include="util\MultiHashSet.h" />
<ClInclude Include="util\PerfTimer.h" />
<ClInclude Include="util\Point.h" />

View file

@ -737,6 +737,12 @@
<ClCompile Include="third_party\putty\wildcard.c">
<Filter>src\third_party\putty</Filter>
</ClCompile>
<ClCompile Include="util\MTRand.cpp">
<Filter>src\util</Filter>
</ClCompile>
<ClCompile Include="img\BMPData.cpp">
<Filter>src\img</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Common.h">
@ -1132,6 +1138,15 @@
<ClInclude Include="third_party\putty\wildcard.h">
<Filter>src\third_party\putty</Filter>
</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>
<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\Texture.cpp" />
<ClCompile Include="img\BFIData.cpp" />
<ClCompile Include="img\BMPData.cpp" />
<ClCompile Include="img\ImageAdjustments.cpp" />
<ClCompile Include="img\ImageData.cpp" />
<ClCompile Include="img\ImageUtils.cpp" />
@ -908,6 +909,7 @@
<ClInclude Include="gfx\Shader.h" />
<ClInclude Include="gfx\Texture.h" />
<ClInclude Include="img\BFIData.h" />
<ClInclude Include="img\BMPData.h" />
<ClInclude Include="img\ImageAdjustments.h" />
<ClInclude Include="img\ImageData.h" />
<ClInclude Include="img\ImageUtils.h" />

View file

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

View file

@ -36,13 +36,13 @@ int CachedDataStream::GetSize()
return mStream->GetSize();
}
void CachedDataStream::Read(void* ptr, int size)
int CachedDataStream::Read(void* ptr, int size)
{
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)
{
@ -59,6 +59,7 @@ void CachedDataStream::Write(void* ptr, int size)
size -= writeBytes;
mDataPtr += writeBytes;
}
return size;
}
int CachedDataStream::GetPos()

View file

@ -24,8 +24,8 @@ public:
virtual bool Eof() override;
virtual int GetSize() override;
virtual void Read(void* ptr, int size) override;
virtual void Write(void* ptr, int size) override;
virtual int Read(void* ptr, int size) override;
virtual int Write(void* ptr, int size) override;
virtual int GetPos() 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);
}
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