Browse Source

String library is a little less bugged - fixed byte, char, some cases of frontier patterns and uppercase classes patterns

Xanathar 11 years ago
parent
commit
14a85d5311

+ 35 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/StringLibTests.cs

@@ -91,6 +91,41 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			DynValue res = Script.RunString(script);
 			Utils.DynAssert(res, null);
 		}
+		[Test]
+		public void String_Find_9()
+		{
+			string script = @"
+				s = 'Deadline is 30/05/1999, firm'
+				date = '%d%d/%d%d/%d%d%d%d';
+				return s:sub(s:find(date));
+			";
+			DynValue res = Script.RunString(script);
+			Utils.DynAssert(res, "30/05/1999");
+		}
+
+		[Test]
+		public void String_Find_10()
+		{
+			string script = @"
+				s = 'Deadline is 30/05/1999, firm'
+				date = '%f[%S]%d%d/%d%d/%d%d%d%d';
+				return s:sub(s:find(date));
+			";
+			DynValue res = Script.RunString(script);
+			Utils.DynAssert(res, "30/05/1999");
+		}
+
+		[Test]
+		public void String_Find_11()
+		{
+			string script = @"
+				s = 'Deadline is 30/05/1999, firm'
+				date = '%f[%s]%d%d/%d%d/%d%d%d%d';
+				return s:sub(s:find(date));
+			";
+			DynValue res = Script.RunString(script);
+			Assert.IsTrue(res.IsNil());
+		}
 
 
 		[Test]

+ 12 - 2
src/MoonSharp.Interpreter/CoreLib/Patterns/PatternMatching.cs

@@ -105,6 +105,14 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 		private static bool MatchClass(char c, char cl)
 		{
 			bool res;
+			bool reverse = false;
+
+			if (char.IsUpper(cl))
+			{
+				cl = char.ToLower(cl);
+				reverse = true;
+			}
+
 			switch (cl)
 			{
 				case 'a': res = Char.IsLetter(c); break;
@@ -120,7 +128,9 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 				case 'z': res = (c == '\0'); break;  /* deprecated option */
 				default: return (cl == c);
 			}
-			return res;
+
+			if (reverse) return !res;
+			else return res;
 		}
 
 		private static bool MatchBreaketClass(MatchState ms, char c, int p, int ec)
@@ -305,7 +315,7 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 							case 'f': // frontier?
 								{
 									p += 2;
-									if (ms.Pattern[p] != '[')
+									if (p >= ms.Pattern.Length || ms.Pattern[p] != '[')
 										throw new ScriptRuntimeException("missing '[' after '%f' in pattern");
 									int ep = ClassEnd(ms, p); //points to what is next
 									char previous = (s == ms.SrcInit) ? '\0' : ms.Src[s - 1];

+ 16 - 29
src/MoonSharp.Interpreter/CoreLib/Patterns/StringRange.cs

@@ -5,10 +5,10 @@ using System.Text;
 
 namespace MoonSharp.Interpreter.CoreLib.Patterns
 {
-	public class StringRange
+	internal class StringRange
 	{
-		public int Start;
-		public int End;
+		public int Start { get; set; }
+		public int End { get; set; }
 
 		public StringRange()
 		{
@@ -27,39 +27,26 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 			int i = start.IsNil() ? 1 : (int)start.Number;
 			int j = end.IsNil() ? (defaultEnd ?? i) : (int)end.Number;
 
-			return FromLuaRange(i, j);
+			return new StringRange(i, j);
 		}
 
-		public static StringRange FromLuaRange(int start, int end)
-		{
-			StringRange range = new StringRange();
-			range.Start = (start > 0) ? start - 1 : start;
-			range.End = (end > 0) ? end - 1 : end;
-
-			return range;
-		}
 
-		public void MapToString(String value)
+		// Returns the substring of s that starts at i and continues until j; i and j can be negative. 
+		// If, after the translation of negative indices, i is less than 1, it is corrected to 1. 
+		// If j is greater than the string length, it is corrected to that length. 
+		// If, after these corrections, i is greater than j, the function returns the empty string. 		
+		public string ApplyToString(string value)
 		{
-			if (Start < 0)
-			{
-				Start = value.Length + Start;
-			}
+			int i = Start < 0 ? Start + value.Length + 1 : Start;
+			int j = End < 0 ? End + value.Length + 1 : End;
 
-			if (Start < 0)
-			{
-				Start = 0;
-			}
+			if (i < 1) i = 1;
+			if (j > value.Length) j = value.Length;
 
-			if (End < 0)
-			{
-				End = value.Length + End;
-			}
+			if (i > j)
+				return string.Empty;
 
-			if (End >= value.Length)
-			{
-				End = value.Length - 1;
-			}
+			return value.Substring(i - 1, j - i + 1);
 		}
 
 		public int Length()

+ 38 - 32
src/MoonSharp.Interpreter/CoreLib/StringModule.cs

@@ -17,6 +17,37 @@ namespace MoonSharp.Interpreter.CoreLib
 			globalTable.OwnerScript.SetTypeMetatable(DataType.String, stringMetatable);
 		}
 
+		[MoonSharpMethod]
+		public static DynValue @char(ScriptExecutionContext executionContext, CallbackArguments args)
+		{
+			StringBuilder sb = new StringBuilder(args.Count);
+
+			for (int i = 0; i < args.Count; i++)
+			{
+				DynValue v = args[i];
+				double d = 0d;
+
+				if (v.Type == DataType.String)
+				{
+					double? nd = v.CastToNumber();
+					if (nd == null)
+						args.AsType(i, "char", DataType.Number, false);
+					else
+						d = nd.Value;
+				}
+				else
+				{
+					args.AsType(i, "char", DataType.Number, false);
+					d = v.Number;
+				}
+
+				sb.Append((char)(d));
+			}
+
+			return DynValue.NewString(sb.ToString());
+		}
+
+
 		[MoonSharpMethod]
 		public static DynValue @byte(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
@@ -48,22 +79,15 @@ namespace MoonSharp.Interpreter.CoreLib
 
 		private static DynValue PerformByteLike(DynValue vs, DynValue vi, DynValue vj, Func<int, int> filter)
 		{
-			string s = vs.String;
-            int conv_i = vi.IsNil() ? 1 : (int)vi.Number;
-            int conv_j = vj.IsNil() ? conv_i : (int)vj.Number;
+            StringRange range = StringRange.FromLuaRange(vi, vj, null);
+            string s = range.ApplyToString(vs.String);
 
-            StringRange range = StringRange.FromLuaRange(conv_i, conv_j);
-            range.MapToString(vs.String);
-
-            if ((range.Start >= vs.String.Length) || (range.End < range.Start))
-                return DynValue.Nil;
-
-            int length = range.Length();
+            int length = s.Length;
 			DynValue[] rets = new DynValue[length];
 
             for (int i = 0; i < length; ++i)
             {
-                rets[i] = DynValue.NewNumber(filter((int)s[range.Start + i]));
+                rets[i] = DynValue.NewNumber(filter((int)s[i]));
             }
 
 			return DynValue.NewTuple(rets);
@@ -134,26 +158,13 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue v_i = args.AsType(2, "find", DataType.Number, true);
 			DynValue v_plain = args.AsType(3, "find", DataType.Boolean, true);
 
-			int i = v_i.IsNilOrNan() ? int.MinValue : (int)v_i.Number;
+			int i = v_i.IsNilOrNan() ? 1 : (int)v_i.Number;
 
 			bool plain = v_plain.CastToBool();
 
 			return PatternMatching.Str_Find(v_s.String, v_p.String, i, plain);
 		}
 
-        [MoonSharpMethod]
-        public static DynValue @char(ScriptExecutionContext executionContext, CallbackArguments args)
-        {
-            StringBuilder result = new StringBuilder(args.Count);
-
-            for (int i = 0; i < args.Count; ++i)
-            {
-                DynValue value = args.AsType(i, "char", DataType.Number, false);
-                result.Append((char)value.Number);
-            }
-
-            return DynValue.NewString(result.ToString());
-        }
 
         [MoonSharpMethod]
         public static DynValue lower(ScriptExecutionContext executionContext, CallbackArguments args)
@@ -226,14 +237,9 @@ namespace MoonSharp.Interpreter.CoreLib
             DynValue arg_j = args.AsType(2, "sub", DataType.Number, true);
 
 			StringRange range = StringRange.FromLuaRange(arg_i, arg_j, -1);
-            range.MapToString(arg_s.String);
-
-            if ((range.Start >= arg_s.String.Length) || (range.End < range.Start))
-            {
-                return DynValue.NewString("");
-            }
+            string s = range.ApplyToString(arg_s.String);
 
-            return DynValue.NewString(arg_s.String.Substring(range.Start, range.Length()));
+            return DynValue.NewString(s);
         }
 	}
 

+ 9 - 0
src/MoonSharp.Interpreter/DataTypes/Closure.cs

@@ -52,6 +52,15 @@ namespace MoonSharp.Interpreter
 				ClosureContext = emptyClosure;
 		}
 
+		/// <summary>
+		/// Calls this function with the specified args
+		/// </summary>
+		/// <returns></returns>
+		/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception>
+		public DynValue Call()
+		{
+			return OwnerScript.Call(this);
+		}
 
 		/// <summary>
 		/// Calls this function with the specified args