comparison src/luan/lib/StringLib.java @ 43:80b67b1a653c

implement string lib git-svn-id: https://luan-java.googlecode.com/svn/trunk@44 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 25 Dec 2012 03:42:42 +0000
parents
children 57054fa43189
comparison
equal deleted inserted replaced
42:786699c78837 43:80b67b1a653c
1 package luan.lib;
2
3 import java.util.regex.Pattern;
4 import java.util.regex.Matcher;
5 import luan.Lua;
6 import luan.LuaState;
7 import luan.LuaTable;
8 import luan.LuaFunction;
9 import luan.LuaJavaFunction;
10 import luan.LuaNumber;
11 import luan.LuaElement;
12 import luan.LuaException;
13
14
15 public final class StringLib {
16
17 public static void register(LuaState lua) {
18 LuaTable module = new LuaTable();
19 LuaTable global = lua.global();
20 global.put("string",module);
21 try {
22 module.put( "byte", new LuaJavaFunction(StringLib.class.getMethod("byte_",String.class,Integer.class,Integer.class),null) );
23 module.put( "char", new LuaJavaFunction(StringLib.class.getMethod("char_",new byte[0].getClass()),null) );
24 add( module, "find", String.class, String.class, Integer.class, Boolean.class );
25 add( module, "gmatch", String.class, String.class );
26 add( module, "gsub", LuaState.class, String.class, String.class, Object.class, Integer.class );
27 add( module, "len", String.class );
28 add( module, "lower", String.class );
29 add( module, "match", String.class, String.class, Integer.class );
30 add( module, "rep", String.class, Integer.TYPE, String.class );
31 add( module, "reverse", String.class );
32 add( module, "sub", String.class, Integer.TYPE, Integer.class );
33 add( module, "upper", String.class );
34 } catch(NoSuchMethodException e) {
35 throw new RuntimeException(e);
36 }
37 }
38
39 private static void add(LuaTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
40 t.put( method, new LuaJavaFunction(StringLib.class.getMethod(method,parameterTypes),null) );
41 }
42
43 static int start(String s,int i) {
44 return i==0 ? 0 : i > 0 ? i - 1 : s.length() + i;
45 }
46
47 static int start(String s,Integer i,int dflt) {
48 return i==null ? dflt : start(s,i);
49 }
50
51 static int end(String s,int i) {
52 return i==0 ? 0 : i > 0 ? i : s.length() + i + 1;
53 }
54
55 static int end(String s,Integer i,int dflt) {
56 return i==null ? dflt : end(s,i);
57 }
58
59 public static byte[] byte_(String s,Integer i,Integer j) {
60 int start = start(s,i,0);
61 int end = end(s,j,start+1);
62 return s.substring(start,end).getBytes();
63 }
64
65 public static String char_(byte... bytes) {
66 return new String(bytes);
67 }
68
69 // format is hard because String.format() is too stupid to convert ints to floats.
70
71 public static int len(String s) {
72 return s.length();
73 }
74
75 public static String lower(String s) {
76 return s.toLowerCase();
77 }
78
79 public static String upper(String s) {
80 return s.toUpperCase();
81 }
82
83 public static String reverse(String s) {
84 return new StringBuilder(s).reverse().toString();
85 }
86
87 public static String rep(String s,int n,String sep) {
88 if( n < 1 )
89 return "";
90 StringBuilder buf = new StringBuilder(s);
91 while( --n > 0 ) {
92 if( sep != null )
93 buf.append(sep);
94 buf.append(s);
95 }
96 return buf.toString();
97 }
98
99 public static String sub(String s,int i,Integer j) {
100 int start = start(s,i);
101 int end = end(s,j,s.length());
102 return s.substring(start,end);
103 }
104
105 public static int[] find(String s,String pattern,Integer init,Boolean plain) {
106 int start = start(s,init,0);
107 if( Boolean.TRUE.equals(plain) ) {
108 int i = s.indexOf(pattern,start);
109 return i == -1 ? null : new int[]{i+1,i+pattern.length()};
110 }
111 Matcher m = Pattern.compile(pattern).matcher(s);
112 return m.find(start) ? new int[]{m.start()+1,m.end()} : null;
113 }
114
115 public static String[] match(String s,String pattern,Integer init) {
116 int start = start(s,init,0);
117 Matcher m = Pattern.compile(pattern).matcher(s);
118 if( !m.find(start) )
119 return null;
120 final int n = m.groupCount();
121 if( n == 0 )
122 return new String[]{m.group()};
123 String[] rtn = new String[n];
124 for( int i=0; i<n; i++ ) {
125 rtn[i] = m.group(i);
126 }
127 return rtn;
128 }
129
130 public static LuaFunction gmatch(String s,String pattern) {
131 final Matcher m = Pattern.compile(pattern).matcher(s);
132 return new LuaFunction() {
133 public Object[] call(LuaState lua,Object[] args) {
134 if( !m.find() )
135 return LuaFunction.EMPTY_RTN;
136 final int n = m.groupCount();
137 if( n == 0 )
138 return new String[]{m.group()};
139 String[] rtn = new String[n];
140 for( int i=0; i<n; i++ ) {
141 rtn[i] = m.group(i);
142 }
143 return rtn;
144 }
145 };
146 }
147
148 public static Object[] gsub(LuaState lua,String s,String pattern,Object repl,Integer n) throws LuaException {
149 int max = n==null ? Integer.MAX_VALUE : n;
150 final Matcher m = Pattern.compile(pattern).matcher(s);
151 if( repl instanceof String ) {
152 String replacement = (String)repl;
153 int i = 0;
154 StringBuffer sb = new StringBuffer();
155 while( i<max && m.find() ) {
156 m.appendReplacement(sb,replacement);
157 i++;
158 }
159 m.appendTail(sb);
160 return new Object[]{ sb.toString(), new LuaNumber(i) };
161 }
162 if( repl instanceof LuaTable ) {
163 LuaTable t = (LuaTable)repl;
164 int i = 0;
165 StringBuffer sb = new StringBuffer();
166 while( i<max && m.find() ) {
167 String match = m.groupCount()==0 ? m.group() : m.group(0);
168 Object val = t.get(match);
169 if( Lua.toBoolean(val) ) {
170 String replacement = Lua.asString(val);
171 if( replacement==null )
172 throw new LuaException( lua, LuaElement.JAVA, "invalid replacement value (a "+Lua.type(val)+")" );
173 m.appendReplacement(sb,replacement);
174 }
175 i++;
176 }
177 m.appendTail(sb);
178 return new Object[]{ sb.toString(), new LuaNumber(i) };
179 }
180 if( repl instanceof LuaFunction ) {
181 LuaFunction fn = (LuaFunction)repl;
182 int i = 0;
183 StringBuffer sb = new StringBuffer();
184 while( i<max && m.find() ) {
185 Object[] args;
186 final int count = m.groupCount();
187 if( count == 0 ) {
188 args = new Object[]{m.group()};
189 } else {
190 args = new Object[count];
191 for( int j=0; j<count; j++ ) {
192 args[j] = m.group(j);
193 }
194 }
195 Object val = Lua.first( lua.call(fn,LuaElement.JAVA,"repl-arg",args) );
196 if( Lua.toBoolean(val) ) {
197 String replacement = Lua.asString(val);
198 if( replacement==null )
199 throw new LuaException( lua, LuaElement.JAVA, "invalid replacement value (a "+Lua.type(val)+")" );
200 m.appendReplacement(sb,replacement);
201 }
202 i++;
203 }
204 m.appendTail(sb);
205 return new Object[]{ sb.toString(), new LuaNumber(i) };
206 }
207 throw new LuaException( lua, LuaElement.JAVA, "bad argument #3 to 'gsub' (string/function/table expected)" );
208 }
209
210 }