Mercurial Hosting > luan
view core/src/luan/modules/StringLuan.java @ 572:f1601a4ce1aa
fix stack when calling meta-methods
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 12 Jul 2015 21:34:23 -0600 |
parents | e25ba7a2e816 |
children | 6cc2f047019b |
line wrap: on
line source
package luan.modules; import java.util.regex.Pattern; import java.util.regex.Matcher; import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; import luan.LuanJavaFunction; import luan.LuanElement; import luan.LuanException; import luan.LuanMethod; import luan.LuanBit; public final class StringLuan { static int start(String s,int i) { int len = s.length(); return i==0 ? 0 : i > 0 ? Math.min(i-1,len) : Math.max(len+i,0); } static int start(String s,Integer i,int dflt) { return i==null ? dflt : start(s,i); } static int end(String s,int i) { int len = s.length(); return i==0 ? 0 : i > 0 ? Math.min(i,len) : Math.max(len+i+1,0); } static int end(String s,Integer i,int dflt) { return i==null ? dflt : end(s,i); } @LuanMethod public static Integer[] unicode(LuanState luan,String s,Integer i,Integer j) throws LuanException { Utils.checkNotNull(luan,s); int start = start(s,i,1); int end = end(s,j,start+1); Integer[] chars = new Integer[end-start]; for( int k=0; k<chars.length; k++ ) { chars[k] = (int)s.charAt(start+k); } return chars; } public static String char_(int... chars) { char[] a = new char[chars.length]; for( int i=0; i<chars.length; i++ ) { a[i] = (char)chars[i]; } return new String(a); } @LuanMethod public static byte[] to_binary(String s) { return s.getBytes(); } public static String lower(LuanState luan,String s) throws LuanException { Utils.checkNotNull(luan,s); return s.toLowerCase(); } public static String upper(LuanState luan,String s) throws LuanException { Utils.checkNotNull(luan,s); return s.toUpperCase(); } public static String trim(LuanState luan,String s) throws LuanException { Utils.checkNotNull(luan,s); return s.trim(); } public static String reverse(LuanState luan,String s) throws LuanException { Utils.checkNotNull(luan,s); return new StringBuilder(s).reverse().toString(); } public static String rep(String s,int n,String sep) { if( n < 1 ) return ""; StringBuilder buf = new StringBuilder(s); while( --n > 0 ) { if( sep != null ) buf.append(sep); buf.append(s); } return buf.toString(); } public static String sub(LuanState luan,String s,int i,Integer j) throws LuanException { Utils.checkNotNull(luan,s); int start = start(s,i); int end = end(s,j,s.length()); return s.substring(start,end); } @LuanMethod public static Object[] find(String s,String pattern,Integer init,Boolean plain) { int start = start(s,init,0); if( Boolean.TRUE.equals(plain) ) { int i = s.indexOf(pattern,start); return i == -1 ? null : new Integer[]{i+1,i+pattern.length()}; } Matcher m = Pattern.compile(pattern).matcher(s); if( !m.find(start) ) return null; int n = m.groupCount(); Object[] rtn = new Object[2+n]; rtn[0] = m.start() + 1; rtn[1] = m.end(); for( int i=0; i<n; i++ ) { rtn[2+i] = m.group(i+1); } return rtn; } @LuanMethod public static String[] match(String s,String pattern,Integer init) { int start = start(s,init,0); Matcher m = Pattern.compile(pattern).matcher(s); if( !m.find(start) ) return null; int n = m.groupCount(); if( n == 0 ) return new String[]{m.group()}; String[] rtn = new String[n]; for( int i=0; i<n; i++ ) { rtn[i] = m.group(i+1); } return rtn; } public static LuanFunction gmatch(LuanState luan,String s,String pattern) throws LuanException { Utils.checkNotNull(luan,s); final Matcher m = Pattern.compile(pattern).matcher(s); return new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) { if( !m.find() ) return null; final int n = m.groupCount(); if( n == 0 ) return m.group(); String[] rtn = new String[n]; for( int i=0; i<n; i++ ) { rtn[i] = m.group(i+1); } return rtn; } }; } @LuanMethod public static Object[] gsub(LuanState luan,String s,String pattern,Object repl,Integer n) throws LuanException { int max = n==null ? Integer.MAX_VALUE : n; final Matcher m = Pattern.compile(pattern).matcher(s); if( repl instanceof String ) { String replacement = (String)repl; int i = 0; StringBuffer sb = new StringBuffer(); while( i<max && m.find() ) { m.appendReplacement(sb,replacement); i++; } m.appendTail(sb); return new Object[]{ sb.toString(), i }; } if( repl instanceof LuanTable ) { LuanTable t = (LuanTable)repl; int i = 0; StringBuffer sb = new StringBuffer(); while( i<max && m.find() ) { String match = m.groupCount()==0 ? m.group() : m.group(1); Object val = t.get(luan.JAVA,match); if( val != null ) { String replacement = luan.JAVA.toString(val); m.appendReplacement(sb,replacement); } i++; } m.appendTail(sb); return new Object[]{ sb.toString(), i }; } if( repl instanceof LuanFunction ) { LuanFunction fn = (LuanFunction)repl; int i = 0; StringBuffer sb = new StringBuffer(); while( i<max && m.find() ) { Object[] args; final int count = m.groupCount(); if( count == 0 ) { args = new String[]{m.group()}; } else { args = new String[count]; for( int j=0; j<count; j++ ) { args[j] = m.group(j+1); } } Object val = Luan.first( luan.call(fn,"repl-arg",args) ); if( val != null ) { String replacement = luan.JAVA.toString(val); m.appendReplacement(sb,replacement); } i++; } m.appendTail(sb); return new Object[]{ sb.toString(), i }; } throw luan.exception( "bad argument #3 to 'gsub' (string/function/table expected)" ); } // note - String.format() is too stupid to convert between ints and floats. public static String format(String format,Object... args) { return String.format(format,args); } public static String concat(LuanState luan,Object... args) throws LuanException { StringBuilder sb = new StringBuilder(); for( Object arg : args ) { sb.append( luan.JAVA.toString(arg) ); } return sb.toString(); } public static String encode(String s) { return Luan.stringEncode(s); } public static Number to_number(LuanState luan,String s,Integer base) throws LuanException { Utils.checkNotNull(luan,s); try { if( base == null ) { return Double.valueOf(s); } else { return Long.valueOf(s,base); } } catch(NumberFormatException e) {} return null; } public static boolean matches(String s,String pattern) { return s.matches(pattern); } }