Skip to content

Commit

Permalink
Finally Directory.Info function again calling the right plug too: IFi…
Browse files Browse the repository at this point in the history
…leSystemObject_get_Exists!

- Modified String.Compare() to be totally managed code & added tests
- Clean up
  • Loading branch information
fanoI committed Jan 3, 2018
1 parent f201619 commit b337241
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 150 deletions.
34 changes: 33 additions & 1 deletion Tests/Cosmos.Compiler.Tests.Bcl/System/StringTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public static void Execute()
string substr = str.Substring(0, 6);
Assert.IsTrue((substr == expected), "Substring is not equal to the expected result, result should be \"Cosmos\". Substrings are broken or MichaelTheShifter made an off-by-one error.");


int value1 = 1;
string value2 = "4";
string expected_res = "1 + 3 = 4";
Expand Down Expand Up @@ -66,6 +65,39 @@ public static void Execute()
char[] char_array_expected = { 'c', 'h', 'a', 'r' };
Assert.IsTrue((char_array_test.ToCharArray().Length == 4), "string.ToCharArray() does not work.");

string strA;
string strB;
int comparisionResult;

strA = "Test";
strB = "Test";

comparisionResult = String.Compare(strA, 0, strB, 0, strA.Length, StringComparison.Ordinal);
Assert.IsTrue(comparisionResult == 0, "String.Compare (same string) not working!");

strA = "\x0041\x0042\x0043";
strB = "\x0061\x0062\x0063";

comparisionResult = String.Compare(strA, 0, strB, 0, strA.Length, StringComparison.Ordinal);
Assert.IsTrue(comparisionResult == -32, "String.Compare (uppercase vs lowercase) not working!");

strA = "\x0041\x0042\x0043";
strB = "\x0041\x0062\x0063";

comparisionResult = String.Compare(strA, 0, strB, 0, strA.Length, StringComparison.Ordinal);
Assert.IsTrue(comparisionResult == -32, "String.Compare (first letter same) not working!");

strA = "Horse";
strB = "Morse"; /* . _ . */

comparisionResult = String.Compare(strA, 1, strB, 1, strA.Length, StringComparison.Ordinal);
Assert.IsTrue(comparisionResult == 0, "String.Compare (first letter different skipped) not working!");

strA = "\x0041\x0042\x0043";
strB = "\x0061\x0062\x0063";

comparisionResult = String.Compare(strA, 0, strB, 0, strA.Length, StringComparison.OrdinalIgnoreCase);
Assert.IsTrue(comparisionResult == 0, "String.Compare (uppercase vs lowercase ignoring case) not working!");
}
}
}
5 changes: 1 addition & 4 deletions Tests/Cosmos.Compiler.Tests.Bcl/System/UnsafeCodeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,11 @@ public static unsafe void TestFixed()
val1 = StartsWithOrdinal(path, (uint)pathLength, "\\\\?\\");
}

Assert.IsTrue(val1 == false, "Path does is UNC path");
Assert.IsTrue(val1 == false, "Path is not UNC path");
}

public static void Execute()
{

long val = Int64.MaxValue;
long* p = &val;
long newVal = *p;
Expand Down Expand Up @@ -74,8 +73,6 @@ public static void Execute()
//Assert.IsTrue(asLong == 0x3FF0000000000000, "DoubleToInt64Bits is wrong!");

TestFixed();

}

}
}
154 changes: 19 additions & 135 deletions source/Cosmos.Core_Plugs/System/StringImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -865,151 +865,35 @@ public static string TrimStart(string aThis, string aSubStr)
return aFirstChar;
}

/*
* This function has been copied straight from CoreRt, it seems a sort of conversion from ASM or C of a safe
* memcmp() in future it could become MemoryOperations.Compare()
*/
private static unsafe int FastCompareStringHelper(uint* strAChars, int countA, uint* strBChars, int countB)
public static unsafe int CompareOrdinalHelper(string strA, int indexA, int countA, string strB, int indexB, int countB)
{
// Please note that Argument validation should be handled by callers.
int count = (countA < countB) ? countA : countB;
int xResult = 0;

#if BIT64
long diff = (long)((byte*)strAChars - (byte*)strBChars);
#else
int diff = (int)((byte*)strAChars - (byte*)strBChars);
#endif

#if BIT64
int alignmentA = (int)((long)strAChars) & (sizeof(IntPtr) - 1);
int alignmentB = (int)((long)strBChars) & (sizeof(IntPtr) - 1);
strA = strA.Substring(indexA);
strB = strB.Substring(indexB);

if (alignmentA == alignmentB)
/*
* This optimization is not taking effect yet in Cosmos as String.Intern() is not implemented
*/
if (ReferenceEquals(strA, strB))
{
if ((alignmentA == 2 || alignmentA == 6) && (count >= 1))
{
char* ptr2 = (char*)strBChars;

if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);

strBChars = (uint*)(++ptr2);
count -= 1;
alignmentA = (alignmentA == 2 ? 4 : 0);
}

if ((alignmentA == 4) && (count >= 2))
{
uint* ptr2 = (uint*)strBChars;

if ((*((uint*)((byte*)ptr2 + diff)) - *ptr2) != 0)
{
char* chkptr1 = (char*)((byte*)strBChars + diff);
char* chkptr2 = (char*)strBChars;

if (*chkptr1 != *chkptr2)
return ((int)*chkptr1 - (int)*chkptr2);
return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
}
strBChars = ++ptr2;
count -= 2;
alignmentA = 0;
}

if ((alignmentA == 0))
{
while (count >= 4)
{
long* ptr2 = (long*)strBChars;

if ((*((long*)((byte*)ptr2 + diff)) - *ptr2) != 0)
{
if ((*((uint*)((byte*)ptr2 + diff)) - *(uint*)ptr2) != 0)
{
char* chkptr1 = (char*)((byte*)strBChars + diff);
char* chkptr2 = (char*)strBChars;

if (*chkptr1 != *chkptr2)
return ((int)*chkptr1 - (int)*chkptr2);
return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
}
else
{
char* chkptr1 = (char*)((uint*)((byte*)strBChars + diff) + 1);
char* chkptr2 = (char*)((uint*)strBChars + 1);

if (*chkptr1 != *chkptr2)
return ((int)*chkptr1 - (int)*chkptr2);
return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
}
}
strBChars = (uint*)(++ptr2);
count -= 4;
}
}

{
char* ptr2 = (char*)strBChars;
while ((count -= 1) >= 0)
{
if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);
++ptr2;
}
}
mDebugger.SendInternal($"strA ({strA}) is the same object of strB ({strB}) returning 0");
return 0;
}
else
#endif // BIT64
{
#if BIT64
if (Math.Abs(alignmentA - alignmentB) == 4)
{
if ((alignmentA == 2) || (alignmentB == 2))
{
char* ptr2 = (char*)strBChars;

if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);
strBChars = (uint*)(++ptr2);
count -= 1;
}
}
#endif // BIT64

// Loop comparing a DWORD at a time.
// Reads are potentially unaligned
while ((count -= 2) >= 0)
{
if ((*((uint*)((byte*)strBChars + diff)) - *strBChars) != 0)
{
char* ptr1 = (char*)((byte*)strBChars + diff);
char* ptr2 = (char*)strBChars;
if (*ptr1 != *ptr2)
return ((int)*ptr1 - (int)*ptr2);
return ((int)*(ptr1 + 1) - (int)*(ptr2 + 1));
}
++strBChars;
}

int c;
if (count == -1)
if ((c = *((char*)((byte*)strBChars + diff)) - *((char*)strBChars)) != 0)
return c;
}

return countA - countB;
}
mDebugger.SendInternal($"strA ({strA}) is NOT the same object of StrB ({strB})");

public static unsafe int CompareOrdinalHelper(string strA, int indexA, int countA, string strB, int indexB, int countB)
{
// Please note that Argument validation should be handled by callers.

// Set up the loop variables.
fixed (char* pStrA = strA, pStrB = strB)
for (int i = 0; i < count; i++)
{
char* strAChars = pStrA + indexA;
char* strBChars = pStrB + indexB;
return FastCompareStringHelper((uint*)strAChars, countA, (uint*)strBChars, countB);
xResult = strA[i] - strB[i];
// Different characters we have finished
if (xResult != 0)
break;
}

return xResult;
}

public static int CompareOrdinalHelperIgnoreCase(string strA, int indexA, int countA, string strB, int indexB, int countB)
Expand Down
9 changes: 6 additions & 3 deletions source/Cosmos.System2_Plugs/System/IO/CosmosFileSystemInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//#define COSMOSDEBUG
#define COSMOSDEBUG
using System.IO;
using IL2CPU.API.Attribs;
using Cosmos.System;
Expand All @@ -16,12 +16,15 @@ namespace Cosmos.System_Plugs.System.IO
[Plug(Target = typeof(FileSystemInfo))]
public static class CosmosFileSystemInfo
{
[PlugMethod(Signature = "System_Boolean__System_IO_FileSystemInfo__System_IO_IFileSystemObject_get_Exists")]
[PlugMethod(Signature = "System_Boolean__System_IO_FileSystemInfo_System_IO_IFileSystemObject_get_Exists__")]
public static bool get_Exists(FileSystemInfo aThis)
{
Global.mFileSystemDebugger.SendInternal($"FileSystemInfo.get_Exists : fullPath = {aThis.FullName}");
// TODO we have to find if 'aThis' is a DirectoryInfo or a FileInfo to decide what method to call
return VFSManager.DirectoryExists(aThis.FullName);
if (aThis is DirectoryInfo)
return VFSManager.DirectoryExists(aThis.FullName);
else
return VFSManager.FileExists(aThis.FullName);
}

public static FileAttributes get_Attributes(FileSystemInfo aThis)
Expand Down
7 changes: 0 additions & 7 deletions source/Cosmos.System2_Plugs/System/IO/DirectoryInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ namespace Cosmos.System_Plugs.System.IO
[Plug(Target = typeof(DirectoryInfo))]
public static class DirectoryInfoImpl
{
public static bool get_Exists(DirectoryInfo aThis)
{
string aPath = aThis.FullName;
Global.mFileSystemDebugger.SendInternal($"DirectoryInfo.Exists : aPath = {aPath}");
return VFSManager.DirectoryExists(aPath);
}

/* The real implementation uses IEnumerable and do a conversion ToArray that crashes IL2CPU */
public static DirectoryInfo[] GetDirectories(DirectoryInfo aThis)
{
Expand Down
4 changes: 4 additions & 0 deletions source/Cosmos.System2_Plugs/System/IO/FileInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ namespace Cosmos.System2_Plugs.System.IO
[Plug(Target = typeof(FileInfo))]
public static class FileInfoImpl
{
/*
* If I try to remove this as done with DirectoryInfo the satanic IFileSystemObject.get_Exists
* of CosmosFileSystemInfo is not found... again! Why works with DirectoryInfo and not with FileInfo?
*/
public static bool get_Exists(FileInfo aThis)
{
string aPath = aThis.FullName;
Expand Down

0 comments on commit b337241

Please sign in to comment.