Skip to content

Commit

Permalink
Regex: add couple of regex methods to the devpack (#796)
Browse files Browse the repository at this point in the history
* add couple of regex methods to  the devpack

* Rename methods

* Clean code

* update regex methods

* add comments

---------

Co-authored-by: Fernando Diaz Toledano <shargon@gmail.com>
  • Loading branch information
Jim8y and shargon authored Feb 26, 2024
1 parent fd14cb2 commit 194d98c
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 2 deletions.
109 changes: 109 additions & 0 deletions src/Neo.SmartContract.Framework/ByteString.Extension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using Neo.SmartContract.Framework.Native;
namespace Neo.SmartContract.Framework;

public static class ByteStringExtension
{
/// <summary>
/// Denotes whether provided character is a number.
/// </summary>
/// <param name="byteString">Input to check</param>
/// <returns>True if is number</returns>
public static bool IsNumber(this ByteString byteString)
{
foreach (var value in byteString)
{
if (value is < 48 or > 57)
return false;
}
return true;
}

/// <summary>
/// Denotes whether provided character is a lowercase letter.
/// </summary>
/// <param name="byteString">Input to check</param>
/// <returns>True if is Alpha character</returns>
public static bool IsLowerAlphabet(this ByteString byteString)
{
foreach (var value in byteString)
{
if (value is < 97 or > 122)
return false;
}
return true;
}

/// <summary>
/// Denotes whether provided character is a lowercase letter.
/// </summary>
/// <param name="byteString">Input to check</param>
/// <returns>True if is Alpha character</returns>
public static bool IsUpperAlphabet(this ByteString byteString)
{
foreach (var value in byteString)
{
if (value is < 65 or > 90)
return false;
}
return true;
}

/// <summary>
/// Denotes whether provided character is a lowercase letter.
/// </summary>
/// <param name="byteString">Input to check</param>
/// <returns>True if is Alpha character</returns>
public static bool IsAlphabet(this ByteString byteString)
{
foreach (var value in byteString)
{
if (!((value >= 65 && value <= 90) || (value >= 97 && value <= 122)))
return false;
}
return true;
}

/// <summary>
/// Returns the index of the first occurrence of a given value in an array.
/// </summary>
/// <param name="byteString">Array where to search.</param>
/// <param name="byteToFind">Array to search.</param>
/// <returns>Index where it is located or -1</returns>
public static int IndexOf(this ByteString byteString, ByteString byteToFind)
{
return StdLib.MemorySearch(byteString, byteToFind);
}

/// <summary>
/// Determines whether the beginning of this string instance matches the specified string when compared using the specified culture.
/// </summary>
/// <param name="byteString">Array where to search.</param>
/// <param name="byteToFind">Array to search.</param>
/// <returns>True if start with</returns>
public static bool StartWith(this ByteString byteString, ByteString byteToFind)
{
return StdLib.MemorySearch(byteString, byteToFind) == 0;
}

/// <summary>
/// Determines whether the end of this string instance matches a specified string.
/// </summary>
/// <param name="byteString">Array where to search.</param>
/// <param name="byteToFind">Array to search.</param>
/// <returns>True if ends with</returns>
public static bool EndsWith(this ByteString byteString, ByteString byteToFind)
{
return StdLib.MemorySearch(byteString, byteToFind) + byteToFind.Length == byteString.Length;
}

/// <summary>
/// Checks if the <see cref="ByteString"/> contains the given <see cref="ByteString"/>.
/// </summary>
/// <param name="byteString"><see cref="ByteString"/> to search.</param>
/// <param name="byteToFind"><see cref="ByteString"/> to be searched.</param>
/// <returns></returns>
public static bool Contains(this ByteString byteString, ByteString byteToFind)
{
return StdLib.MemorySearch(byteString, byteToFind) != -1;
}
}
45 changes: 45 additions & 0 deletions tests/Neo.SmartContract.Framework.TestContracts/Contract_Regex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace Neo.SmartContract.Framework.UnitTests.TestClasses
{
public class Contract_Regex : SmartContract
{
public static bool TestStartWith()
{
return ((ByteString)"Hello World").StartWith("Hello");
}

public static int TestIndexOf()
{
return ((ByteString)"Hello World").IndexOf("o");
}

public static bool TestEndWith()
{
return ((ByteString)"Hello World").EndsWith("World");
}

public static bool TestContains()
{
return ((ByteString)"Hello World").Contains("ll");
}

public static bool TestNumberOnly()
{
return ((ByteString)"0123456789").IsNumber();
}

public static bool TestAlphabetOnly()
{
return ((ByteString)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").IsAlphabet();
}

public static bool TestLowerAlphabetOnly()
{
return ((ByteString)"abcdefghijklmnopqrstuvwxyz").IsAlphabet();
}

public static bool TestUpperAlphabetOnly()
{
return ((ByteString)"ABCDEFGHIJKLMNOPQRSTUVWXYZ").IsAlphabet();
}
}
}
82 changes: 82 additions & 0 deletions tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.VM.Types;
using Neo.SmartContract.TestEngine;

namespace Neo.SmartContract.Framework.UnitTests
{
[TestClass]
public class RegexTest
{
private TestEngine.TestEngine _engine;

[TestInitialize]
public void Init()
{
_engine = new TestEngine.TestEngine(snapshot: new TestDataCache());
_engine.AddEntryScript(Utils.Extensions.TestContractRoot + "Contract_Regex.cs");
}

[TestMethod]
public void TestStartWith()
{
var result = _engine.ExecuteTestCaseStandard("testStartWith");
Assert.AreEqual(1, result.Count);
var item = result.Pop<Boolean>();
Assert.IsTrue(item.GetBoolean());
}

[TestMethod]
public void TestIndexOf()
{
_engine.Reset();
var result = _engine.ExecuteTestCaseStandard("testIndexOf");
Assert.AreEqual(1, result.Count);
var item = result.Pop<Integer>();
Assert.AreEqual(4, item.GetInteger());
}

[TestMethod]
public void TestEndWith()
{
var result = _engine.ExecuteTestCaseStandard("testEndWith");
Assert.AreEqual(1, result.Count);
var item = result.Pop<Boolean>();
Assert.IsTrue(item.GetBoolean());
}
[TestMethod]
public void TestContains()
{
var result = _engine.ExecuteTestCaseStandard("testContains");
Assert.AreEqual(1, result.Count);
var item = result.Pop<Boolean>();
Assert.IsTrue(item.GetBoolean());
}

[TestMethod]
public void TestNumberOnly()
{
var result = _engine.ExecuteTestCaseStandard("testNumberOnly");
Assert.AreEqual(1, result.Count);
var item = result.Pop<Boolean>();
Assert.IsTrue(item.GetBoolean());
}

[TestMethod]
public void TestAlphabetOnly()
{
var result = _engine.ExecuteTestCaseStandard("testAlphabetOnly");
Assert.AreEqual(1, result.Count);
Assert.IsTrue(result.Pop<Boolean>().GetBoolean());

_engine.Reset();
result = _engine.ExecuteTestCaseStandard("testLowerAlphabetOnly");
Assert.AreEqual(1, result.Count);
Assert.IsTrue(result.Pop<Boolean>().GetBoolean());

_engine.Reset();
result = _engine.ExecuteTestCaseStandard("testUpperAlphabetOnly");
Assert.AreEqual(1, result.Count);
Assert.IsTrue(result.Pop<Boolean>().GetBoolean());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Neo.VM;
using Neo.VM.Types;
using System;
using Neo.Persistence;
using Neo.SmartContract.TestEngine;
using Array = Neo.VM.Types.Array;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace Neo.SmartContract.Template.UnitTests.templates.neocontractowner
{
/// <summary>
/// You need to build the solution to resolve Ownable class.
/// You need to build the solution to resolve OracleRequest class.
/// </summary>
[TestClass]
public class OracleRequestTests : TestBase<OracleRequest>
Expand Down

0 comments on commit 194d98c

Please sign in to comment.