From 192191dc701c18d741fc60a04fe3da2bc5087a22 Mon Sep 17 00:00:00 2001 From: brian Date: Fri, 30 Jan 2004 07:02:36 +0000 Subject: [PATCH] 2003/06/28 06:57:09 darcs-hash:20040130070236-aa32f-2f88643122555ad8a6b00c32d61f80c073dadd19.gz --- src/org/xwt/js/JS.java | 3 + src/org/xwt/js/Regexp.java | 354 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 349 insertions(+), 8 deletions(-) diff --git a/src/org/xwt/js/JS.java b/src/org/xwt/js/JS.java index be82e70..9cd65ee 100644 --- a/src/org/xwt/js/JS.java +++ b/src/org/xwt/js/JS.java @@ -41,6 +41,9 @@ public abstract class JS { /** coerce an object to a Long */ public static long toLong(Object o) { return toNumber(o).longValue(); } + /** coerce an object to an Int */ + public static int toInt(Object o) { return toNumber(o).intValue(); } + /** coerce an object to a Double */ public static double toDouble(Object o) { return toNumber(o).doubleValue(); } diff --git a/src/org/xwt/js/Regexp.java b/src/org/xwt/js/Regexp.java index 9805602..fd85881 100644 --- a/src/org/xwt/js/Regexp.java +++ b/src/org/xwt/js/Regexp.java @@ -1,11 +1,349 @@ -// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] +package org.xwt.js; -package org.xwt.js; -import org.xwt.util.*; -import java.io.*; -import java.util.*; +import gnu.regexp.*; -/** a JavaScript Regexp object */ -class Regexp extends JS.Obj { - // FIXME: implement +public class Regexp extends JS.Obj { + private boolean global; + private RE re; + private int lastIndex; + + public Regexp(JS.Array args) throws JS.Exn { + if(args.length() < 1) throw new JS.Exn("Not enough args to regexp"); + Object arg0 = args.elementAt(0); + if(arg0 instanceof Regexp) { + Regexp r = (Regexp) arg0; + this.global = r.global; + this.re = r.re; + this.lastIndex = r.lastIndex; + } else { + String pattern = arg0.toString(); + String sFlags = null; + int flags = 0; + if(args.length() == 2) sFlags = args.elementAt(1).toString(); + if(sFlags == null) sFlags = ""; + for(int i=0;i= s.length()) { + lastIndex = 0; + return null; + } + + REMatch match = re.getMatch(s,start); + if(global) + lastIndex = match == null ? s.length() : match.getEndIndex(); + if(match == null) + return null; + else + return matchToExecResult(match,re,s); + } + + private static Object matchToExecResult(REMatch match, RE re, String s) { + JS.Obj ret = new JS.Obj(); + ret.put("index",new Integer(match.getStartIndex())); + ret.put("input",s); + int n = re.getNumSubs(); + ret.put("length",new Integer(n+1)); + ret.put("0",match.toString()); + for(int i=1;i<=n;i++) + ret.put(Integer.toString(i),match.toString(i)); + return ret; + } + + + private Object exec(JS.Array args) throws JS.Exn { + if(args.length() < 1) throw new JS.Exn("Not enough args to exec"); + String s = args.elementAt(0).toString(); + return exec(s); + } + + private Object test(JS.Array args) throws JS.Exn { + if(args.length() < 1) throw new JS.Exn("Not enough args to match"); + String s = args.elementAt(0).toString(); + + if(global) { + int start = global ? lastIndex : 0; + if(start < 0 || start >= s.length()) { + lastIndex = 0; + return null; + } + + REMatch match = re.getMatch(s,start); + lastIndex = match != null ? s.length() : match.getEndIndex(); + return wrapBool(match != null); + } else { + return wrapBool(re.getMatch(s) != null); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append('/'); + sb.append(get("source")); + sb.append('/'); + if(global) sb.append('g'); + if(Boolean.TRUE.equals(get("ignoreCase"))) sb.append('i'); + if(Boolean.TRUE.equals(get("multiline"))) sb.append('m'); + return sb.toString(); + } + + public static Object stringMatch(Object o, JS.Array args) throws JS.Exn { + if(args.length() < 1) throw new JS.Exn("not enough args to match"); + Object arg0 = args.elementAt(0); + String s = o.toString(); + RE re; + Regexp regexp = null; + if(arg0 instanceof Regexp) { + regexp = (Regexp) arg0; + re = regexp.re; + } else { + re = newRE(arg0.toString(),0); + } + + if(regexp == null) { + REMatch match = re.getMatch(s); + return matchToExecResult(match,re,s); + } + if(!regexp.global) + return regexp.exec(s); + + JS.Array ret = new JS.Array(); + REMatch[] matches = re.getAllMatches(s); + for(int i=0;i 0) + regexp.lastIndex = matches[matches.length-1].getEndIndex(); + else + regexp.lastIndex = s.length(); + return ret; + } + + public static Object stringSearch(Object o, JS.Array args) throws JS.Exn { + if(args.length() < 1) throw new JS.Exn("not enough args to match"); + Object arg0 = args.elementAt(0); + String s = o.toString(); + RE re; + if(arg0 instanceof Regexp) + re = ((Regexp)arg0).re; + else + re = newRE(arg0.toString(),0); + REMatch match = re.getMatch(s); + if(match == null) return new Integer(-1); + return new Integer(match.getStartIndex()); + } + + public static Object stringReplace(Object o, JS.Array args) throws JS.Exn { + if(args.length() < 2) throw new JS.Exn("not enough args to replace"); + Object arg0 = args.elementAt(0); + Object arg1 = args.elementAt(1); + String s = o.toString(); + RE re; + JS.Callable replaceFunc = null; + String replaceString = null; + Regexp regexp = null; + if(arg0 instanceof Regexp) { + regexp = (Regexp) arg0; + re = regexp.re; + } else { + re = newRE(arg0.toString(),0); + } + if(arg1 instanceof JS.Callable) + replaceFunc = (JS.Callable) arg1; + else + replaceString = arg1.toString(); + REMatch[] matches; + if(regexp != null && regexp.global) { + matches = re.getAllMatches(s); + if(regexp != null) { + if(matches.length > 0) + regexp.lastIndex = matches[matches.length-1].getEndIndex(); + else + regexp.lastIndex = s.length(); + } + } else { + REMatch match = re.getMatch(s); + if(match != null) + matches = new REMatch[]{ match }; + else + matches = new REMatch[0]; + } + + StringBuffer sb = new StringBuffer(s.length()); + int pos = 0; + char[] sa = s.toCharArray(); + for(int i=0;i= '0' && c2 <= '9') { + n = (c - '0') * 10 + (c2 - '0'); + i++; + } else { + n = c - '0'; + } + if(n > 0) + sb.append(match.toString(n)); + break; + case '$': + sb.append('$'); break; + case '&': + sb.append(match.toString()); break; + case '`': + sb.append(source.substring(0,match.getStartIndex())); break; + case '\'': + sb.append(source.substring(match.getEndIndex())); break; + default: + sb.append('$'); + sb.append(c); + } + } + if(i < s.length()) sb.append(s.charAt(i)); + return sb.toString(); + } + + + public static Object stringSplit(Object o,JS.Array args) { + String s = o.toString(); + if(args.length() < 1 || args.elementAt(0) == null || s.length() == 0) { + JS.Array ret = new JS.Array(); + ret.addElement(s); + return ret; + } + Object arg0 = args.elementAt(0); + + int limit = args.length() < 2 ? Integer.MAX_VALUE : JS.toInt(args.elementAt(1)); + if(limit < 0) limit = Integer.MAX_VALUE; + if(limit == 0) return new JS.Array(); + + RE re = null; + Regexp regexp = null; + String sep = null; + JS.Array ret = new JS.Array(); + int p = 0; + + if(arg0 instanceof Regexp) { + regexp = (Regexp) arg0; + re = regexp.re; + } else { + sep = arg0.toString(); + } + + // special case this for speed. additionally, the code below doesn't properly handle + // zero length strings + if(sep != null && sep.length()==0) { + int len = s.length(); + for(int i=0;i