changeset 758:c29d11d675fd

added Json.toString() and rpc now sends tables as json
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 19 Jul 2016 00:57:37 -0600
parents e1dfeddfbc7b
children ae612dfc57cb
files core/src/luan/modules/IoLuan.java core/src/luan/modules/RpcLuan.java core/src/luan/modules/parsers/Json.java
diffstat 3 files changed, 150 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/modules/IoLuan.java	Mon Jul 18 20:18:02 2016 -0600
+++ b/core/src/luan/modules/IoLuan.java	Tue Jul 19 00:57:37 2016 -0600
@@ -171,6 +171,21 @@
 	}
 
 
+	private static File objToFile(Object obj) {
+		if( obj instanceof String ) {
+			return new File((String)obj);
+		}
+		if( obj instanceof LuanTable ) {
+			LuanTable t = (LuanTable)obj;
+			Object java = t.rawGet("java");
+			if( java instanceof LuanFile ) {
+				LuanFile luanFile = (LuanFile)java;
+				return luanFile.file;
+			}
+		}
+		return null;
+	}
+
 
 	public static abstract class LuanIn {
 		public abstract InputStream inputStream() throws IOException, LuanException;
@@ -213,13 +228,16 @@
 			}
 		}
 
-		public void unzip(String path) throws IOException, LuanException {
+		public void unzip(Object path) throws IOException, LuanException {
+			File pathFile = objToFile(path);
+			if( pathFile==null )
+				throw new LuanException( "bad argument #1 to 'unzip' (string or file table expected)" );
 			ZipInputStream in = new ZipInputStream(new BufferedInputStream(inputStream()));
 			ZipEntry entry;
 			while( (entry = in.getNextEntry()) != null ) {
 				if( entry.isDirectory() )
 					continue;
-				File file = new File(path,entry.getName());
+				File file = new File(pathFile,entry.getName());
 				file.getParentFile().mkdirs();
 				OutputStream out = new FileOutputStream(file);
 				Utils.copyAll(in,out);
@@ -255,7 +273,7 @@
 					LuanIn.class.getMethod( "exists" ), this
 				) );
 				tbl.rawPut( "unzip", new LuanJavaFunction(
-					LuanIn.class.getMethod( "unzip", String.class ), this
+					LuanIn.class.getMethod( "unzip", Object.class ), this
 				) );
 			} catch(NoSuchMethodException e) {
 				throw new RuntimeException(e);
@@ -333,12 +351,15 @@
 			return binaryWriter(new BufferedOutputStream(outputStream()));
 		}
 
-		public void zip(LuanState luan,String basePath,LuanTable filePathList) throws LuanException, IOException {
+		public void zip(LuanState luan,Object basePathObj,LuanTable filePathList) throws LuanException, IOException {
+			File basePathFile = objToFile(basePathObj);
+			if( basePathFile==null )
+				throw new LuanException( "bad argument #1 to 'zip' (string or file table expected)" );
 			String[] filePaths;
 			if( filePathList==null ) {
-				File file = new File(basePath).getCanonicalFile();
+				File file = basePathFile.getCanonicalFile();
 				filePaths = new String[]{file.toString()};
-				basePath = file.getParent();
+				basePathFile = file.getParentFile();
 			} else {
 				List list = filePathList.asList();
 				filePaths = new String[list.size()];
@@ -349,8 +370,7 @@
 					filePaths[i] = (String)obj;
 				}
 			}
-			if( !basePath.endsWith("/") )
-				basePath += '/';
+			String basePath = basePathFile.toString() + '/';
 			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(outputStream()));
 			zip(out,basePath,filePaths);
 			out.close();
@@ -393,7 +413,7 @@
 					LuanIO.class.getMethod( "binary_writer" ), this
 				) );
 				tbl.rawPut( "zip", new LuanJavaFunction(
-					LuanIO.class.getMethod( "zip", LuanState.class, String.class, LuanTable.class ), this
+					LuanIO.class.getMethod( "zip", LuanState.class, Object.class, LuanTable.class ), this
 				) );
 			} catch(NoSuchMethodException e) {
 				throw new RuntimeException(e);
@@ -537,8 +557,12 @@
 			return file.exists();
 		}
 
-		public boolean rename_to(String dest) {
-			return file.renameTo(new File(dest));
+		public void rename_to(Object destObj) throws LuanException {
+			File dest = objToFile(destObj);
+			if( dest==null )
+				throw new LuanException( "bad argument #1 to 'objToFile' (string or file table expected)" );
+			if( !file.renameTo(dest) )
+				throw new LuanException("couldn't rename file "+file+" to "+dest);
 		}
 
 		public LuanTable canonical(LuanState luan) throws LuanException, IOException {
@@ -605,7 +629,7 @@
 					LuanFile.class.getMethod( "parent", LuanState.class ), this
 				) );
 				tbl.rawPut( "rename_to", new LuanJavaFunction(
-					LuanFile.class.getMethod( "rename_to", String.class ), this
+					LuanFile.class.getMethod( "rename_to", Object.class ), this
 				) );
 				tbl.rawPut( "canonical", new LuanJavaFunction(
 					LuanFile.class.getMethod( "canonical", LuanState.class ), this
--- a/core/src/luan/modules/RpcLuan.java	Mon Jul 18 20:18:02 2016 -0600
+++ b/core/src/luan/modules/RpcLuan.java	Tue Jul 19 00:57:37 2016 -0600
@@ -20,6 +20,8 @@
 import luan.LuanFunction;
 import luan.LuanException;
 import luan.LuanMethod;
+import luan.modules.parsers.Json;
+import luan.modules.parsers.ParseException;
 
 
 public final class RpcLuan {
@@ -144,7 +146,8 @@
 		}
 		else if( obj instanceof LuanTable ) {
 			out.write(TABLE);
-			String s = pickle( luan, obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
+//			String s = pickle( luan, obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
+			String s = Json.toString(obj);
 			writeString(out,s);
 		}
 		else
@@ -166,8 +169,15 @@
 			return readBinary(in,readInt(in));
 		case TABLE:
 			String s = readString(in);
+/*
 			LuanFunction fn = Luan.load("return "+s,"rpc-reader");
 			return fn.call(luan);
+*/
+			try {
+				return Json.parse(s);
+			} catch(ParseException e) {
+				throw new LuanException(e);
+			}
 		case IO:
 			return new LuanInputStream(in,close).table();
 		default:
@@ -224,7 +234,7 @@
         out.write((v >>>  0) & 0xFF);
 	}
 
-
+/*
 	private static String pickle(LuanState luan,Object obj,Set<LuanTable> set) throws LuanException {
 		if( obj == null )
 			return "nil";
@@ -253,7 +263,7 @@
 		}
 		throw new LuanException( "invalid type: " + obj.getClass() );
 	}
-
+*/
 
 	private static class Close {
 		boolean b = true;
--- a/core/src/luan/modules/parsers/Json.java	Mon Jul 18 20:18:02 2016 -0600
+++ b/core/src/luan/modules/parsers/Json.java	Tue Jul 19 00:57:37 2016 -0600
@@ -4,7 +4,9 @@
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.LinkedHashMap;
+import java.util.Iterator;
 import luan.LuanTable;
+import luan.LuanException;
 
 
 public final class Json {
@@ -201,4 +203,103 @@
 	private void spaces() {
 		while( parser.anyOf(" \t\r\n") );
 	}
+
+
+
+
+
+
+
+
+
+	public static String toString(Object obj) throws LuanException {
+		StringBuilder sb = new StringBuilder();
+		toString(obj,sb);
+		return sb.toString();
+	}
+
+	private static void toString(Object obj,StringBuilder sb) throws LuanException {
+		if( obj == null || obj instanceof Boolean || obj instanceof Number ) {
+			sb.append(obj);
+			return;
+		}
+		if( obj instanceof String ) {
+			toString((String)obj,sb);
+			return;
+		}
+		if( obj instanceof LuanTable ) {
+			toString((LuanTable)obj,sb);
+			return;
+		}
+		throw new LuanException("can't handle type "+obj.getClass().getName());
+	}
+
+	private static void toString(final String s,StringBuilder sb) {
+		sb.append('"');
+		for( int i=0; i<s.length(); i++ ) {
+			char c = s.charAt(i);
+			switch(c) {
+			case '"':
+				sb.append("\\\"");
+				break;
+			case '\\':
+				sb.append("\\\\");
+				break;
+			case '\b':
+				sb.append("\\b");
+				break;
+			case '\f':
+				sb.append("\\f");
+				break;
+			case '\n':
+				sb.append("\\n");
+				break;
+			case '\r':
+				sb.append("\\r");
+				break;
+			case '\t':
+				sb.append("\\t");
+				break;
+			default:
+				sb.append(c);
+			}
+		}
+		sb.append('"');
+	}
+
+	private static void toString(LuanTable t,StringBuilder sb) throws LuanException {
+		if( t.isList() ) {
+			final List list = t.asList();
+			if( list.isEmpty() ) {
+				sb.append("{}");
+				return;
+			}
+			sb.append('[');
+			toString(list.get(0),sb);
+			for( int i=1; i<list.size(); i++ ) {
+				sb.append(',');
+				toString(list.get(i),sb);
+			}
+			sb.append(']');
+			return;
+		}
+		sb.append('{');
+		Iterator<Map.Entry<Object,Object>> i = t.rawIterator();
+		toString(i.next(),sb);
+		while( i.hasNext() ) {
+			sb.append(',');
+			toString(i.next(),sb);
+		}
+		sb.append('}');
+	}
+
+	private static void toString(Map.Entry<Object,Object> entry,StringBuilder sb) throws LuanException {
+		Object key = entry.getKey();
+		if( !(key instanceof String) )
+			throw new LuanException("table keys must be strings");
+		toString((String)key,sb);
+		sb.append(':');
+		toString(entry.getValue(),sb);
+	}
+
 }