comparison core/src/luan/modules/StringLuan.java @ 195:24ede40ee0aa

make MetatableGetter DeepCloneable, scoped, and secure git-svn-id: https://luan-java.googlecode.com/svn/trunk@196 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 03 Jul 2014 08:19:48 +0000
parents 3dcb0f9bee82
children be0275bda373
comparison
equal deleted inserted replaced
194:08df375e2e5f 195:24ede40ee0aa
8 import luan.LuanFunction; 8 import luan.LuanFunction;
9 import luan.LuanJavaFunction; 9 import luan.LuanJavaFunction;
10 import luan.LuanElement; 10 import luan.LuanElement;
11 import luan.LuanException; 11 import luan.LuanException;
12 import luan.MetatableGetter; 12 import luan.MetatableGetter;
13 import luan.DeepCloner;
13 14
14 15
15 public final class StringLuan { 16 public final class StringLuan {
16 17
17 public static final LuanFunction LOADER = new LuanFunction() { 18 public static final LuanFunction LOADER = new LuanFunction() {
18 @Override public Object call(LuanState luan,Object[] args) { 19 @Override public Object call(LuanState luan,Object[] args) {
19 luan.addMetatableGetter(mg);
20 LuanTable module = new LuanTable(); 20 LuanTable module = new LuanTable();
21 module.metatableGetter = new MyMetatableGetter(module);
21 try { 22 try {
22 add( module, "to_binary", String.class ); 23 add( module, "to_binary", String.class );
23 add( module, "to_integers", String.class ); 24 add( module, "to_integers", String.class );
24 add( module, "from_integers", new int[0].getClass() ); 25 add( module, "from_integers", new int[0].getClass() );
25 add( module, "find", String.class, String.class, Integer.class, Boolean.class ); 26 add( module, "find", String.class, String.class, Integer.class, Boolean.class );
42 43
43 private static void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { 44 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 t.put( method, new LuanJavaFunction(StringLuan.class.getMethod(method,parameterTypes),null) );
45 } 46 }
46 47
47 private static final LuanTable mt = new LuanTable(); 48 public static class MyMetatableGetter implements MetatableGetter {
48 static { 49 private LuanTable module;
49 try { 50 private LuanTable metatable;
50 add( mt, "__index", LuanState.class, String.class, Object.class ); 51
51 } catch(NoSuchMethodException e) { 52 private MyMetatableGetter() {}
52 throw new RuntimeException(e); 53
53 } 54 MyMetatableGetter(LuanTable module) {
54 } 55 this.module = module;
55 56 this.metatable = table();
56 private static final MetatableGetter mg = new MetatableGetter() { 57 }
57 public LuanTable getMetatable(Object obj) { 58
58 return obj instanceof String ? mt : null; 59 @Override public LuanTable getMetatable(Object obj) {
59 } 60 return obj instanceof String ? metatable : null;
60 }; 61 }
61 62
62 public static Object __index(LuanState luan,final String s,Object key) throws LuanException { 63 public Object __index(LuanState luan,final String s,Object key) throws LuanException {
63 LuanTable mod = (LuanTable)luan.loaded().get("String"); 64 Object obj = module.get(key);
64 if( mod!=null ) {
65 Object obj = mod.get(key);
66 if( obj instanceof LuanFunction ) { 65 if( obj instanceof LuanFunction ) {
67 final LuanFunction fn = (LuanFunction)obj; 66 final LuanFunction fn = (LuanFunction)obj;
68 return new LuanFunction() { 67 return new LuanFunction() {
69 @Override public Object call(LuanState luan,Object[] args) throws LuanException { 68 @Override public Object call(LuanState luan,Object[] args) throws LuanException {
70 Object[] a = new Object[args.length+1]; 69 Object[] a = new Object[args.length+1];
72 System.arraycopy(args,0,a,1,args.length); 71 System.arraycopy(args,0,a,1,args.length);
73 return fn.call(luan,a); 72 return fn.call(luan,a);
74 } 73 }
75 }; 74 };
76 } 75 }
77 } 76 LuanTable mt = luan.getMetatable(s,this);
78 if( luan.loaded().get("Java") != null ) 77 if( mt == null )
79 return JavaLuan.__index(luan,s,key); 78 return null;
80 return null; 79 Object h = mt.get("__index");
80 if( !(h instanceof LuanFunction) )
81 return null;
82 LuanFunction fn = (LuanFunction)h;
83 return luan.call(fn,new Object[]{s,key});
84 }
85
86 LuanTable table() {
87 LuanTable tbl = new LuanTable();
88 try {
89 tbl.put( "__index", new LuanJavaFunction(
90 MyMetatableGetter.class.getMethod( "__index", LuanState.class, String.class, Object.class ), this
91 ) );
92 } catch(NoSuchMethodException e) {
93 throw new RuntimeException(e);
94 }
95 return tbl;
96 }
97
98 @Override public MetatableGetter shallowClone() {
99 return new MyMetatableGetter();
100 }
101
102 @Override public void deepenClone(MetatableGetter c,DeepCloner cloner) {
103 MyMetatableGetter clone = (MyMetatableGetter)c;
104 clone.module = cloner.deepClone(module);
105 clone.metatable = clone.table();
106 }
81 } 107 }
82 108
83 static int start(String s,int i) { 109 static int start(String s,int i) {
84 return i==0 ? 0 : i > 0 ? i - 1 : s.length() + i; 110 return i==0 ? 0 : i > 0 ? i - 1 : s.length() + i;
85 } 111 }