mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-30 05:15:59 +02:00
Moving corlib files out of "System" directory into root
This commit is contained in:
parent
4cd58262e4
commit
7dbfd15292
179 changed files with 3 additions and 0 deletions
301
BeefLibs/corlib/src/Diagnostics/AsyncStreamReader.bf
Normal file
301
BeefLibs/corlib/src/Diagnostics/AsyncStreamReader.bf
Normal file
|
@ -0,0 +1,301 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
internal delegate void UserCallBack(String data);
|
||||
|
||||
class AsyncStreamReader
|
||||
{
|
||||
internal const int32 DefaultBufferSize = 1024; // Byte buffer size
|
||||
private const int32 MinBufferSize = 128;
|
||||
|
||||
private Stream stream;
|
||||
private Encoding encoding;
|
||||
private Decoder decoder;
|
||||
private uint8[] byteBuffer;
|
||||
private char8[] char8Buffer;
|
||||
// Record the number of valid bytes in the byteBuffer, for a few checks.
|
||||
|
||||
// This is the maximum number of char8s we can get from one call to
|
||||
// ReadBuffer. Used so ReadBuffer can tell when to copy data into
|
||||
// a user's char8[] directly, instead of our internal char8[].
|
||||
private int32 mMaxCharsPerBuffer;
|
||||
|
||||
// Store a backpointer to the process class, to check for user callbacks
|
||||
private Process process;
|
||||
|
||||
// Delegate to call user function.
|
||||
private UserCallBack userCallBack;
|
||||
|
||||
// Internal Cancel operation
|
||||
private bool cancelOperation;
|
||||
private WaitEvent eofEvent = new WaitEvent() ~ delete _;
|
||||
private Queue<String> messageQueue ~ delete _;
|
||||
private String sb;
|
||||
private bool bLastCarriageReturn;
|
||||
private Monitor mMonitor = new Monitor();
|
||||
|
||||
// Cache the last position scanned in sb when searching for lines.
|
||||
private int currentLinePos;
|
||||
|
||||
internal this(Process process, Stream stream, UserCallBack callback, Encoding encoding)
|
||||
: this(process, stream, callback, encoding, DefaultBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
internal ~this()
|
||||
{
|
||||
for (var msg in messageQueue)
|
||||
delete msg;
|
||||
Close();
|
||||
}
|
||||
|
||||
// Creates a new AsyncStreamReader for the given stream. The
|
||||
// character encoding is set by encoding and the buffer size,
|
||||
// in number of 16-bit characters, is set by bufferSize.
|
||||
//
|
||||
internal this(Process process, Stream stream, UserCallBack callback, Encoding encoding, int32 bufferSize)
|
||||
{
|
||||
Debug.Assert(process != null && stream != null && encoding != null && callback != null, "Invalid arguments!");
|
||||
Debug.Assert(stream.CanRead, "Stream must be readable!");
|
||||
Debug.Assert(bufferSize > 0, "Invalid buffer size!");
|
||||
|
||||
Init(process, stream, callback, encoding, bufferSize);
|
||||
messageQueue = new Queue<String>();
|
||||
}
|
||||
|
||||
public virtual Encoding CurrentEncoding
|
||||
{
|
||||
get { return encoding; }
|
||||
}
|
||||
|
||||
public virtual Stream BaseStream
|
||||
{
|
||||
get { return stream; }
|
||||
}
|
||||
|
||||
private void Init(Process process, Stream stream, UserCallBack callback, Encoding encoding, int32 bufferSize)
|
||||
{
|
||||
this.process = process;
|
||||
this.stream = stream;
|
||||
this.encoding = encoding;
|
||||
this.userCallBack = callback;
|
||||
int32 useBufferSize = bufferSize;
|
||||
if (useBufferSize < MinBufferSize) useBufferSize = MinBufferSize;
|
||||
byteBuffer = new uint8[useBufferSize];
|
||||
mMaxCharsPerBuffer = (int32)encoding.GetMaxCharCount(useBufferSize);
|
||||
char8Buffer = new char8[mMaxCharsPerBuffer];
|
||||
cancelOperation = false;
|
||||
sb = null;
|
||||
this.bLastCarriageReturn = false;
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
if (stream != null)
|
||||
{
|
||||
stream = null;
|
||||
encoding = null;
|
||||
decoder = null;
|
||||
byteBuffer = null;
|
||||
char8Buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// User calls BeginRead to start the asynchronous read
|
||||
internal void BeginReadLine()
|
||||
{
|
||||
if (cancelOperation)
|
||||
{
|
||||
cancelOperation = false;
|
||||
}
|
||||
|
||||
if (sb == null)
|
||||
{
|
||||
sb = new String(DefaultBufferSize);
|
||||
stream.BeginRead(byteBuffer, 0, byteBuffer.Count, new => ReadBuffer, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlushMessageQueue();
|
||||
}
|
||||
}
|
||||
|
||||
internal void CancelOperation()
|
||||
{
|
||||
cancelOperation = true;
|
||||
}
|
||||
|
||||
// This is the async callback function. Only one thread could/should call this.
|
||||
private void ReadBuffer(IAsyncResult ar)
|
||||
{
|
||||
int byteLen = stream.EndRead(ar);
|
||||
|
||||
// We should ideally consume errors from operations getting cancelled
|
||||
// so that we don't crash the unsuspecting parent with an unhandled exc.
|
||||
// This seems to come in 2 forms of exceptions (depending on platform and scenario),
|
||||
// namely OperationCanceledException and IOException (for errorcode that we don't
|
||||
// map explicitly).
|
||||
byteLen = 0; // Treat this as EOF
|
||||
|
||||
|
||||
if (byteLen == 0)
|
||||
{
|
||||
// We're at EOF, we won't call this function again from here on.
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (sb.Length != 0)
|
||||
{
|
||||
messageQueue.Enqueue(new String(sb));
|
||||
sb.Clear();
|
||||
}
|
||||
messageQueue.Enqueue(null);
|
||||
}
|
||||
|
||||
// UserCallback could throw, we should still set the eofEvent
|
||||
FlushMessageQueue();
|
||||
|
||||
eofEvent.Set(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int char8Len = decoder.GetChars(byteBuffer, 0, byteLen, char8Buffer, 0);
|
||||
sb.Append(char8Buffer, 0, char8Len);
|
||||
GetLinesFromStringBuilder();
|
||||
stream.BeginRead(byteBuffer, 0, byteBuffer.Count, new => ReadBuffer, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Read lines stored in StringBuilder and the buffer we just read into.
|
||||
// A line is defined as a sequence of characters followed by
|
||||
// a carriage return ('\r'), a line feed ('\n'), or a carriage return
|
||||
// immediately followed by a line feed. The resulting string does not
|
||||
// contain the terminating carriage return and/or line feed. The returned
|
||||
// value is null if the end of the input stream has been reached.
|
||||
//
|
||||
|
||||
private void GetLinesFromStringBuilder()
|
||||
{
|
||||
int currentIndex = currentLinePos;
|
||||
int lineStart = 0;
|
||||
int len = sb.Length;
|
||||
|
||||
// skip a beginning '\n' char8acter of new block if last block ended
|
||||
// with '\r'
|
||||
if (bLastCarriageReturn && (len > 0) && sb[0] == '\n')
|
||||
{
|
||||
currentIndex = 1;
|
||||
lineStart = 1;
|
||||
bLastCarriageReturn = false;
|
||||
}
|
||||
|
||||
while (currentIndex < len)
|
||||
{
|
||||
char8 ch = sb[currentIndex];
|
||||
// Note the following common line feed char8s:
|
||||
// \n - UNIX \r\n - DOS \r - Mac
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
String s = new String();
|
||||
s.Append(sb, lineStart, currentIndex - lineStart);
|
||||
|
||||
lineStart = currentIndex + 1;
|
||||
// skip the "\n" char8acter following "\r" char8acter
|
||||
if ((ch == '\r') && (lineStart < len) && (sb[lineStart] == '\n'))
|
||||
{
|
||||
lineStart++;
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
messageQueue.Enqueue(s);
|
||||
}
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
if (sb[len - 1] == '\r')
|
||||
{
|
||||
bLastCarriageReturn = true;
|
||||
}
|
||||
// Keep the rest char8acaters which can't form a new line in string builder.
|
||||
if (lineStart < len)
|
||||
{
|
||||
if (lineStart == 0)
|
||||
{
|
||||
// we found no breaklines, in this case we cache the position
|
||||
// so next time we don't have to restart from the beginning
|
||||
currentLinePos = currentIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Remove(0, lineStart);
|
||||
currentLinePos = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Clear();
|
||||
currentLinePos = 0;
|
||||
}
|
||||
|
||||
FlushMessageQueue();
|
||||
}
|
||||
|
||||
private void FlushMessageQueue()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// When we call BeginReadLine, we also need to flush the queue
|
||||
// So there could be a ---- between the ReadBuffer and BeginReadLine
|
||||
// We need to take lock before DeQueue.
|
||||
if (messageQueue.Count > 0)
|
||||
{
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (messageQueue.Count > 0)
|
||||
{
|
||||
String s = messageQueue.Dequeue();
|
||||
// skip if the read is the read is cancelled
|
||||
// this might happen inside UserCallBack
|
||||
// However, continue to drain the queue
|
||||
if (!cancelOperation)
|
||||
{
|
||||
userCallBack(s);
|
||||
}
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until we hit EOF. This is called from Process.WaitForExit
|
||||
// We will lose some information if we don't do this.
|
||||
internal void WaitUtilEOF()
|
||||
{
|
||||
if (eofEvent != null)
|
||||
{
|
||||
eofEvent.WaitFor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
BeefLibs/corlib/src/Diagnostics/Check.bf
Normal file
37
BeefLibs/corlib/src/Diagnostics/Check.bf
Normal file
|
@ -0,0 +1,37 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
class Check
|
||||
{
|
||||
|
||||
[Unchecked, SkipCall]
|
||||
public static void Assert(bool condition)
|
||||
{
|
||||
}
|
||||
|
||||
[Checked]
|
||||
public static void Assert(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
Internal.FatalError("Assert failed", 1);
|
||||
}
|
||||
|
||||
[Unchecked, SkipCall]
|
||||
public static void Assert(bool condition, String error)
|
||||
{
|
||||
}
|
||||
|
||||
[Checked]
|
||||
public static void Assert(bool condition, String error)
|
||||
{
|
||||
if (!condition)
|
||||
Internal.FatalError(error, 1);
|
||||
}
|
||||
|
||||
[NoReturn]
|
||||
[SkipCall]
|
||||
public static void FatalError(String msg = "Fatal error encountered")
|
||||
{
|
||||
Internal.FatalError(msg, 1);
|
||||
}
|
||||
}
|
||||
}
|
61
BeefLibs/corlib/src/Diagnostics/Contracts/Contracts.bf
Normal file
61
BeefLibs/corlib/src/Diagnostics/Contracts/Contracts.bf
Normal file
|
@ -0,0 +1,61 @@
|
|||
namespace System.Diagnostics.Contracts
|
||||
{
|
||||
class Contract
|
||||
{
|
||||
public enum ContractFailureKind
|
||||
{
|
||||
Precondition,
|
||||
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
|
||||
Postcondition,
|
||||
//[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
|
||||
PostconditionOnException,
|
||||
Invariant,
|
||||
Assert,
|
||||
Assume,
|
||||
}
|
||||
|
||||
static extern void ReportFailure(ContractFailureKind failureKind, char8* userMessage, int32 userMessageLen, char8* conditionText, int32 conditionTextLen);
|
||||
|
||||
/// <summary>
|
||||
/// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
|
||||
/// It is NEVER used to indicate failure of actual contracts at runtime.
|
||||
/// </summary>
|
||||
static void AssertMustUseRewriter(ContractFailureKind kind, String contractKind)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Assume(bool condition, StringView userMessage)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
ReportFailure(ContractFailureKind.Assume, userMessage.Ptr, (int32)userMessage.Length, null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Assert(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
ReportFailure(ContractFailureKind.Assert, null, 0, null, 0);
|
||||
}
|
||||
|
||||
public static void Assert(bool condition, String userMessage)
|
||||
{
|
||||
if (!condition)
|
||||
ReportFailure(ContractFailureKind.Assert, userMessage.Ptr, (int32)userMessage.Length, null, 0);
|
||||
}
|
||||
|
||||
public static void Requires(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
ReportFailure(ContractFailureKind.Assert, null, 0, null, 0);
|
||||
//AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
|
||||
}
|
||||
|
||||
public static void Requires(bool condition, StringView userMessage)
|
||||
{
|
||||
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
|
||||
}
|
||||
|
||||
public static void EndContractBlock() { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace System.Diagnostics.Contracts
|
||||
{
|
||||
class ContractsBcl
|
||||
{
|
||||
}
|
||||
}
|
30
BeefLibs/corlib/src/Diagnostics/DataReceivedEventArgs.bf
Normal file
30
BeefLibs/corlib/src/Diagnostics/DataReceivedEventArgs.bf
Normal file
|
@ -0,0 +1,30 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <copyright file="Process.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
using System;
|
||||
|
||||
public delegate void DataReceivedEventHandler(Object sender, DataReceivedEventArgs e);
|
||||
|
||||
public class DataReceivedEventArgs : EventArgs
|
||||
{
|
||||
internal String _data;
|
||||
|
||||
internal this(String data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public String Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
BeefLibs/corlib/src/Diagnostics/Debug.bf
Normal file
58
BeefLibs/corlib/src/Diagnostics/Debug.bf
Normal file
|
@ -0,0 +1,58 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
class Debug
|
||||
{
|
||||
#if !DEBUG
|
||||
[SkipCall]
|
||||
#endif
|
||||
public static void Assert(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
Internal.FatalError("Assert failed", 1);
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
[SkipCall]
|
||||
#endif
|
||||
public static void Assert(bool condition, String error)
|
||||
{
|
||||
if (!condition)
|
||||
Internal.FatalError(error, 1);
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
[SkipCall]
|
||||
#endif
|
||||
public static void FatalError(String msg = "Fatal error encountered")
|
||||
{
|
||||
Internal.FatalError(msg, 1);
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
[SkipCall]
|
||||
#endif
|
||||
public static void AssertNotStack(Object obj)
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
if ((obj != null) && (obj.GetFlags() & 8 != 0))
|
||||
Internal.FatalError("Assert failed", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static extern void Write(char8* str, int strLen);
|
||||
|
||||
public static void WriteLine(StringView line)
|
||||
{
|
||||
Write(line.Ptr, line.Length);
|
||||
Write("\n", 1);
|
||||
}
|
||||
|
||||
public static void WriteLine(StringView strFormat, params Object[] args)
|
||||
{
|
||||
String paramStr = scope String();
|
||||
paramStr.AppendF(strFormat, params args);
|
||||
paramStr.Append('\n');
|
||||
Write(paramStr.Ptr, paramStr.Length);
|
||||
}
|
||||
}
|
||||
}
|
593
BeefLibs/corlib/src/Diagnostics/FileVersionInfo.bf
Normal file
593
BeefLibs/corlib/src/Diagnostics/FileVersionInfo.bf
Normal file
|
@ -0,0 +1,593 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
public class FileVersionInfo
|
||||
{
|
||||
public enum Error
|
||||
{
|
||||
FileNotFound,
|
||||
NotSupported
|
||||
}
|
||||
|
||||
private String mFileName ~ delete _;
|
||||
private String mCompanyName ~ delete _;
|
||||
private String mFileDescription ~ delete _;
|
||||
private String mFileVersion ~ delete _;
|
||||
private String mInternalName ~ delete _;
|
||||
private String mLegalCopyright ~ delete _;
|
||||
private String mOriginalFilename ~ delete _;
|
||||
private String mProductName ~ delete _;
|
||||
private String mProductVersion ~ delete _;
|
||||
private String mComments ~ delete _;
|
||||
private String mLegalTrademarks ~ delete _;
|
||||
private String mPrivateBuild ~ delete _;
|
||||
private String mSpecialBuild ~ delete _;
|
||||
private String mLanguage ~ delete _;
|
||||
private int32 mFileMajor;
|
||||
private int32 mFileMinor;
|
||||
private int32 mFileBuild;
|
||||
private int32 mFilePrivate;
|
||||
private int32 mProductMajor;
|
||||
private int32 mProductMinor;
|
||||
private int32 mProductBuild;
|
||||
private int32 mProductPrivate;
|
||||
private int32 mFileFlags;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DeleteAndNullify!(mFileName);
|
||||
DeleteAndNullify!(mCompanyName);
|
||||
DeleteAndNullify!(mFileDescription);
|
||||
DeleteAndNullify!(mFileVersion);
|
||||
DeleteAndNullify!(mInternalName);
|
||||
DeleteAndNullify!(mLegalCopyright);
|
||||
DeleteAndNullify!(mOriginalFilename);
|
||||
DeleteAndNullify!(mProductName);
|
||||
DeleteAndNullify!(mProductVersion);
|
||||
DeleteAndNullify!(mComments);
|
||||
DeleteAndNullify!(mLegalTrademarks);
|
||||
DeleteAndNullify!(mPrivateBuild);
|
||||
DeleteAndNullify!(mSpecialBuild);
|
||||
DeleteAndNullify!(mLanguage);
|
||||
mFileMajor = 0;
|
||||
mFileMajor = 0;
|
||||
mFileBuild = 0;
|
||||
mFilePrivate = 0;
|
||||
mProductMajor = 0;
|
||||
mProductMinor = 0;
|
||||
mProductBuild = 0;
|
||||
mProductPrivate = 0;
|
||||
mFileFlags = 0;
|
||||
}
|
||||
|
||||
/// Gets the comments associated with the file.
|
||||
public StringView Comments
|
||||
{
|
||||
get
|
||||
{
|
||||
return mComments;
|
||||
}
|
||||
}
|
||||
|
||||
/// >Gets the name of the company that produced the file.
|
||||
public StringView CompanyName
|
||||
{
|
||||
get
|
||||
{
|
||||
return mCompanyName;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the build number of the file.
|
||||
public int FileBuildPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileBuild;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the description of the file.
|
||||
///
|
||||
public String FileDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileDescription;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the major part of the version number.
|
||||
///
|
||||
public int FileMajorPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileMajor;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the minor
|
||||
/// part of the version number of the file.
|
||||
///
|
||||
public int FileMinorPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileMinor;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the name of the file that this instance describes.
|
||||
///
|
||||
public String FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileName;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the file private part number.
|
||||
///
|
||||
public int FilePrivatePart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFilePrivate;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the file version number.
|
||||
///
|
||||
public String FileVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return mFileVersion;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the internal name of the file, if one exists.
|
||||
///
|
||||
public String InternalName
|
||||
{
|
||||
get
|
||||
{
|
||||
return mInternalName;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets a value that specifies whether the file
|
||||
/// contains debugging information or is compiled with debugging features enabled.
|
||||
///
|
||||
public bool IsDebug
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return (mFileFlags & Windows.VS_FF_DEBUG) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets a value that specifies whether the file has been modified and is not identical to
|
||||
/// the original shipping file of the same version number.
|
||||
///
|
||||
public bool IsPatched
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return (mFileFlags & Windows.VS_FF_PATCHED) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets a value that specifies whether the file was built using standard release procedures.
|
||||
///
|
||||
public bool IsPrivateBuild
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return (mFileFlags & Windows.VS_FF_PRIVATEBUILD) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets a value that specifies whether the file
|
||||
/// is a development version, rather than a commercially released product.
|
||||
///
|
||||
public bool IsPreRelease
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return (mFileFlags & Windows.VS_FF_PRERELEASE) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets a value that specifies whether the file is a special build.
|
||||
///
|
||||
public bool IsSpecialBuild
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return (mFileFlags & Windows.VS_FF_SPECIALBUILD) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// Gets the default language String for the version info block.
|
||||
///
|
||||
///
|
||||
public String Language
|
||||
{
|
||||
get
|
||||
{
|
||||
return mLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets all copyright notices that apply to the specified file.
|
||||
///
|
||||
public String LegalCopyright
|
||||
{
|
||||
get
|
||||
{
|
||||
return mLegalCopyright;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the trademarks and registered trademarks that apply to the file.
|
||||
///
|
||||
public String LegalTrademarks
|
||||
{
|
||||
get
|
||||
{
|
||||
return mLegalTrademarks;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the name the file was created with.
|
||||
///
|
||||
public String OriginalFilename
|
||||
{
|
||||
get
|
||||
{
|
||||
return mOriginalFilename;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets information about a private version of the file.
|
||||
///
|
||||
public String PrivateBuild
|
||||
{
|
||||
get
|
||||
{
|
||||
return mPrivateBuild;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the build number of the product this file is associated with.
|
||||
///
|
||||
public int ProductBuildPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductBuild;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the major part of the version number for the product this file is associated with.
|
||||
///
|
||||
public int ProductMajorPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductMajor;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the minor part of the version number for the product the file is associated with.
|
||||
///
|
||||
public int ProductMinorPart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductMinor;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the name of the product this file is distributed with.
|
||||
///
|
||||
public String ProductName
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductName;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the private part number of the product this file is associated with.
|
||||
///
|
||||
public int ProductPrivatePart
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductPrivate;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the version of the product this file is distributed with.
|
||||
///
|
||||
public String ProductVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProductVersion;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gets the special build information for the file.
|
||||
///
|
||||
public String SpecialBuild
|
||||
{
|
||||
get
|
||||
{
|
||||
return mSpecialBuild;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConvertTo8DigitHex(int value, String s)
|
||||
{
|
||||
s.AppendF("{:X8}", value);
|
||||
}
|
||||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
private static Windows.VS_FIXEDFILEINFO GetFixedFileInfo(void* memPtr)
|
||||
{
|
||||
void* memRef = null;
|
||||
if (Windows.VerQueryValueW(memPtr, "\\".ToScopedNativeWChar!(), ref memRef, var memLen))
|
||||
return *(Windows.VS_FIXEDFILEINFO*)memRef;
|
||||
return .();
|
||||
}
|
||||
|
||||
private static String GetFileVersionLanguage(void* memPtr)
|
||||
{
|
||||
int langid = GetVarEntry(memPtr) >> 16;
|
||||
|
||||
char16[256] langChars = .(0, ?);
|
||||
Windows.VerLanguageNameW((uint32)langid, &langChars, (uint32)langChars.Count);
|
||||
return new String()..Append(&langChars);
|
||||
}
|
||||
|
||||
private static String GetFileVersionString(void* memPtr, String name)
|
||||
{
|
||||
String str = new String();
|
||||
void* memRef = null;
|
||||
if (Windows.VerQueryValueW(memPtr, name.ToScopedNativeWChar!(), ref memRef, var memLen))
|
||||
{
|
||||
if (memRef != null)
|
||||
{
|
||||
str.Append((char16*)memRef);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static int32 GetVarEntry(void* memPtr)
|
||||
{
|
||||
void* memRef = null;
|
||||
if (Windows.VerQueryValueW(memPtr, "\\VarFileInfo\\Translation".ToScopedNativeWChar!(), ref memRef, var memLen))
|
||||
{
|
||||
return ((int32)(*(int16*)(memRef)) << 16) + *(int16*)((uint8*)memRef + 2);
|
||||
}
|
||||
return 0x040904E4;
|
||||
}
|
||||
|
||||
//
|
||||
// This function tries to find version informaiton for a specific codepage.
|
||||
// Returns true when version information is found.
|
||||
//
|
||||
private bool GetVersionInfoForCodePage(void* memIntPtr, String codepage)
|
||||
{
|
||||
StringView template = "\\\\StringFileInfo\\\\{0}\\\\{1}";
|
||||
|
||||
mCompanyName = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "CompanyName"));
|
||||
mFileDescription = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "FileDescription"));
|
||||
mFileVersion = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "FileVersion"));
|
||||
mInternalName = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "InternalName"));
|
||||
mLegalCopyright = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "LegalCopyright"));
|
||||
mOriginalFilename = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "OriginalFilename"));
|
||||
mProductName = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "ProductName"));
|
||||
mProductVersion = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "ProductVersion"));
|
||||
mComments = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "Comments"));
|
||||
mLegalTrademarks = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "LegalTrademarks"));
|
||||
mPrivateBuild = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "PrivateBuild"));
|
||||
mSpecialBuild = GetFileVersionString(memIntPtr, scope String()..AppendF(CultureInfo.InvariantCulture, template, codepage, "SpecialBuild"));
|
||||
|
||||
mLanguage = GetFileVersionLanguage(memIntPtr);
|
||||
|
||||
Windows.VS_FIXEDFILEINFO ffi = GetFixedFileInfo(memIntPtr);
|
||||
mFileMajor = HIWORD(ffi.dwFileVersionMS);
|
||||
mFileMinor = LOWORD(ffi.dwFileVersionMS);
|
||||
mFileBuild = HIWORD(ffi.dwFileVersionLS);
|
||||
mFilePrivate = LOWORD(ffi.dwFileVersionLS);
|
||||
mProductMajor = HIWORD(ffi.dwProductVersionMS);
|
||||
mProductMinor = LOWORD(ffi.dwProductVersionMS);
|
||||
mProductBuild = HIWORD(ffi.dwProductVersionLS);
|
||||
mProductPrivate = LOWORD(ffi.dwProductVersionLS);
|
||||
mFileFlags = (.)ffi.dwFileFlags;
|
||||
|
||||
// fileVersion is chosen based on best guess. Other fields can be used if appropriate.
|
||||
return (mFileVersion != string.Empty);
|
||||
}
|
||||
|
||||
///
|
||||
/// <para>Returns a System.Windows.Forms.FileVersionInfo representing the version information associated with the specified file.
|
||||
///
|
||||
public Result<void, Error> GetVersionInfo(StringView fileName)
|
||||
{
|
||||
if (mFileName != null)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
// Check for the existence of the file. File.Exists returns false
|
||||
// if Read permission is denied.
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
//
|
||||
// The previous version of this code in the success case would require
|
||||
// one imperative Assert for PathDiscovery permission, one Demand for
|
||||
// PathDiscovery permission (blocked by the Assert), and 2 demands for
|
||||
// Read permission. It turns out that File.Exists does a demand for
|
||||
// Read permission, so in the success case, we only need to do a single Demand.
|
||||
// In the success case, this change increases the performance of this
|
||||
// function dramatically.
|
||||
//
|
||||
// In the failure case, we want to remain backwardly compatible by throwing
|
||||
// a SecurityException in the case where Read access is denied
|
||||
// (it can be argued that this is less secure than throwing a FileNotFoundException,
|
||||
// but perhaps not so much as to be worth a breaking change).
|
||||
// File.Exists eats a SecurityException, so we need to Demand for it
|
||||
// here. Since performance in the failure case is not crucial, as an
|
||||
// exception will be thrown anyway, we do a Demand for Read access.
|
||||
// If that does not throw an exception, then we will throw a FileNotFoundException.
|
||||
//
|
||||
// We also change the code to do a declarative Assert for PathDiscovery,
|
||||
// as that performs much better than an imperative Assert.
|
||||
//
|
||||
return .Err(.FileNotFound);
|
||||
}
|
||||
|
||||
mFileName = new String(fileName);
|
||||
char16* wcStr = fileName.ToScopedNativeWChar!();
|
||||
|
||||
uint32 handle; // This variable is not used, but we need an out variable.
|
||||
uint32 infoSize = Windows.GetFileVersionInfoSizeW(wcStr, out handle);
|
||||
|
||||
if (infoSize != 0)
|
||||
{
|
||||
uint8* memPtr = new:ScopedAlloc! uint8[infoSize]*;
|
||||
if (Windows.GetFileVersionInfoW(wcStr, 0, infoSize, memPtr))
|
||||
{
|
||||
int langid = GetVarEntry(memPtr);
|
||||
String langStr = scope .();
|
||||
ConvertTo8DigitHex(langid, langStr);
|
||||
if (!GetVersionInfoForCodePage(memPtr, langStr))
|
||||
{
|
||||
// Some dlls might not contain correct codepage information. In this case we will fail during lookup.
|
||||
// Explorer will take a few shots in dark by trying following ID:
|
||||
//
|
||||
// 040904B0 // US English + CP_UNICODE
|
||||
// 040904E4 // US English + CP_USASCII
|
||||
// 04090000 // US English + unknown codepage
|
||||
// Explorer also randomly guess 041D04B0=Swedish+CP_UNICODE and 040704B0=German+CP_UNICODE) sometimes.
|
||||
// We will try to simulate similiar behavior here.
|
||||
int[] ids = scope .(0x040904B0, 0x040904E4, 0x04090000);
|
||||
for (int id in ids)
|
||||
{
|
||||
if (id != langid)
|
||||
{
|
||||
String idStr = scope .();
|
||||
ConvertTo8DigitHex(id, idStr);
|
||||
if (GetVersionInfoForCodePage(memPtr, idStr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return .Ok;
|
||||
}
|
||||
#else
|
||||
public Result<void, Error> GetVersionInfo(StringView fileName)
|
||||
{
|
||||
return .Err(.NotSupported);
|
||||
}
|
||||
#endif
|
||||
|
||||
private static int32 HIWORD(uint32 val)
|
||||
{
|
||||
return (.)((val << 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
private static int32 LOWORD(uint32 val)
|
||||
{
|
||||
return (.)(val & 0xFFFF);
|
||||
}
|
||||
|
||||
///
|
||||
/// <para>Returns a partial list of properties in System.Windows.Forms.FileVersionInfo
|
||||
/// and their values.
|
||||
///
|
||||
public override void ToString(String str)
|
||||
{
|
||||
String nl = "\r\n";
|
||||
str.Append("File: "); str.Append(FileName); str.Append(nl);
|
||||
str.Append("InternalName: "); str.Append(InternalName); str.Append(nl);
|
||||
str.Append("OriginalFilename: "); str.Append(OriginalFilename); str.Append(nl);
|
||||
str.Append("FileVersion: "); str.Append(FileVersion); str.Append(nl);
|
||||
str.Append("FileDescription: "); str.Append(FileDescription); str.Append(nl);
|
||||
str.Append("Product: "); str.Append(ProductName); str.Append(nl);
|
||||
str.Append("ProductVersion: "); str.Append(ProductVersion); str.Append(nl);
|
||||
str.Append("Debug: "); IsDebug.ToString(str); str.Append(nl);
|
||||
str.Append("Patched: "); IsPatched.ToString(str); str.Append(nl);
|
||||
str.Append("PreRelease: "); IsPreRelease.ToString(str); str.Append(nl);
|
||||
str.Append("PrivateBuild: "); IsPrivateBuild.ToString(str); str.Append(nl);
|
||||
str.Append("SpecialBuild: "); IsSpecialBuild.ToString(str); str.Append(nl);
|
||||
str.Append("Language: "); str.Append(Language); str.Append(nl);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
119
BeefLibs/corlib/src/Diagnostics/Process.bf
Normal file
119
BeefLibs/corlib/src/Diagnostics/Process.bf
Normal file
|
@ -0,0 +1,119 @@
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
class Process
|
||||
{
|
||||
Platform.BfpProcess* mProcess;
|
||||
String mProcessName ~ delete _;
|
||||
|
||||
public int32 Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return Platform.BfpProcess_GetProcessId(mProcess);
|
||||
}
|
||||
}
|
||||
|
||||
public static int32 CurrentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int32)Platform.BfpProcess_GetCurrentId();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAttached
|
||||
{
|
||||
get
|
||||
{
|
||||
return mProcess != null;
|
||||
}
|
||||
}
|
||||
|
||||
public StringView ProcessName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mProcessName == null)
|
||||
{
|
||||
mProcessName = new String();
|
||||
Platform.GetStrHelper(mProcessName, scope (outPtr, outSize, outResult) =>
|
||||
{
|
||||
Platform.BfpProcess_GetProcessName(mProcess, outPtr, outSize, (Platform.BfpProcessResult*)outResult);
|
||||
});
|
||||
}
|
||||
return mProcessName;
|
||||
}
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (mProcess != null)
|
||||
{
|
||||
Platform.BfpProcess_Release(mProcess);
|
||||
mProcess = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Result<void> GetProcessById(String machineName, int32 processId)
|
||||
{
|
||||
if (mProcess != null)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
let bfpProcess = Platform.BfpProcess_GetById((machineName != null) ? machineName : null, processId, null);
|
||||
if (bfpProcess == null)
|
||||
return .Err;
|
||||
mProcess = bfpProcess;
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public Result<void> GetProcessById(int32 processId)
|
||||
{
|
||||
return GetProcessById(null, processId);
|
||||
}
|
||||
|
||||
public void GetMainWindowTitle(String outTitle)
|
||||
{
|
||||
Platform.GetStrHelper(outTitle, scope (outPtr, outSize, outResult) =>
|
||||
{
|
||||
Platform.BfpProcess_GetMainWindowTitle(mProcess, outPtr, outSize, (Platform.BfpProcessResult*)outResult);
|
||||
});
|
||||
}
|
||||
|
||||
public static Result<void> GetProcesses(List<Process> processes)
|
||||
{
|
||||
let result = Platform.GetSizedHelper<Platform.BfpProcess*>(scope (outPtr, outSize, outResult) =>
|
||||
{
|
||||
Platform.BfpProcess_Enumerate(null, outPtr, outSize, (Platform.BfpProcessResult*)outResult);
|
||||
});
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case .Err:
|
||||
return .Err;
|
||||
case .Ok(let bfpProcSpan):
|
||||
for (var proc in bfpProcSpan)
|
||||
{
|
||||
let process = new Process();
|
||||
process.mProcess = proc;
|
||||
processes.Add(process);
|
||||
}
|
||||
delete bfpProcSpan.Ptr;
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
}
|
||||
}
|
18
BeefLibs/corlib/src/Diagnostics/ProcessManager.bf
Normal file
18
BeefLibs/corlib/src/Diagnostics/ProcessManager.bf
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
internal static class ProcessManager
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
|
||||
|
||||
public static bool IsRemoteMachine(StringView machineName)
|
||||
{
|
||||
return Platform.BfpProcess_IsRemoteMachine(machineName.ToScopeCStr!());
|
||||
}
|
||||
|
||||
#endif //BF_PLATFORM_WINDOWS
|
||||
}
|
||||
}
|
13
BeefLibs/corlib/src/Diagnostics/ProcessPriorityClass.bf
Normal file
13
BeefLibs/corlib/src/Diagnostics/ProcessPriorityClass.bf
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
public enum ProcessPriorityClass
|
||||
{
|
||||
Normal = 0x20,
|
||||
Idle = 0x40,
|
||||
High = 0x80,
|
||||
RealTime = 0x100,
|
||||
|
||||
BelowNormal = 0x4000,
|
||||
AboveNormal = 0x8000
|
||||
}
|
||||
}
|
83
BeefLibs/corlib/src/Diagnostics/ProcessStartInfo.bf
Normal file
83
BeefLibs/corlib/src/Diagnostics/ProcessStartInfo.bf
Normal file
|
@ -0,0 +1,83 @@
|
|||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
class ProcessStartInfo
|
||||
{
|
||||
bool mUseShellExecute = true;
|
||||
bool mRedirectStandardInput = false;
|
||||
bool mRedirectStandardOutput = false;
|
||||
bool mRedirectStandardError = false;
|
||||
bool mCreateNoWindow = false;
|
||||
public bool ErrorDialog;
|
||||
//public Windows.Handle ErrorDialogParentHandle;
|
||||
//public ProcessWindowStyle WindowStyle;
|
||||
|
||||
internal String mFileName = new String() ~ delete _;
|
||||
internal String mArguments = new String() ~ delete _;
|
||||
internal String mDirectory = new String() ~ delete _;
|
||||
internal String mVerb = new String("Open") ~ delete _;
|
||||
|
||||
public Dictionary<String, String> mEnvironmentVariables ~ DeleteDictionyAndKeysAndItems!(_);
|
||||
|
||||
public bool UseShellExecute { get { return mUseShellExecute; } set { mUseShellExecute = value; } };
|
||||
public bool RedirectStandardInput { get { return mRedirectStandardInput; } set { mRedirectStandardInput = value; } };
|
||||
public bool RedirectStandardOutput { get { return mRedirectStandardOutput; } set { mRedirectStandardOutput = value; } };
|
||||
public bool RedirectStandardError { get { return mRedirectStandardError; } set { mRedirectStandardError = value; } };
|
||||
public bool CreateNoWindow { get { return mCreateNoWindow; } set { mCreateNoWindow = value; } };
|
||||
|
||||
internal Encoding StandardOutputEncoding;
|
||||
internal Encoding StandardErrorEncoding;
|
||||
|
||||
//public bool redirectStandardInput { get { return redirectStandardInput; } set { redirectStandardInput = value; } };
|
||||
//public bool redirectStandardInput { get { return redirectStandardInput; } set { redirectStandardInput = value; } };
|
||||
|
||||
public void GetFileName(String outFileName)
|
||||
{
|
||||
if (mFileName != null)
|
||||
outFileName.Append(mFileName);
|
||||
}
|
||||
|
||||
public void SetFileName(StringView fileName)
|
||||
{
|
||||
mFileName.Set(fileName);
|
||||
}
|
||||
|
||||
public void SetWorkingDirectory(StringView fileName)
|
||||
{
|
||||
mDirectory.Set(fileName);
|
||||
}
|
||||
|
||||
public void SetArguments(StringView arguments)
|
||||
{
|
||||
mArguments.Set(arguments);
|
||||
}
|
||||
|
||||
public void SetVerb(StringView verb)
|
||||
{
|
||||
mVerb.Set(verb);
|
||||
}
|
||||
|
||||
public void AddEnvironmentVariable(StringView key, StringView value)
|
||||
{
|
||||
if (mEnvironmentVariables == null)
|
||||
{
|
||||
mEnvironmentVariables = new Dictionary<String, String>();
|
||||
Environment.GetEnvironmentVariables(mEnvironmentVariables);
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable(mEnvironmentVariables, key, value);
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
//Debug.WriteLine("ProcStartInfo {0} Verb: {1} Tick: {2}", this, mVerb, (int32)Platform.BfpSystem_TickCount());
|
||||
}
|
||||
|
||||
public this(Process process)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
10
BeefLibs/corlib/src/Diagnostics/ProcessWindowStyle.bf
Normal file
10
BeefLibs/corlib/src/Diagnostics/ProcessWindowStyle.bf
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace System.Diagnostics
|
||||
{
|
||||
public enum ProcessWindowStyle
|
||||
{
|
||||
Normal,
|
||||
Hidden,
|
||||
Minimized,
|
||||
Maximized
|
||||
}
|
||||
}
|
95
BeefLibs/corlib/src/Diagnostics/Profiler.bf
Normal file
95
BeefLibs/corlib/src/Diagnostics/Profiler.bf
Normal file
|
@ -0,0 +1,95 @@
|
|||
using System.Threading;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
enum ProfilerScope
|
||||
{
|
||||
Thread,
|
||||
Process
|
||||
}
|
||||
|
||||
struct ProfileInstance : int32
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
String str = scope String();
|
||||
str.Append("StopSampling\t");
|
||||
((int32)this).ToString(str);
|
||||
Internal.ProfilerCmd(str);
|
||||
}
|
||||
}
|
||||
|
||||
class Profiler
|
||||
{
|
||||
public enum Priority
|
||||
{
|
||||
Low,
|
||||
Normal,
|
||||
High
|
||||
}
|
||||
|
||||
static int32 gProfileId = 1;
|
||||
|
||||
public struct AutoLeave
|
||||
{
|
||||
//Profiler mProfiler;
|
||||
|
||||
public this(/*Profiler profiler*/)
|
||||
{
|
||||
//mProfiler = profiler;
|
||||
}
|
||||
|
||||
void Dispose()
|
||||
{
|
||||
Profiler.LeaveSection();
|
||||
}
|
||||
}
|
||||
|
||||
static Result<ProfileInstance> StartSampling(int threadId, StringView profileDesc, int sampleRate)
|
||||
{
|
||||
int32 curId = Interlocked.Increment(ref gProfileId);
|
||||
|
||||
String str = scope String();
|
||||
str.Append("StartSampling\t");
|
||||
curId.ToString(str);
|
||||
str.Append("\t");
|
||||
threadId.ToString(str);
|
||||
str.Append("\t");
|
||||
sampleRate.ToString(str);
|
||||
str.Append("\t");
|
||||
str.Append(profileDesc);
|
||||
Internal.ProfilerCmd(str);
|
||||
return (ProfileInstance)curId;
|
||||
}
|
||||
|
||||
public static Result<ProfileInstance> StartSampling(Thread thread, StringView profileDesc = default, int sampleRate = -1)
|
||||
{
|
||||
return StartSampling(thread.Id, profileDesc, sampleRate);
|
||||
}
|
||||
|
||||
public static Result<ProfileInstance> StartSampling(StringView profileDesc = default, int sampleRate = -1)
|
||||
{
|
||||
return StartSampling(0, profileDesc, sampleRate);
|
||||
}
|
||||
|
||||
public static void ClearSampling()
|
||||
{
|
||||
Internal.ProfilerCmd("ClearSampling");
|
||||
}
|
||||
|
||||
public void Mark()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static AutoLeave EnterSection(StringView name, Priority priority = Priority.Normal)
|
||||
{
|
||||
return AutoLeave();
|
||||
}
|
||||
|
||||
public static void LeaveSection()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
151
BeefLibs/corlib/src/Diagnostics/SpawnedProcess.bf
Normal file
151
BeefLibs/corlib/src/Diagnostics/SpawnedProcess.bf
Normal file
|
@ -0,0 +1,151 @@
|
|||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
class SpawnedProcess
|
||||
{
|
||||
public enum KillFlags
|
||||
{
|
||||
None = 0,
|
||||
KillChildren = 1
|
||||
}
|
||||
|
||||
Platform.BfpSpawn* mSpawn;
|
||||
int mExitCode = 0;
|
||||
bool mIsDone;
|
||||
|
||||
public int ExitCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!mIsDone)
|
||||
WaitFor(-1);
|
||||
return mExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasExited
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!mIsDone)
|
||||
WaitFor(0);
|
||||
return mIsDone;
|
||||
}
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
mSpawn = null;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
public Result<void> Start(ProcessStartInfo startInfo)
|
||||
{
|
||||
String fileName = startInfo.mFileName;
|
||||
|
||||
Platform.BfpSpawnFlags spawnFlags = .None;
|
||||
if (startInfo.ErrorDialog)
|
||||
spawnFlags |= .ErrorDialog;
|
||||
if (startInfo.UseShellExecute)
|
||||
{
|
||||
spawnFlags |= .UseShellExecute;
|
||||
if (!startInfo.mVerb.IsEmpty)
|
||||
fileName = scope:: String(fileName, "|", startInfo.mVerb);
|
||||
}
|
||||
if (startInfo.CreateNoWindow)
|
||||
spawnFlags |= .NoWindow;
|
||||
if (startInfo.RedirectStandardInput)
|
||||
spawnFlags |= .RedirectStdInput;
|
||||
if (startInfo.RedirectStandardOutput)
|
||||
spawnFlags |= .RedirectStdOutput;
|
||||
if (startInfo.RedirectStandardError)
|
||||
spawnFlags |= .RedirectStdError;
|
||||
|
||||
//startInfo.mEnvironmentVariables
|
||||
|
||||
List<char8> env = scope List<char8>();
|
||||
if (startInfo.mEnvironmentVariables != null)
|
||||
Environment.EncodeEnvironmentVariables(startInfo.mEnvironmentVariables, env);
|
||||
Span<char8> envSpan = env;
|
||||
|
||||
Platform.BfpSpawnResult result = .Ok;
|
||||
mSpawn = Platform.BfpSpawn_Create(fileName, startInfo.mArguments, startInfo.mDirectory, envSpan.Ptr, spawnFlags, &result);
|
||||
|
||||
if ((mSpawn == null) || (result != .Ok))
|
||||
return .Err;
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public Result<void> AttachStandardInput(FileStream stream)
|
||||
{
|
||||
if (mSpawn == null)
|
||||
return .Err;
|
||||
Platform.BfpFile* bfpFile = null;
|
||||
Platform.BfpSpawn_GetStdHandles(mSpawn, &bfpFile, null, null);
|
||||
if (bfpFile == null)
|
||||
return .Err;
|
||||
stream.Attach(bfpFile);
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public Result<void> AttachStandardOutput(FileStream stream)
|
||||
{
|
||||
if (mSpawn == null)
|
||||
return .Err;
|
||||
Platform.BfpFile* bfpFile = null;
|
||||
Platform.BfpSpawn_GetStdHandles(mSpawn, null, &bfpFile, null);
|
||||
if (bfpFile == null)
|
||||
return .Err;
|
||||
stream.Attach(bfpFile);
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public Result<void> AttachStandardError(FileStream stream)
|
||||
{
|
||||
if (mSpawn == null)
|
||||
return .Err;
|
||||
Platform.BfpFile* bfpFile = null;
|
||||
Platform.BfpSpawn_GetStdHandles(mSpawn, null, null, &bfpFile);
|
||||
if (bfpFile == null)
|
||||
return .Err;
|
||||
stream.Attach(bfpFile);
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public bool WaitFor(int waitMS = -1)
|
||||
{
|
||||
if (mSpawn == null)
|
||||
return true;
|
||||
|
||||
if (!Platform.BfpSpawn_WaitFor(mSpawn, waitMS, &mExitCode, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mIsDone = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (mSpawn != null)
|
||||
{
|
||||
Platform.BfpSpawn_Release(mSpawn);
|
||||
mSpawn = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Kill(int32 exitCode = 0, KillFlags killFlags = .None)
|
||||
{
|
||||
if (mSpawn != null)
|
||||
{
|
||||
Platform.BfpSpawn_Kill(mSpawn, exitCode, (Platform.BfpKillFlags)killFlags, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
142
BeefLibs/corlib/src/Diagnostics/Stopwatch.bf
Normal file
142
BeefLibs/corlib/src/Diagnostics/Stopwatch.bf
Normal file
|
@ -0,0 +1,142 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
using System;
|
||||
|
||||
|
||||
namespace System.Diagnostics
|
||||
{
|
||||
public class Stopwatch
|
||||
{
|
||||
private const int64 TicksPerMillisecond = 1000;
|
||||
private const int64 TicksPerSecond = TicksPerMillisecond * 1000;
|
||||
|
||||
private int64 elapsed;
|
||||
private int64 startTimeStamp;
|
||||
private bool isRunning;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// Calling start on a running Stopwatch is a no-op.
|
||||
if (!isRunning)
|
||||
{
|
||||
startTimeStamp = GetTimestamp();
|
||||
isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFrom(Stopwatch sw)
|
||||
{
|
||||
elapsed = sw.elapsed;
|
||||
startTimeStamp = sw.startTimeStamp;
|
||||
isRunning = sw.isRunning;
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
}
|
||||
|
||||
public this(bool startNow)
|
||||
{
|
||||
if (startNow)
|
||||
Start();
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
}
|
||||
|
||||
public static Stopwatch StartNew()
|
||||
{
|
||||
Stopwatch s = new Stopwatch();
|
||||
s.Start();
|
||||
return s;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// Calling stop on a stopped Stopwatch is a no-op.
|
||||
if (isRunning)
|
||||
{
|
||||
int64 endTimeStamp = GetTimestamp();
|
||||
int64 elapsedThisPeriod = endTimeStamp - startTimeStamp;
|
||||
elapsed += elapsedThisPeriod;
|
||||
isRunning = false;
|
||||
|
||||
if (elapsed < 0)
|
||||
{
|
||||
// When measuring small time periods the StopWatch.Elapsed*
|
||||
// properties can return negative values. This is due to
|
||||
// bugs in the basic input/output system (BIOS) or the hardware
|
||||
// abstraction layer (HAL) on machines with variable-speed CPUs
|
||||
// (e.g. Intel SpeedStep).
|
||||
elapsed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
elapsed = 0;
|
||||
isRunning = false;
|
||||
startTimeStamp = 0;
|
||||
}
|
||||
|
||||
// Convenience method for replacing {sw.Reset(); sw.Start();} with a single sw.Restart()
|
||||
public void Restart()
|
||||
{
|
||||
elapsed = 0;
|
||||
startTimeStamp = GetTimestamp();
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get { return isRunning; }
|
||||
}
|
||||
|
||||
public TimeSpan Elapsed
|
||||
{
|
||||
get { return TimeSpan(GetElapsedDateTimeTicks()); }
|
||||
}
|
||||
|
||||
public int64 ElapsedMilliseconds
|
||||
{
|
||||
get { return GetRawElapsedTicks() / TicksPerMillisecond; }
|
||||
}
|
||||
|
||||
public int64 ElapsedMicroseconds
|
||||
{
|
||||
get { return GetRawElapsedTicks(); }
|
||||
}
|
||||
|
||||
public static int64 GetTimestamp()
|
||||
{
|
||||
return Internal.GetTickCountMicro();
|
||||
}
|
||||
|
||||
// Get the elapsed ticks.
|
||||
private int64 GetRawElapsedTicks()
|
||||
{
|
||||
int64 timeElapsed = elapsed;
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
// If the StopWatch is running, add elapsed time since
|
||||
// the Stopwatch is started last time.
|
||||
int64 currentTimeStamp = GetTimestamp();
|
||||
int64 elapsedUntilNow = currentTimeStamp - startTimeStamp;
|
||||
timeElapsed += elapsedUntilNow;
|
||||
}
|
||||
return timeElapsed;
|
||||
}
|
||||
|
||||
// Get the elapsed ticks.
|
||||
private int64 GetElapsedDateTimeTicks()
|
||||
{
|
||||
return GetRawElapsedTicks() * 10;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue