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