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:
commit
4b879670ca
294 changed files with 15180 additions and 4106 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ SDL2.dll
|
|||
*.vcxproj.user
|
||||
*/llvm-*
|
||||
*/llvm_*
|
||||
*/_llvm*
|
||||
*/x64/*
|
||||
**/Debug/*
|
||||
**/Debug */*
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
66
BeefLibs/Beefy2D/src/gfx/ImageAtlas.bf
Normal file
66
BeefLibs/Beefy2D/src/gfx/ImageAtlas.bf
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
592
BeefLibs/Beefy2D/src/res/FilePack.bf
Normal file
592
BeefLibs/Beefy2D/src/res/FilePack.bf
Normal 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;
|
||||
}
|
||||
}
|
275
BeefLibs/Beefy2D/src/res/PEFile.bf
Normal file
275
BeefLibs/Beefy2D/src/res/PEFile.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace Beefy.theme.dark
|
|||
public float mLabelYOfs;
|
||||
|
||||
[DesignEditable(DefaultEditString=true)]
|
||||
public String Label
|
||||
public StringView Label
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -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('&');
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
60
BeefLibs/Beefy2D/src/utils/StableIndexedList.bf
Normal file
60
BeefLibs/Beefy2D/src/utils/StableIndexedList.bf
Normal 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];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -372,7 +372,7 @@ namespace System
|
|||
[AttributeUsage(.Constructor)]
|
||||
public struct AllowAppendAttribute : Attribute
|
||||
{
|
||||
|
||||
public bool ZeroGap;
|
||||
}
|
||||
|
||||
[AttributeUsage(.Class | .Struct)]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -396,6 +396,7 @@ namespace System
|
|||
{
|
||||
sForegroundColor = sOriginalForegroundColor;
|
||||
sBackgroundColor = sOriginalBackgroundColor;
|
||||
SetColors();
|
||||
|
||||
#if !BF_PLATFORM_WINDOWS
|
||||
Write("\x1B[0m");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace System.FFI
|
||||
{
|
||||
[CRepr, StaticInitPriority(100)]
|
||||
[CRepr, StaticInitPriority(200)]
|
||||
struct FFIType
|
||||
{
|
||||
public enum TypeKind : uint16
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace System.IO
|
|||
mString = appendStr;
|
||||
}
|
||||
|
||||
[DisableChecks]
|
||||
public ~this()
|
||||
{
|
||||
if (mStringKind == .Append)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
90
BeefLibs/corlib/src/StaticHookAttribute.bf
Normal file
90
BeefLibs/corlib/src/StaticHookAttribute.bf
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -2,7 +2,7 @@ using System.Diagnostics;
|
|||
using System.Threading;
|
||||
namespace System.Text
|
||||
{
|
||||
[StaticInitPriority(100)]
|
||||
[StaticInitPriority(200)]
|
||||
abstract class Encoding
|
||||
{
|
||||
public enum DecodeError
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
5
BeefLibs/corlib/src/Tuple.bf
Normal file
5
BeefLibs/corlib/src/Tuple.bf
Normal file
|
@ -0,0 +1,5 @@
|
|||
namespace System;
|
||||
|
||||
struct Tuple
|
||||
{
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue