comparison core/src/luan/modules/StringLuan.java @ 171:3dcb0f9bee82

add core component git-svn-id: https://luan-java.googlecode.com/svn/trunk@172 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Sun, 22 Jun 2014 05:41:22 +0000
parents src/luan/modules/StringLuan.java@ebe9db183eb7
children 24ede40ee0aa
comparison
equal deleted inserted replaced
170:7c792a328a83 171:3dcb0f9bee82
1 package luan.modules;
2
3 import java.util.regex.Pattern;
4 import java.util.regex.Matcher;
5 import luan.Luan;
6 import luan.LuanState;
7 import luan.LuanTable;
8 import luan.LuanFunction;
9 import luan.LuanJavaFunction;
10 import luan.LuanElement;
11 import luan.LuanException;
12 import luan.MetatableGetter;
13
14
15 public final class StringLuan {
16
17 public static final LuanFunction LOADER = new LuanFunction() {
18 @Override public Object call(LuanState luan,Object[] args) {
19 luan.addMetatableGetter(mg);
20 LuanTable module = new LuanTable();
21 try {
22 add( module, "to_binary", String.class );
23 add( module, "to_integers", String.class );
24 add( module, "from_integers", new int[0].getClass() );
25 add( module, "find", String.class, String.class, Integer.class, Boolean.class );
26 add( module, "format", String.class, new Object[0].getClass() );
27 add( module, "gmatch", String.class, String.class );
28 add( module, "gsub", LuanState.class, String.class, String.class, Object.class, Integer.class );
29 add( module, "len", String.class );
30 add( module, "lower", String.class );
31 add( module, "match", String.class, String.class, Integer.class );
32 add( module, "rep", String.class, Integer.TYPE, String.class );
33 add( module, "reverse", String.class );
34 add( module, "sub", String.class, Integer.TYPE, Integer.class );
35 add( module, "upper", String.class );
36 } catch(NoSuchMethodException e) {
37 throw new RuntimeException(e);
38 }
39 return module;
40 }
41 };
42
43 private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
44 t.put( method, new LuanJavaFunction(StringLuan.class.getMethod(method,parameterTypes),null) );
45 }
46
47 private static final LuanTable mt = new LuanTable();
48 static {
49 try {
50 add( mt, "__index", LuanState.class, String.class, Object.class );
51 } catch(NoSuchMethodException e) {
52 throw new RuntimeException(e);
53 }
54 }
55
56 private static final MetatableGetter mg = new MetatableGetter() {
57 public LuanTable getMetatable(Object obj) {
58 return obj instanceof String ? mt : null;
59 }
60 };
61
62 public static Object __index(LuanState luan,final String s,Object key) throws LuanException {
63 LuanTable mod = (LuanTable)luan.loaded().get("String");
64 if( mod!=null ) {
65 Object obj = mod.get(key);
66 if( obj instanceof LuanFunction ) {
67 final LuanFunction fn = (LuanFunction)obj;
68 return new LuanFunction() {
69 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
70 Object[] a = new Object[args.length+1];
71 a[0] = s;
72 System.arraycopy(args,0,a,1,args.length);
73 return fn.call(luan,a);
74 }
75 };
76 }
77 }
78 if( luan.loaded().get("Java") != null )
79 return JavaLuan.__index(luan,s,key);
80 return null;
81 }
82
83 static int start(String s,int i) {
84 return i==0 ? 0 : i > 0 ? i - 1 : s.length() + i;
85 }
86
87 static int start(String s,Integer i,int dflt) {
88 return i==null ? dflt : start(s,i);
89 }
90
91 static int end(String s,int i) {
92 return i==0 ? 0 : i > 0 ? i : s.length() + i + 1;
93 }
94
95 static int end(String s,Integer i,int dflt) {
96 return i==null ? dflt : end(s,i);
97 }
98
99 public static byte[] to_binary(String s) {
100 return s.getBytes();
101 }
102
103 public static int[] to_integers(String s) {
104 char[] a = s.toCharArray();
105 int[] chars = new int[a.length];
106 for( int i=0; i<a.length; i++ ) {
107 chars[i] = a[i];
108 }
109 return chars;
110 }
111
112 public static String from_integers(int... chars) {
113 char[] a = new char[chars.length];
114 for( int i=0; i<chars.length; i++ ) {
115 a[i] = (char)chars[i];
116 }
117 return new String(a);
118 }
119
120 public static int len(String s) {
121 return s.length();
122 }
123
124 public static String lower(String s) {
125 return s.toLowerCase();
126 }
127
128 public static String upper(String s) {
129 return s.toUpperCase();
130 }
131
132 public static String reverse(String s) {
133 return new StringBuilder(s).reverse().toString();
134 }
135
136 public static String rep(String s,int n,String sep) {
137 if( n < 1 )
138 return "";
139 StringBuilder buf = new StringBuilder(s);
140 while( --n > 0 ) {
141 if( sep != null )
142 buf.append(sep);
143 buf.append(s);
144 }
145 return buf.toString();
146 }
147
148 public static String sub(String s,int i,Integer j) {
149 int start = start(s,i);
150 int end = end(s,j,s.length());
151 return s.substring(start,end);
152 }
153
154 public static int[] find(String s,String pattern,Integer init,Boolean plain) {
155 int start = start(s,init,0);
156 if( Boolean.TRUE.equals(plain) ) {
157 int i = s.indexOf(pattern,start);
158 return i == -1 ? null : new int[]{i+1,i+pattern.length()};
159 }
160 Matcher m = Pattern.compile(pattern).matcher(s);
161 return m.find(start) ? new int[]{m.start()+1,m.end()} : null;
162 }
163
164 public static String[] match(String s,String pattern,Integer init) {
165 int start = start(s,init,0);
166 Matcher m = Pattern.compile(pattern).matcher(s);
167 if( !m.find(start) )
168 return null;
169 final int n = m.groupCount();
170 if( n == 0 )
171 return new String[]{m.group()};
172 String[] rtn = new String[n];
173 for( int i=0; i<n; i++ ) {
174 rtn[i] = m.group(i+1);
175 }
176 return rtn;
177 }
178
179 public static LuanFunction gmatch(String s,String pattern) {
180 final Matcher m = Pattern.compile(pattern).matcher(s);
181 return new LuanFunction() {
182 @Override public Object call(LuanState luan,Object[] args) {
183 if( !m.find() )
184 return null;
185 final int n = m.groupCount();
186 if( n == 0 )
187 return m.group();
188 String[] rtn = new String[n];
189 for( int i=0; i<n; i++ ) {
190 rtn[i] = m.group(i+1);
191 }
192 return rtn;
193 }
194 };
195 }
196
197 public static Object[] gsub(LuanState luan,String s,String pattern,Object repl,Integer n) throws LuanException {
198 int max = n==null ? Integer.MAX_VALUE : n;
199 final Matcher m = Pattern.compile(pattern).matcher(s);
200 if( repl instanceof String ) {
201 String replacement = (String)repl;
202 int i = 0;
203 StringBuffer sb = new StringBuffer();
204 while( i<max && m.find() ) {
205 m.appendReplacement(sb,replacement);
206 i++;
207 }
208 m.appendTail(sb);
209 return new Object[]{ sb.toString(), i };
210 }
211 if( repl instanceof LuanTable ) {
212 LuanTable t = (LuanTable)repl;
213 int i = 0;
214 StringBuffer sb = new StringBuffer();
215 while( i<max && m.find() ) {
216 String match = m.groupCount()==0 ? m.group() : m.group(1);
217 Object val = t.get(match);
218 if( Luan.toBoolean(val) ) {
219 String replacement = Luan.asString(val);
220 if( replacement==null )
221 throw luan.exception( "invalid replacement value (a "+Luan.type(val)+")" );
222 m.appendReplacement(sb,replacement);
223 }
224 i++;
225 }
226 m.appendTail(sb);
227 return new Object[]{ sb.toString(), i };
228 }
229 if( repl instanceof LuanFunction ) {
230 LuanFunction fn = (LuanFunction)repl;
231 int i = 0;
232 StringBuffer sb = new StringBuffer();
233 while( i<max && m.find() ) {
234 Object[] args;
235 final int count = m.groupCount();
236 if( count == 0 ) {
237 args = new Object[]{m.group()};
238 } else {
239 args = new Object[count];
240 for( int j=0; j<count; j++ ) {
241 args[j] = m.group(j);
242 }
243 }
244 Object val = Luan.first( luan.call(fn,"repl-arg",args) );
245 if( Luan.toBoolean(val) ) {
246 String replacement = Luan.asString(val);
247 if( replacement==null )
248 throw luan.exception( "invalid replacement value (a "+Luan.type(val)+")" );
249 m.appendReplacement(sb,replacement);
250 }
251 i++;
252 }
253 m.appendTail(sb);
254 return new Object[]{ sb.toString(), i };
255 }
256 throw luan.exception( "bad argument #3 to 'gsub' (string/function/table expected)" );
257 }
258
259 // note - String.format() is too stupid to convert between ints and floats.
260 public static String format(String format,Object... args) {
261 return String.format(format,args);
262 }
263
264 }