rt/emul/mini/src/main/java/java/lang/String.java
branchclosure
changeset 1513 ba912ef24b27
parent 1486 b5c7970a39e6
parent 1402 e896bc687984
child 1546 0d62e32b04b2
     1.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java	Fri Apr 25 08:14:12 2014 +0200
     1.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java	Wed Apr 30 15:04:10 2014 +0200
     1.3 @@ -26,7 +26,10 @@
     1.4  package java.lang;
     1.5  
     1.6  import java.io.UnsupportedEncodingException;
     1.7 +import java.lang.reflect.InvocationTargetException;
     1.8 +import java.lang.reflect.Method;
     1.9  import java.util.Comparator;
    1.10 +import java.util.Locale;
    1.11  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    1.12  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    1.13  import org.apidesign.bck2brwsr.core.JavaScriptOnly;
    1.14 @@ -2097,13 +2100,31 @@
    1.15       * @since 1.4
    1.16       * @spec JSR-51
    1.17       */
    1.18 +    public boolean matches(String regex) {
    1.19 +        try {
    1.20 +            return matchesViaJS(regex);
    1.21 +        } catch (Throwable t) {
    1.22 +            // fallback to classical behavior
    1.23 +            try {
    1.24 +                Method m = Class.forName("java.util.regex.Pattern").getMethod("matches", String.class, CharSequence.class);
    1.25 +                return (Boolean)m.invoke(null, regex, this);
    1.26 +            } catch (InvocationTargetException ex) {
    1.27 +                if (ex.getTargetException() instanceof RuntimeException) {
    1.28 +                    throw (RuntimeException)ex.getTargetException();
    1.29 +                }
    1.30 +            } catch (Throwable another) {
    1.31 +                // will report the old one
    1.32 +            }
    1.33 +            throw new RuntimeException(t);
    1.34 +        }
    1.35 +    }
    1.36      @JavaScriptBody(args = { "regex" }, body = 
    1.37            "var self = this.toString();\n"
    1.38          + "var re = new RegExp(regex.toString());\n"
    1.39          + "var r = re.exec(self);\n"
    1.40          + "return r != null && r.length > 0 && self.length == r[0].length;"
    1.41      )
    1.42 -    public boolean matches(String regex) {
    1.43 +    private boolean matchesViaJS(String regex) {
    1.44          throw new UnsupportedOperationException();
    1.45      }
    1.46  
    1.47 @@ -2159,6 +2180,14 @@
    1.48       * @since 1.4
    1.49       * @spec JSR-51
    1.50       */
    1.51 +    @JavaScriptBody(args = { "regex", "newText" }, body = 
    1.52 +          "var self = this.toString();\n"
    1.53 +        + "var re = new RegExp(regex.toString());\n"
    1.54 +        + "var r = re.exec(self);\n"
    1.55 +        + "if (r === null || r.length === 0) return this;\n"
    1.56 +        + "var from = self.indexOf(r[0]);\n"
    1.57 +        + "return this.substring(0, from) + newText + this.substring(from + r[0].length);\n"
    1.58 +    )
    1.59      public String replaceFirst(String regex, String replacement) {
    1.60          throw new UnsupportedOperationException();
    1.61      }
    1.62 @@ -2203,7 +2232,14 @@
    1.63       * @spec JSR-51
    1.64       */
    1.65      public String replaceAll(String regex, String replacement) {
    1.66 -        throw new UnsupportedOperationException();
    1.67 +        String p = this;
    1.68 +        for (;;) {
    1.69 +            String n = p.replaceFirst(regex, replacement);
    1.70 +            if (n == p) {
    1.71 +                return n;
    1.72 +            }
    1.73 +            p = n;
    1.74 +        }
    1.75      }
    1.76  
    1.77      /**
    1.78 @@ -2224,12 +2260,14 @@
    1.79            "var s = this.toString();\n"
    1.80          + "target = target.toString();\n"
    1.81          + "replacement = replacement.toString();\n"
    1.82 +        + "var pos = 0;\n"
    1.83          + "for (;;) {\n"
    1.84 -        + "  var ret = s.replace(target, replacement);\n"
    1.85 -        + "  if (ret === s) {\n"
    1.86 -        + "    return ret;\n"
    1.87 +        + "  var indx = s.indexOf(target, pos);\n"
    1.88 +        + "  if (indx === -1) {\n"
    1.89 +        + "    return s;\n"
    1.90          + "  }\n"
    1.91 -        + "  s = ret;\n"
    1.92 +        + "  pos = indx + replacement.length;\n"
    1.93 +        + "  s = s.substring(0, indx) + replacement + s.substring(indx + target.length);\n"
    1.94          + "}"
    1.95      )
    1.96      public native String replace(CharSequence target, CharSequence replacement);
    1.97 @@ -2315,8 +2353,35 @@
    1.98       * @spec JSR-51
    1.99       */
   1.100      public String[] split(String regex, int limit) {
   1.101 -        throw new UnsupportedOperationException("Needs regexp");
   1.102 +        if (limit <= 0) {
   1.103 +            Object[] arr = splitImpl(this, regex, Integer.MAX_VALUE);
   1.104 +            int to = arr.length;
   1.105 +            if (limit == 0 && to > 0) {
   1.106 +                while (to > 0 && ((String)arr[--to]).isEmpty()) {
   1.107 +                }
   1.108 +                to++;
   1.109 +            }
   1.110 +            String[] ret = new String[to];
   1.111 +            System.arraycopy(arr, 0, ret, 0, to);
   1.112 +            return ret;
   1.113 +        } else {
   1.114 +            Object[] arr = splitImpl(this, regex, limit);
   1.115 +            String[] ret = new String[arr.length];
   1.116 +            int pos = 0;
   1.117 +            for (int i = 0; i < arr.length; i++) {
   1.118 +                final String s = (String)arr[i];
   1.119 +                ret[i] = s;
   1.120 +                pos = indexOf(s, pos) + s.length();
   1.121 +            }
   1.122 +            ret[arr.length - 1] += substring(pos);
   1.123 +            return ret;
   1.124 +        }
   1.125      }
   1.126 +    
   1.127 +    @JavaScriptBody(args = { "str", "regex", "limit"}, body = 
   1.128 +        "return str.split(new RegExp(regex), limit);"
   1.129 +    )
   1.130 +    private static native Object[] splitImpl(String str, String regex, int limit);
   1.131  
   1.132      /**
   1.133       * Splits this string around matches of the given <a
   1.134 @@ -2412,7 +2477,9 @@
   1.135       * @see     java.lang.String#toUpperCase(Locale)
   1.136       * @since   1.1
   1.137       */
   1.138 -//    public String toLowerCase(Locale locale) {
   1.139 +    public String toLowerCase(java.util.Locale locale) {
   1.140 +        return toLowerCase();
   1.141 +    }
   1.142  //        if (locale == null) {
   1.143  //            throw new NullPointerException();
   1.144  //        }
   1.145 @@ -2527,7 +2594,7 @@
   1.146       */
   1.147      @JavaScriptBody(args = {}, body = "return this.toLowerCase();")
   1.148      public String toLowerCase() {
   1.149 -        throw new UnsupportedOperationException("Should be supported but without connection to locale");
   1.150 +        return null;
   1.151      }
   1.152  
   1.153      /**
   1.154 @@ -2578,8 +2645,10 @@
   1.155       * @see     java.lang.String#toLowerCase(Locale)
   1.156       * @since   1.1
   1.157       */
   1.158 +    public String toUpperCase(Locale locale) {
   1.159 +        return toUpperCase();
   1.160 +    }
   1.161      /* not for javascript 
   1.162 -    public String toUpperCase(Locale locale) {
   1.163          if (locale == null) {
   1.164              throw new NullPointerException();
   1.165          }
   1.166 @@ -2693,7 +2762,7 @@
   1.167       */
   1.168      @JavaScriptBody(args = {}, body = "return this.toUpperCase();")
   1.169      public String toUpperCase() {
   1.170 -        throw new UnsupportedOperationException();
   1.171 +        return null;
   1.172      }
   1.173  
   1.174      /**
   1.175 @@ -2804,7 +2873,7 @@
   1.176       * @since  1.5
   1.177       */
   1.178      public static String format(String format, Object ... args) {
   1.179 -        throw new UnsupportedOperationException();
   1.180 +        return format((Locale)null, format, args);
   1.181      }
   1.182  
   1.183      /**
   1.184 @@ -2847,9 +2916,15 @@
   1.185       * @see  java.util.Formatter
   1.186       * @since  1.5
   1.187       */
   1.188 -//    public static String format(Locale l, String format, Object ... args) {
   1.189 -//        return new Formatter(l).format(format, args).toString();
   1.190 -//    }
   1.191 +    public static String format(Locale l, String format, Object ... args) {
   1.192 +        String p = format;
   1.193 +        for (int i = 0; i < args.length; i++) {
   1.194 +            String v = args[i] == null ? "null" : args[i].toString();
   1.195 +            p = p.replaceFirst("%s", v);
   1.196 +        }
   1.197 +        return p;
   1.198 +        // return new Formatter(l).format(format, args).toString();
   1.199 +    }
   1.200  
   1.201      /**
   1.202       * Returns the string representation of the <code>Object</code> argument.
   1.203 @@ -3034,6 +3109,14 @@
   1.204       * @return  a string that has the same contents as this string, but is
   1.205       *          guaranteed to be from a pool of unique strings.
   1.206       */
   1.207 +    @JavaScriptBody(args = {}, body = 
   1.208 +        "var s = this.toString().toString();\n" +
   1.209 +        "var i = String.intern || (String.intern = {})\n" + 
   1.210 +        "if (!i[s]) {\n" +
   1.211 +        "  i[s] = s;\n" +
   1.212 +        "}\n" +
   1.213 +        "return i[s];"
   1.214 +    )
   1.215      public native String intern();
   1.216      
   1.217