Mercurial Hosting > luan
comparison src/luan/modules/StringLib.java @ 167:4c0131c2b650
merge luan/lib into modules
git-svn-id: https://luan-java.googlecode.com/svn/trunk@168 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Sun, 22 Jun 2014 04:28:32 +0000 |
parents | src/luan/lib/StringLib.java@3c95a2291d64 |
children |
comparison
equal
deleted
inserted
replaced
166:4eaee12f6c65 | 167:4c0131c2b650 |
---|---|
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 StringLib { | |
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(StringLib.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 JavaLib.__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 } |