changeset 413:8937263f59f6

add __pairs; add back HttpServicer.get_parameter_values;
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 29 Apr 2015 19:01:18 -0600
parents 094f37c5e6f9
children d2ab2240cc65
files core/src/luan/LuanMeta.java core/src/luan/LuanPropertyMeta.java core/src/luan/modules/BasicLuan.java lucene/src/luan/modules/lucene/FieldTable.java web/src/luan/modules/web/HttpServicer.java
diffstat 5 files changed, 107 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/LuanMeta.java	Wed Apr 29 16:28:18 2015 -0600
+++ b/core/src/luan/LuanMeta.java	Wed Apr 29 19:01:18 2015 -0600
@@ -1,13 +1,41 @@
 package luan;
 
 import java.util.Map;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashSet;
 
 
-public abstract class LuanMeta /*implements Iterable<Map.Entry<Object,Object>>*/ {
+public abstract class LuanMeta {
 
 	public abstract Object __index(LuanState luan,LuanTable tbl,Object key) throws LuanException;
 
-//	public abstract LuanFunction __pairs(LuanState luan,LuanTable tbl) throws LuanException;
+	protected abstract Iterator keys();
+
+	public LuanFunction __pairs(final LuanState luan,final LuanTable tbl) {
+		return new LuanFunction() {
+			final Iterator<Map.Entry<Object,Object>> iter1 = tbl.iterator();
+			final Iterator<Object> iter2 = keys();
+			final Set<Object> set = new HashSet<Object>();
+
+			@Override public Object[] call(LuanState luan,Object[] args) throws LuanException {
+				if( iter1.hasNext() ) {
+					Map.Entry<Object,Object> entry = iter1.next();
+					Object key = entry.getKey();
+					set.add(key);
+					return new Object[]{key,entry.getValue()};
+				}
+				while( iter2.hasNext() ) {
+					Object key = iter2.next();
+					if( set.add(key) ) {
+						Object value = __index(luan,tbl,key);
+						return new Object[]{key,value};
+					}
+				}
+				return LuanFunction.NOTHING;
+			}
+		};
+	}
 
 	public boolean canNewindex() {
 		return false;
@@ -19,22 +47,8 @@
 
 	public LuanTable newMetatable() {
 		LuanTable mt = new LuanTable();
-/*
-		try {
-			mt.put( "__index", new LuanJavaFunction(
-				LuanMeta.class.getMethod( "__index", LuanState.class, LuanTable.class, Object.class ), this
-			) );
-			if( canNewindex() ) {
-				mt.put( "__newindex", new LuanJavaFunction(
-					LuanMeta.class.getMethod( "__newindex", LuanState.class, LuanTable.class, Object.class, Object.class ), mt
-				) );
-			}
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
-		}
-*/
 		mt.put( "__index", this );
-//		mt.put( "__pairs", this );
+		mt.put( "__pairs", this );
 		if( canNewindex() )
 			mt.put( "__newindex", this );
 		return mt;
--- a/core/src/luan/LuanPropertyMeta.java	Wed Apr 29 16:28:18 2015 -0600
+++ b/core/src/luan/LuanPropertyMeta.java	Wed Apr 29 19:01:18 2015 -0600
@@ -1,7 +1,10 @@
 package luan;
 
+import java.util.Map;
+import java.util.Iterator;
 
-public class LuanPropertyMeta extends LuanMeta implements DeepCloneable<LuanPropertyMeta> {
+
+public final class LuanPropertyMeta extends LuanMeta implements DeepCloneable<LuanPropertyMeta> {
 	private LuanTable getters;
 	private LuanTable setters;
 
@@ -41,6 +44,23 @@
 		return luan.call(fn);
 	}
 
+	@Override protected Iterator keys() {
+		return new Iterator() {
+			final Iterator<Map.Entry<Object,Object>> iter = getters.iterator();
+
+			@Override public boolean hasNext() {
+				return iter.hasNext();
+			}
+			@Override public Object next() {
+				return iter.next().getKey();
+			}
+			@Override public void remove() {
+				throw new UnsupportedOperationException();
+			}
+		};
+	}
+
+
 	@Override public boolean canNewindex() {
 		return true;
 	}
--- a/core/src/luan/modules/BasicLuan.java	Wed Apr 29 16:28:18 2015 -0600
+++ b/core/src/luan/modules/BasicLuan.java	Wed Apr 29 19:01:18 2015 -0600
@@ -16,6 +16,7 @@
 import luan.LuanSource;
 import luan.LuanElement;
 import luan.LuanMethod;
+import luan.LuanMeta;
 import luan.impl.LuanCompiler;
 
 
@@ -49,8 +50,22 @@
 
 	public static LuanFunction pairs(LuanState luan,final LuanTable t) throws LuanException {
 		Utils.checkNotNull(luan,t);
+		Object obj = luan.getHandler("__pairs",t);
+		if( obj != null ) {
+			if( obj instanceof LuanFunction ) {
+				obj = Luan.first(luan.call((LuanFunction)obj,"__pairs",new Object[]{t}));
+				if( !(obj instanceof LuanFunction) )
+					throw luan.exception( "metamethod __pairs should return function but returned " + Luan.type(obj) );
+				return (LuanFunction)obj;
+			}
+			if( obj instanceof LuanMeta ) {
+				LuanMeta meta = (LuanMeta)obj;
+				return meta.__pairs(luan,t);
+			}
+			throw luan.exception( "invalid type of metamethod __pairs: " + Luan.type(obj) );
+		}
 		return new LuanFunction() {
-			Iterator<Map.Entry<Object,Object>> iter = t.iterator();
+			final Iterator<Map.Entry<Object,Object>> iter = t.iterator();
 
 			@Override public Object[] call(LuanState luan,Object[] args) {
 				if( !iter.hasNext() )
--- a/lucene/src/luan/modules/lucene/FieldTable.java	Wed Apr 29 16:28:18 2015 -0600
+++ b/lucene/src/luan/modules/lucene/FieldTable.java	Wed Apr 29 19:01:18 2015 -0600
@@ -52,11 +52,11 @@
 //	@Override public final Object get(Object key) {
 		return map.get(key);
 	}
+
+	@Override public final Iterator keys() {
+		return map.keySet().iterator();
+	}
 /*
-	@Override public final Iterator<Map.Entry<Object,Object>> iterator() {
-		return new HashMap<Object,Object>(map).entrySet().iterator();
-	}
-
 	@Override protected String type() {
 		return "lucene-field-table";
 	}
--- a/web/src/luan/modules/web/HttpServicer.java	Wed Apr 29 16:28:18 2015 -0600
+++ b/web/src/luan/modules/web/HttpServicer.java	Wed Apr 29 19:01:18 2015 -0600
@@ -5,6 +5,7 @@
 import java.io.PrintWriter;
 import java.io.IOException;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.AbstractMap;
 import java.util.Set;
 import java.util.List;
@@ -124,12 +125,11 @@
 		LuanTable parameters = new NameMeta() {
 
 			@Override Object get(String name) {
-				String[] a = request.getParameterValues(name);
-				return a==null ? null : a.length==1 ? a[0] : a;
+				return request.getParameter(name);
 			}
 
-			@Override Iterator<String> names() {
-				return new EnumerationIterator<String>(request.getParameterNames());
+			@Override protected Iterator keys() {
+				return new EnumerationIterator(request.getParameterNames());
 			}
 /*
 			@Override protected String type() {
@@ -138,14 +138,15 @@
 */
 		}.newTable();
 		tbl.put( "parameters", parameters );
+		add( tbl, "get_parameter_values", String.class );
 		LuanTable headers = new NameMeta() {
 
 			@Override Object get(String name) {
 				return request.getHeader(name);
 			}
 
-			@Override Iterator<String> names() {
-				return new EnumerationIterator<String>(request.getHeaderNames());
+			@Override protected Iterator keys() {
+				return new EnumerationIterator(request.getHeaderNames());
 			}
 /*
 			@Override protected String type() {
@@ -180,27 +181,24 @@
 				String name = (String)key;
 				return getCookieValue(request,name);
 			}
-/*
-			@Override public final Iterator<Map.Entry<Object,Object>> iterator() {
-				return new Iterator<Map.Entry<Object,Object>>() {
+
+			@Override protected Iterator<Object> keys() {
+				return new Iterator<Object>() {
 					final Cookie[] cookies = request.getCookies();
 					int i = 0;
 	
 					@Override public boolean hasNext() {
 						return i < cookies.length;
 					}
-					@Override public Map.Entry<Object,Object> next() {
-						Cookie cookie = cookies[i++];
-						String name = cookie.getName();
-						Object val = unescape(cookie.getValue());
-						return new AbstractMap.SimpleEntry<Object,Object>(name,val);
+					@Override public Object next() {
+						return cookies[i++].getName();
 					}
 					@Override public void remove() {
 						throw new UnsupportedOperationException();
 					}
 				};
 			}
-
+/*
 			@Override protected String type() {
 				return "request.cookies-table";
 			}
@@ -215,6 +213,7 @@
 				final MultiPartInputStream mpis = new MultiPartInputStream(in,contentType,null,null);
 				mpis.setDeleteOnExit(true);
 				parameters = new LuanTable();
+				final Map map = new HashMap();
 				for( Part p : mpis.getParts() ) {
 					final MultiPartInputStream.MultiPart part = (MultiPartInputStream.MultiPart)p;
 					String name = part.getName();
@@ -241,20 +240,26 @@
 						} );
 						value = partTbl;
 					}
-					Object old = parameters.get(name);
+					parameters.put(name,value);
+					Object old = map.get(name);
 					if( old == null ) {
-						parameters.put(name,value);
+						map.put(name,value);
 					} else if( old instanceof Object[] ) {
 						Object[] aOld = (Object[])old;
 						Object[] aNew = new Object[aOld.length+1];
 						System.arraycopy(aOld,0,aNew,0,aOld.length);
 						aNew[aOld.length] = value;
-						parameters.put(name,aNew);
+						map.put(name,aNew);
 					} else {
-						parameters.put(name,new Object[]{old,value});
+						map.put(name,new Object[]{old,value});
 					}
 				}
 				tbl.put( "parameters", parameters );
+				tbl.put( "get_parameter_values", new LuanFunction() {
+					@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+						return args.length==0 ? null : map.get(args[0]);
+					}
+				} );
 			} catch(IOException e) {
 				throw new RuntimeException(e);
 			} catch(ServletException e) {
@@ -277,7 +282,7 @@
 				return response.getHeader(name);
 			}
 
-			@Override Iterator<String> names() {
+			@Override protected Iterator keys() {
 				return response.getHeaderNames().iterator();
 			}
 
@@ -339,8 +344,8 @@
 				return request.getSession().getAttribute(name);
 			}
 
-			@Override Iterator<String> names() {
-				return new EnumerationIterator<String>(request.getSession().getAttributeNames());
+			@Override protected Iterator keys() {
+				return new EnumerationIterator(request.getSession().getAttributeNames());
 			}
 
 			@Override public boolean canNewindex() {
@@ -379,6 +384,10 @@
 		return IoLuan.textWriter(response.getWriter());
 	}
 
+	public Object[] get_parameter_values(String name) {
+		return request.getParameterValues(name);
+	}
+
 	public void send_redirect(String redirectUrl)
 		throws IOException
 	{
@@ -515,10 +524,10 @@
 
 	// util classes
 
-	static final class EnumerationIterator<E> implements Iterator<E> {
-		private final Enumeration<E> en;
+	static final class EnumerationIterator implements Iterator {
+		private final Enumeration en;
 
-		EnumerationIterator(Enumeration<E> en) {
+		EnumerationIterator(Enumeration en) {
 			this.en = en;
 		}
 
@@ -526,7 +535,7 @@
 			return en.hasMoreElements();
 		}
 
-		@Override public E next() {
+		@Override public Object next() {
 			return en.nextElement();
 		}
 
@@ -537,7 +546,6 @@
 
 	private static abstract class NameMeta extends LuanMeta {
 		abstract Object get(String name);
-		abstract Iterator<String> names();
 
 		@Override public Object __index(LuanState luan,LuanTable tbl,Object key) {
 			if( !(key instanceof String) )
@@ -545,25 +553,7 @@
 			String name = (String)key;
 			return get(name);
 		}
-/*
-		@Override public final Iterator<Map.Entry<Object,Object>> iterator() {
-			return new Iterator<Map.Entry<Object,Object>>() {
-				Iterator<String> names = names();
 
-				@Override public boolean hasNext() {
-					return names.hasNext();
-				}
-				@Override public Map.Entry<Object,Object> next() {
-					String name = names.next();
-					Object val = get(name);
-					return new AbstractMap.SimpleEntry<Object,Object>(name,val);
-				}
-				@Override public void remove() {
-					throw new UnsupportedOperationException();
-				}
-			};
-		}
-*/
 	};
 
 	private static String string(Object value) {