mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-08 15:12:40 +01:00
DroidFish: Rewrote the cuckoochess communication so that internet permission is no longer needed.
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<supports-screens android:largeScreens="true"
|
<supports-screens android:largeScreens="true"
|
||||||
android:anyDensity="true" />
|
android:anyDensity="true" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<application android:icon="@drawable/icon"
|
<application android:icon="@drawable/icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:debuggable="false">
|
android:debuggable="false">
|
||||||
@@ -45,9 +47,6 @@
|
|||||||
android:label="@string/cpu_warning_title">
|
android:label="@string/cpu_warning_title">
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
<uses-sdk android:minSdkVersion="3"
|
<uses-sdk android:minSdkVersion="3"
|
||||||
android:targetSdkVersion="10"/>
|
android:targetSdkVersion="10"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -803,7 +803,7 @@ public class DroidComputerPlayer {
|
|||||||
|
|
||||||
private final synchronized int getReadTimeout() {
|
private final synchronized int getReadTimeout() {
|
||||||
boolean needGuiUpdate = depthModified || currMoveModified || pvModified || statsModified;
|
boolean needGuiUpdate = depthModified || currMoveModified || pvModified || statsModified;
|
||||||
int timeout = 1000;
|
int timeout = 2000000000;
|
||||||
if (needGuiUpdate) {
|
if (needGuiUpdate) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
timeout = (int)(lastGUIUpdate + guiUpdateInterval - now + 1);
|
timeout = (int)(lastGUIUpdate + guiUpdateInterval - now + 1);
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.petero.droidfish.R;
|
import org.petero.droidfish.R;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -45,7 +43,7 @@ public class ExternalEngine extends UCIEngineBase {
|
|||||||
private Thread exitThread;
|
private Thread exitThread;
|
||||||
private Thread stdInThread;
|
private Thread stdInThread;
|
||||||
private Thread stdErrThread;
|
private Thread stdErrThread;
|
||||||
private List<String> inLines;
|
private LocalPipe inLines;
|
||||||
private boolean startedOk;
|
private boolean startedOk;
|
||||||
private boolean isRunning;
|
private boolean isRunning;
|
||||||
|
|
||||||
@@ -58,7 +56,7 @@ public class ExternalEngine extends UCIEngineBase {
|
|||||||
exitThread = null;
|
exitThread = null;
|
||||||
stdInThread = null;
|
stdInThread = null;
|
||||||
stdErrThread = null;
|
stdErrThread = null;
|
||||||
inLines = new LinkedList<String>();
|
inLines = new LocalPipe();
|
||||||
startedOk = false;
|
startedOk = false;
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
}
|
}
|
||||||
@@ -120,8 +118,7 @@ public class ExternalEngine extends UCIEngineBase {
|
|||||||
if ((ep == null) || Thread.currentThread().isInterrupted())
|
if ((ep == null) || Thread.currentThread().isInterrupted())
|
||||||
return;
|
return;
|
||||||
synchronized (inLines) {
|
synchronized (inLines) {
|
||||||
inLines.add(line);
|
inLines.addLine(line);
|
||||||
inLines.notify();
|
|
||||||
if (first) {
|
if (first) {
|
||||||
startedOk = true;
|
startedOk = true;
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
@@ -130,8 +127,8 @@ public class ExternalEngine extends UCIEngineBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
inLines.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
stdInThread.start();
|
stdInThread.start();
|
||||||
@@ -176,26 +173,13 @@ public class ExternalEngine extends UCIEngineBase {
|
|||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
@Override
|
@Override
|
||||||
public String readLineFromEngine(int timeoutMillis) {
|
public String readLineFromEngine(int timeoutMillis) {
|
||||||
try {
|
String ret = inLines.readLine(timeoutMillis);
|
||||||
synchronized (inLines) {
|
if (ret == null)
|
||||||
if (inLines.size() == 0) {
|
return null;
|
||||||
Thread inThread = stdInThread;
|
if (ret.length() > 0) {
|
||||||
if ((inThread == null) || !inThread.isAlive())
|
// System.out.printf("Engine -> GUI: %s\n", ret);
|
||||||
return null;
|
|
||||||
inLines.wait(timeoutMillis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
synchronized (inLines) {
|
|
||||||
if (inLines.size() > 0) {
|
|
||||||
String ret = inLines.get(0);
|
|
||||||
inLines.remove(0);
|
|
||||||
// System.out.printf("Engine -> GUI: %s\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
}
|
||||||
return "";
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|||||||
63
DroidFish/src/org/petero/droidfish/engine/LocalPipe.java
Normal file
63
DroidFish/src/org/petero/droidfish/engine/LocalPipe.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package org.petero.droidfish.engine;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
/** Implements line-based text communication between threads. */
|
||||||
|
public class LocalPipe {
|
||||||
|
private LinkedList<String> lines = new LinkedList<String>();
|
||||||
|
private boolean closed = false;
|
||||||
|
|
||||||
|
/** Write a line to the pipe. */
|
||||||
|
public final synchronized void printLine(String format) {
|
||||||
|
String s = String.format(format, new Object[]{});
|
||||||
|
addLine(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Write a line to the pipe. */
|
||||||
|
public final synchronized void printLine(String format, Object ... args) {
|
||||||
|
String s = String.format(format, args);
|
||||||
|
addLine(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final synchronized void addLine(String line) {
|
||||||
|
lines.add(line);
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read a line from the pipe. Returns null on failure. */
|
||||||
|
public final synchronized String readLine() {
|
||||||
|
return readLine(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read a line from the pipe. Returns null on failure. Returns empty string on timeout. */
|
||||||
|
public final synchronized String readLine(int timeoutMillis) {
|
||||||
|
if (closed)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
if (lines.isEmpty()) {
|
||||||
|
if (timeoutMillis > 0)
|
||||||
|
wait(timeoutMillis);
|
||||||
|
else
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
if (lines.isEmpty())
|
||||||
|
return closed ? null : "";
|
||||||
|
String ret = lines.get(0);
|
||||||
|
lines.remove(0);
|
||||||
|
return ret;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close pipe. Makes readLine() return null. */
|
||||||
|
public final synchronized void close() {
|
||||||
|
closed = true;
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return true if writer side has closed the pipe. */
|
||||||
|
public final synchronized boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,11 +23,9 @@ import chess.ComputerPlayer;
|
|||||||
import chess.Move;
|
import chess.Move;
|
||||||
import chess.Position;
|
import chess.Position;
|
||||||
import chess.TextIO;
|
import chess.TextIO;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.channels.Pipe;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.petero.droidfish.engine.LocalPipe;
|
||||||
import org.petero.droidfish.engine.UCIEngineBase;
|
import org.petero.droidfish.engine.UCIEngineBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,22 +44,16 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
// Set to true to break out of main loop
|
// Set to true to break out of main loop
|
||||||
private boolean quit;
|
private boolean quit;
|
||||||
|
|
||||||
private Pipe guiToEngine;
|
private LocalPipe guiToEngine;
|
||||||
private Pipe engineToGui;
|
private LocalPipe engineToGui;
|
||||||
private NioInputStream inFromEngine;
|
|
||||||
private Thread engineThread;
|
private Thread engineThread;
|
||||||
|
|
||||||
public CuckooChessEngine(Report report) {
|
public CuckooChessEngine(Report report) {
|
||||||
pos = null;
|
pos = null;
|
||||||
moves = new ArrayList<Move>();
|
moves = new ArrayList<Move>();
|
||||||
quit = false;
|
quit = false;
|
||||||
try {
|
guiToEngine = new LocalPipe();
|
||||||
guiToEngine = Pipe.open();
|
engineToGui = new LocalPipe();
|
||||||
engineToGui = Pipe.open();
|
|
||||||
inFromEngine = new NioInputStream(engineToGui);
|
|
||||||
} catch (IOException e) {
|
|
||||||
report.reportError(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
@@ -69,9 +61,7 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
protected final void startProcess() {
|
protected final void startProcess() {
|
||||||
engineThread = new Thread(new Runnable() {
|
engineThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
NioInputStream in = new NioInputStream(guiToEngine);
|
mainLoop(guiToEngine, engineToGui);
|
||||||
NioPrintStream out = new NioPrintStream(engineToGui);
|
|
||||||
mainLoop(in, out);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
int pMin = Thread.MIN_PRIORITY;
|
int pMin = Thread.MIN_PRIORITY;
|
||||||
@@ -93,7 +83,7 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
setOption("strength", strength);
|
setOption("strength", strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void mainLoop(NioInputStream is, NioPrintStream os) {
|
private final void mainLoop(LocalPipe is, LocalPipe os) {
|
||||||
String line;
|
String line;
|
||||||
while ((line = is.readLine()) != null) {
|
while ((line = is.readLine()) != null) {
|
||||||
handleCommand(line, os);
|
handleCommand(line, os);
|
||||||
@@ -103,12 +93,18 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutDown() {
|
||||||
|
super.shutDown();
|
||||||
|
guiToEngine.close();
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
@Override
|
@Override
|
||||||
public final String readLineFromEngine(int timeoutMillis) {
|
public final String readLineFromEngine(int timeoutMillis) {
|
||||||
if ((engineThread != null) && !engineThread.isAlive())
|
if ((engineThread != null) && !engineThread.isAlive())
|
||||||
return null;
|
return null;
|
||||||
String ret = inFromEngine.readLine(timeoutMillis);
|
String ret = engineToGui.readLine(timeoutMillis);
|
||||||
if (ret == null)
|
if (ret == null)
|
||||||
return null;
|
return null;
|
||||||
if (ret.length() > 0) {
|
if (ret.length() > 0) {
|
||||||
@@ -121,25 +117,21 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
@Override
|
@Override
|
||||||
public final synchronized void writeLineToEngine(String data) {
|
public final synchronized void writeLineToEngine(String data) {
|
||||||
// System.out.printf("GUI -> Engine: %s\n", data);
|
// System.out.printf("GUI -> Engine: %s\n", data);
|
||||||
try {
|
guiToEngine.addLine(data);
|
||||||
String s = data + "\n";
|
|
||||||
guiToEngine.sink().write(ByteBuffer.wrap(s.getBytes()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void handleCommand(String cmdLine, NioPrintStream os) {
|
private final void handleCommand(String cmdLine, LocalPipe os) {
|
||||||
String[] tokens = tokenize(cmdLine);
|
String[] tokens = tokenize(cmdLine);
|
||||||
try {
|
try {
|
||||||
String cmd = tokens[0];
|
String cmd = tokens[0];
|
||||||
if (cmd.equals("uci")) {
|
if (cmd.equals("uci")) {
|
||||||
os.printf("id name %s%n", ComputerPlayer.engineName);
|
os.printLine("id name %s", ComputerPlayer.engineName);
|
||||||
os.printf("id author Peter Osterlund%n");
|
os.printLine("id author Peter Osterlund");
|
||||||
DroidEngineControl.printOptions(os);
|
DroidEngineControl.printOptions(os);
|
||||||
os.printf("uciok%n");
|
os.printLine("uciok");
|
||||||
} else if (cmd.equals("isready")) {
|
} else if (cmd.equals("isready")) {
|
||||||
initEngine(os);
|
initEngine(os);
|
||||||
os.printf("readyok%n");
|
os.printLine("readyok");
|
||||||
} else if (cmd.equals("setoption")) {
|
} else if (cmd.equals("setoption")) {
|
||||||
initEngine(os);
|
initEngine(os);
|
||||||
StringBuilder optionName = new StringBuilder();
|
StringBuilder optionName = new StringBuilder();
|
||||||
@@ -260,7 +252,7 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void initEngine(NioPrintStream os) {
|
private final void initEngine(LocalPipe os) {
|
||||||
if (engine == null) {
|
if (engine == null) {
|
||||||
engine = new DroidEngineControl(os);
|
engine = new DroidEngineControl(os);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.petero.droidfish.engine.LocalPipe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control the search thread.
|
* Control the search thread.
|
||||||
* @author petero
|
* @author petero
|
||||||
*/
|
*/
|
||||||
public class DroidEngineControl {
|
public class DroidEngineControl {
|
||||||
NioPrintStream os;
|
LocalPipe os;
|
||||||
|
|
||||||
Thread engineThread;
|
Thread engineThread;
|
||||||
private final Object threadMutex;
|
private final Object threadMutex;
|
||||||
@@ -76,18 +78,18 @@ public class DroidEngineControl {
|
|||||||
* This class is responsible for sending "info" strings during search.
|
* This class is responsible for sending "info" strings during search.
|
||||||
*/
|
*/
|
||||||
static class SearchListener implements Search.Listener {
|
static class SearchListener implements Search.Listener {
|
||||||
NioPrintStream os;
|
LocalPipe os;
|
||||||
|
|
||||||
SearchListener(NioPrintStream os) {
|
SearchListener(LocalPipe os) {
|
||||||
this.os = os;
|
this.os = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyDepth(int depth) {
|
public void notifyDepth(int depth) {
|
||||||
os.printf("info depth %d%n", depth);
|
os.printLine("info depth %d", depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyCurrMove(Move m, int moveNr) {
|
public void notifyCurrMove(Move m, int moveNr) {
|
||||||
os.printf("info currmove %s currmovenumber %d%n", moveToString(m), moveNr);
|
os.printLine("info currmove %s currmovenumber %d", moveToString(m), moveNr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyPV(int depth, int score, int time, long nodes, int nps, boolean isMate,
|
public void notifyPV(int depth, int score, int time, long nodes, int nps, boolean isMate,
|
||||||
@@ -103,16 +105,16 @@ public class DroidEngineControl {
|
|||||||
} else if (lowerBound) {
|
} else if (lowerBound) {
|
||||||
bound = " lowerbound";
|
bound = " lowerbound";
|
||||||
}
|
}
|
||||||
os.printf("info depth %d score %s %d%s time %d nodes %d nps %d pv%s%n",
|
os.printLine("info depth %d score %s %d%s time %d nodes %d nps %d pv%s",
|
||||||
depth, isMate ? "mate" : "cp", score, bound, time, nodes, nps, pvBuf.toString());
|
depth, isMate ? "mate" : "cp", score, bound, time, nodes, nps, pvBuf.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyStats(long nodes, int nps, int time) {
|
public void notifyStats(long nodes, int nps, int time) {
|
||||||
os.printf("info nodes %d nps %d time %d%n", nodes, nps, time);
|
os.printLine("info nodes %d nps %d time %d", nodes, nps, time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DroidEngineControl(NioPrintStream os) {
|
public DroidEngineControl(LocalPipe os) {
|
||||||
this.os = os;
|
this.os = os;
|
||||||
threadMutex = new Object();
|
threadMutex = new Object();
|
||||||
setupTT();
|
setupTT();
|
||||||
@@ -260,9 +262,9 @@ public class DroidEngineControl {
|
|||||||
Move ponderMove = getPonderMove(pos, m);
|
Move ponderMove = getPonderMove(pos, m);
|
||||||
synchronized (threadMutex) {
|
synchronized (threadMutex) {
|
||||||
if (ponderMove != null) {
|
if (ponderMove != null) {
|
||||||
os.printf("bestmove %s ponder %s%n", moveToString(m), moveToString(ponderMove));
|
os.printLine("bestmove %s ponder %s", moveToString(m), moveToString(ponderMove));
|
||||||
} else {
|
} else {
|
||||||
os.printf("bestmove %s%n", moveToString(m));
|
os.printLine("bestmove %s", moveToString(m));
|
||||||
}
|
}
|
||||||
engineThread = null;
|
engineThread = null;
|
||||||
sc = null;
|
sc = null;
|
||||||
@@ -362,14 +364,14 @@ public class DroidEngineControl {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printOptions(NioPrintStream os) {
|
static void printOptions(LocalPipe os) {
|
||||||
os.printf("option name Hash type spin default 2 min 1 max 2048%n");
|
os.printLine("option name Hash type spin default 2 min 1 max 2048");
|
||||||
os.printf("option name OwnBook type check default false%n");
|
os.printLine("option name OwnBook type check default false");
|
||||||
os.printf("option name Ponder type check default true%n");
|
os.printLine("option name Ponder type check default true");
|
||||||
os.printf("option name UCI_AnalyseMode type check default false%n");
|
os.printLine("option name UCI_AnalyseMode type check default false");
|
||||||
os.printf("option name UCI_EngineAbout type string default %s by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html%n",
|
os.printLine("option name UCI_EngineAbout type string default %s by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html",
|
||||||
ComputerPlayer.engineName);
|
ComputerPlayer.engineName);
|
||||||
os.printf("option name Strength type spin default 1000 min 0 max 1000\n");
|
os.printLine("option name Strength type spin default 1000 min 0 max 1000");
|
||||||
}
|
}
|
||||||
|
|
||||||
final void setOption(String optionName, String optionValue) {
|
final void setOption(String optionName, String optionValue) {
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
DroidFish - An Android chess program.
|
|
||||||
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.petero.droidfish.engine.cuckoochess;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.channels.Pipe;
|
|
||||||
import java.nio.channels.SelectionKey;
|
|
||||||
import java.nio.channels.Selector;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/** Simple InputStream look-alike on top of nio. */
|
|
||||||
class NioInputStream {
|
|
||||||
Pipe.SourceChannel in;
|
|
||||||
ByteBuffer buffer;
|
|
||||||
Selector selector;
|
|
||||||
|
|
||||||
ArrayList<Character> inBuf;
|
|
||||||
StringBuilder lineBuf;
|
|
||||||
|
|
||||||
public NioInputStream(Pipe pipe) {
|
|
||||||
in = pipe.source();
|
|
||||||
try {
|
|
||||||
in.configureBlocking(false);
|
|
||||||
selector = Selector.open();
|
|
||||||
in.register(selector, SelectionKey.OP_READ);
|
|
||||||
|
|
||||||
buffer = ByteBuffer.allocate(1024);
|
|
||||||
inBuf = new ArrayList<Character>();
|
|
||||||
lineBuf = new StringBuilder(128);
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String readLine() {
|
|
||||||
while (true) {
|
|
||||||
String s = readLine(1000);
|
|
||||||
if (s != null)
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String readLine(int timeoutMillis) {
|
|
||||||
try {
|
|
||||||
boolean haveNewLine = false;
|
|
||||||
for (int i = 0; i < inBuf.size(); i++) {
|
|
||||||
if (inBuf.get(i) == '\n') {
|
|
||||||
haveNewLine = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!haveNewLine) {
|
|
||||||
// Refill inBuf
|
|
||||||
if (timeoutMillis < 1)
|
|
||||||
timeoutMillis = 1;
|
|
||||||
selector.select(timeoutMillis);
|
|
||||||
buffer.clear();
|
|
||||||
for (SelectionKey sk : selector.selectedKeys())
|
|
||||||
if (sk.isValid() && sk.isReadable())
|
|
||||||
in.read(buffer);
|
|
||||||
buffer.flip();
|
|
||||||
while (buffer.position() < buffer.limit()) {
|
|
||||||
byte b = buffer.get();
|
|
||||||
inBuf.add((char)b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract line
|
|
||||||
String ret = "";
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < inBuf.size(); i++) {
|
|
||||||
char c = inBuf.get(i);
|
|
||||||
if (c == '\n') {
|
|
||||||
int newSize = inBuf.size() - i - 1;
|
|
||||||
for (int j = 0; j < newSize; j++)
|
|
||||||
inBuf.set(j, inBuf.get(j+i+1));
|
|
||||||
while (inBuf.size() > newSize)
|
|
||||||
inBuf.remove(inBuf.size() - 1);
|
|
||||||
ret = lineBuf.toString();
|
|
||||||
lineBuf = new StringBuilder(128);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
lineBuf.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == inBuf.size())
|
|
||||||
inBuf.clear();
|
|
||||||
return ret;
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
DroidFish - An Android chess program.
|
|
||||||
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.petero.droidfish.engine.cuckoochess;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.channels.Pipe;
|
|
||||||
|
|
||||||
/** Simple PrintStream look-alike on top of nio. */
|
|
||||||
class NioPrintStream {
|
|
||||||
Pipe.SinkChannel out;
|
|
||||||
|
|
||||||
public NioPrintStream(Pipe pipe) {
|
|
||||||
out = pipe.sink();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printf(String format) {
|
|
||||||
try {
|
|
||||||
String s = String.format(format, new Object[]{});
|
|
||||||
out.write(ByteBuffer.wrap(s.getBytes()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printf(String format, Object ... args) {
|
|
||||||
try {
|
|
||||||
String s = String.format(format, args);
|
|
||||||
out.write(ByteBuffer.wrap(s.getBytes()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user