package org.idris.rts; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.EOFException; import java.io.PrintStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.StandardOpenOption; import java.nio.channels.Channels; import java.nio.channels.SeekableByteChannel; import java.nio.channels.ReadableByteChannel; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Semaphore; @SuppressWarnings("unchecked") public class ForeignPrimitives { private static final Map> args = new HashMap<>(); private static final Semaphore messageMutex = new Semaphore(1); private static final Map> messages = new HashMap<>(); private static final Set feofFiles = new HashSet<>(); public static synchronized void idris_initArgs(Thread t, String [] args) { ForeignPrimitives.args.put(t, Arrays.asList(args)); } public static synchronized int idris_numArgs(Object thread) { List argsForThread = ForeignPrimitives.args.get((Thread)thread); return (argsForThread == null ? 0 : argsForThread.size()); } public static synchronized String idris_getArg(Object thread, int num) { List argsForThread = ForeignPrimitives.args.get((Thread)thread); return (argsForThread == null ? null : argsForThread.get(num)); } public static String getenv(String x) { return System.getenv(x); } public static void exit(int exitCode) { System.exit(exitCode); } public static void usleep(int microsecs) { try { Thread.sleep(microsecs / 1000, microsecs % 1000); } catch (InterruptedException ex) { } } public static void idris_sendMessage(Object from, Object dest, Object message) throws InterruptedException { messageMutex.acquire(); BlockingQueue messagesForTarget = messages.get((Thread)dest); if (messagesForTarget == null) { messagesForTarget = new LinkedBlockingQueue<>(); messages.put((Thread)dest, messagesForTarget); } messagesForTarget.put(message); messageMutex.release(); } public static int idris_checkMessage(Object dest) throws InterruptedException { messageMutex.acquire(); BlockingQueue messagesForTarget = messages.get((Thread)dest); messageMutex.release(); return (messagesForTarget == null ? 0 : messagesForTarget.size()); } public static Object idris_recvMessage(Object dest) throws InterruptedException { messageMutex.acquire(); BlockingQueue messagesForTarget = messages.get((Thread)dest); if (messagesForTarget == null) { messagesForTarget = new LinkedBlockingQueue(); messages.put((Thread)dest, messagesForTarget); } messageMutex.release(); return messagesForTarget.take(); } public static void putStr(String str) { System.out.print(str); } public static void putchar(char c) { System.out.print(c); } public static int getchar() { try { return (char)System.in.read(); } catch (IOException ex) { return -1; } } public static SeekableByteChannel fileOpen(String name, String privs) { try { OpenOption [] options; switch (privs) { case "r" : options = new StandardOpenOption [] { StandardOpenOption.READ }; break; case "r+" : options = new StandardOpenOption [] { StandardOpenOption.READ, StandardOpenOption.WRITE }; break; case "w" : options = new StandardOpenOption [] { StandardOpenOption.WRITE, StandardOpenOption.CREATE }; break; case "w+" : options = new StandardOpenOption [] { StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE }; break; case "a" : options = new StandardOpenOption [] { StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND }; break; case "a+" : options = new StandardOpenOption [] { StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND }; break; default : options = new StandardOpenOption [] {}; break; } return Files.newByteChannel(new File(name).toPath(), options); } catch (IOException ex) { return null; } } public static synchronized void fileClose(Object file) throws IOException { ((Closeable)file).close(); feofFiles.remove(file); } public static void fputStr(Object file, String string) throws IOException { if (file instanceof PrintStream) { ((PrintStream)file).print(string); } else if (file instanceof SeekableByteChannel) { ((SeekableByteChannel)file).write(ByteBuffer.wrap(string.getBytes())); } } public static synchronized String idris_readStr(Object file) throws IOException { ReadableByteChannel channel = file instanceof InputStream ? Channels.newChannel((InputStream)file) : (ReadableByteChannel)file; ByteBuffer buf = ByteBuffer.allocate(1); StringBuilder resultBuilder = new StringBuilder(""); String delimiter = System.getProperty("line.separator"); int read = 0; do { buf.rewind(); read = channel.read(buf); if (read > 0) { resultBuilder.append(new String(buf.array())); if (resultBuilder.lastIndexOf(delimiter) > -1) { return resultBuilder.toString(); } } if (read < 0) { feofFiles.add(file); } } while (read >= 0); return resultBuilder.toString(); } public static int fileEOF(Object file) { return (feofFiles.contains(file) ? 1 : 0); } public static int isNull(Object o) { return (o == null ? 1 : 0); } }