Example #1
0
		public virtual object Action(Context cx, Scriptable scope, Scriptable thisObj, object[] args, int actionType)
		{
			GlobData data = new GlobData();
			data.mode = actionType;
			switch (actionType)
			{
				case RegExpProxyConstants.RA_MATCH:
				{
					object rval;
					data.optarg = 1;
					rval = MatchOrReplace(cx, scope, thisObj, args, this, data, false);
					return data.arrayobj == null ? rval : data.arrayobj;
				}

				case RegExpProxyConstants.RA_SEARCH:
				{
					data.optarg = 1;
					return MatchOrReplace(cx, scope, thisObj, args, this, data, false);
				}

				case RegExpProxyConstants.RA_REPLACE:
				{
					object arg1 = args.Length < 2 ? Undefined.instance : args[1];
					string repstr = null;
					Function lambda = null;
					if (arg1 is Function)
					{
						lambda = (Function)arg1;
					}
					else
					{
						repstr = ScriptRuntime.ToString(arg1);
					}
					data.optarg = 2;
					data.lambda = lambda;
					data.repstr = repstr;
					data.dollar = repstr == null ? -1 : repstr.IndexOf('$');
					data.charBuf = null;
					data.leftIndex = 0;
					object val = MatchOrReplace(cx, scope, thisObj, args, this, data, true);
					if (data.charBuf == null)
					{
						if (data.global || val == null || !val.Equals(true))
						{
							return data.str;
						}
						SubString lc = this.leftContext;
						Replace_glob(data, cx, scope, this, lc.index, lc.length);
					}
					SubString rc = this.rightContext;
					data.charBuf.AppendRange(rc.str, rc.index, rc.index + rc.length);
					return data.charBuf.ToString();
				}

				default:
				{
					throw Kit.CodeBug();
				}
			}
		}
Example #2
0
		/// <summary>Analog of C match_or_replace.</summary>
		/// <remarks>Analog of C match_or_replace.</remarks>
		private static object MatchOrReplace(Context cx, Scriptable scope, Scriptable thisObj, object[] args, RegExpImpl reImpl, GlobData data, bool forceFlat)
		{
			NativeRegExp re;
			string str = ScriptRuntime.ToString(thisObj);
			data.str = str;
			Scriptable topScope = ScriptableObject.GetTopLevelScope(scope);
			if (args.Length == 0)
			{
				RECompiled compiled = NativeRegExp.CompileRE(cx, string.Empty, string.Empty, false);
				re = new NativeRegExp(topScope, compiled);
			}
			else
			{
				if (args[0] is NativeRegExp)
				{
					re = (NativeRegExp)args[0];
				}
				else
				{
					string src = ScriptRuntime.ToString(args[0]);
					string opt;
					if (data.optarg < args.Length)
					{
						args[0] = src;
						opt = ScriptRuntime.ToString(args[data.optarg]);
					}
					else
					{
						opt = null;
					}
					RECompiled compiled = NativeRegExp.CompileRE(cx, src, opt, forceFlat);
					re = new NativeRegExp(topScope, compiled);
				}
			}
			data.global = (re.GetFlags() & NativeRegExp.JSREG_GLOB) != 0;
			int[] indexp = new int[] { 0 };
			object result = null;
			if (data.mode == RegExpProxyConstants.RA_SEARCH)
			{
				result = re.ExecuteRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
				if (result != null && result.Equals(true))
				{
					result = Sharpen.Extensions.ValueOf(reImpl.leftContext.length);
				}
				else
				{
					result = Sharpen.Extensions.ValueOf(-1);
				}
			}
			else
			{
				if (data.global)
				{
					re.lastIndex = 0;
					for (int count = 0; indexp[0] <= str.Length; count++)
					{
						result = re.ExecuteRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
						if (result == null || !result.Equals(true))
						{
							break;
						}
						if (data.mode == RegExpProxyConstants.RA_MATCH)
						{
							Match_glob(data, cx, scope, count, reImpl);
						}
						else
						{
							if (data.mode != RegExpProxyConstants.RA_REPLACE)
							{
								Kit.CodeBug();
							}
							SubString lastMatch = reImpl.lastMatch;
							int leftIndex = data.leftIndex;
							int leftlen = lastMatch.index - leftIndex;
							data.leftIndex = lastMatch.index + lastMatch.length;
							Replace_glob(data, cx, scope, reImpl, leftIndex, leftlen);
						}
						if (reImpl.lastMatch.length == 0)
						{
							if (indexp[0] == str.Length)
							{
								break;
							}
							indexp[0]++;
						}
					}
				}
				else
				{
					result = re.ExecuteRegExp(cx, scope, reImpl, str, indexp, ((data.mode == RegExpProxyConstants.RA_REPLACE) ? NativeRegExp.TEST : NativeRegExp.MATCH));
				}
			}
			return result;
		}
Example #3
0
		/// <summary>Analog of do_replace in jsstr.c</summary>
		private static void Do_replace(GlobData rdata, Context cx, RegExpImpl regExpImpl)
		{
			StringBuilder charBuf = rdata.charBuf;
			int cp = 0;
			string da = rdata.repstr;
			int dp = rdata.dollar;
			if (dp != -1)
			{
				int[] skip = new int[1];
				do
				{
					int len = dp - cp;
					charBuf.Append(Sharpen.Runtime.Substring(da, cp, dp));
					cp = dp;
					SubString sub = InterpretDollar(cx, regExpImpl, da, dp, skip);
					if (sub != null)
					{
						len = sub.length;
						if (len > 0)
						{
							charBuf.AppendRange(sub.str, sub.index, sub.index + len);
						}
						cp += skip[0];
						dp += skip[0];
					}
					else
					{
						++dp;
					}
					dp = da.IndexOf('$', dp);
				}
				while (dp >= 0);
			}
			int daL = da.Length;
			if (daL > cp)
			{
				charBuf.Append(Sharpen.Runtime.Substring(da, cp, daL));
			}
		}
Example #4
0
		private static void Replace_glob(GlobData rdata, Context cx, Scriptable scope, RegExpImpl reImpl, int leftIndex, int leftlen)
		{
			int replen;
			string lambdaStr;
			if (rdata.lambda != null)
			{
				// invoke lambda function with args lastMatch, $1, $2, ... $n,
				// leftContext.length, whole string.
				SubString[] parens = reImpl.parens;
				int parenCount = (parens == null) ? 0 : parens.Length;
				object[] args = new object[parenCount + 3];
				args[0] = reImpl.lastMatch.ToString();
				for (int i = 0; i < parenCount; i++)
				{
					SubString sub = parens[i];
					if (sub != null)
					{
						args[i + 1] = sub.ToString();
					}
					else
					{
						args[i + 1] = Undefined.instance;
					}
				}
				args[parenCount + 1] = Sharpen.Extensions.ValueOf(reImpl.leftContext.length);
				args[parenCount + 2] = rdata.str;
				// This is a hack to prevent expose of reImpl data to
				// JS function which can run new regexps modifing
				// regexp that are used later by the engine.
				// TODO: redesign is necessary
				if (reImpl != ScriptRuntime.GetRegExpProxy(cx))
				{
					Kit.CodeBug();
				}
				RegExpImpl re2 = new RegExpImpl();
				re2.multiline = reImpl.multiline;
				re2.input = reImpl.input;
				ScriptRuntime.SetRegExpProxy(cx, re2);
				try
				{
					Scriptable parent = ScriptableObject.GetTopLevelScope(scope);
					object result = rdata.lambda.Call(cx, parent, parent, args);
					lambdaStr = ScriptRuntime.ToString(result);
				}
				finally
				{
					ScriptRuntime.SetRegExpProxy(cx, reImpl);
				}
				replen = lambdaStr.Length;
			}
			else
			{
				lambdaStr = null;
				replen = rdata.repstr.Length;
				if (rdata.dollar >= 0)
				{
					int[] skip = new int[1];
					int dp = rdata.dollar;
					do
					{
						SubString sub = InterpretDollar(cx, reImpl, rdata.repstr, dp, skip);
						if (sub != null)
						{
							replen += sub.length - skip[0];
							dp += skip[0];
						}
						else
						{
							++dp;
						}
						dp = rdata.repstr.IndexOf('$', dp);
					}
					while (dp >= 0);
				}
			}
			int growth = leftlen + replen + reImpl.rightContext.length;
			StringBuilder charBuf = rdata.charBuf;
			if (charBuf == null)
			{
				charBuf = new StringBuilder(growth);
				rdata.charBuf = charBuf;
			}
			else
			{
				charBuf.EnsureCapacity(rdata.charBuf.Length + growth);
			}
			charBuf.AppendRange(reImpl.leftContext.str, leftIndex, leftIndex + leftlen);
			if (rdata.lambda != null)
			{
				charBuf.Append(lambdaStr);
			}
			else
			{
				Do_replace(rdata, cx, reImpl);
			}
		}
Example #5
0
		private static void Match_glob(GlobData mdata, Context cx, Scriptable scope, int count, RegExpImpl reImpl)
		{
			if (mdata.arrayobj == null)
			{
				mdata.arrayobj = cx.NewArray(scope, 0);
			}
			SubString matchsub = reImpl.lastMatch;
			string matchstr = matchsub.ToString();
			mdata.arrayobj.Put(count, mdata.arrayobj, matchstr);
		}