Mercurial Hosting > luan
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 } |