diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java index d9a28ada0512f4222df9ab7524d610805b80710c..2c8a6e78563b8b909d6e524b6d88bccef429369a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java @@ -118,7 +118,17 @@ public class RegExp { } break; case ']': - withinCharClass = false; + // Detecting that the current ']' closes "empty brackets '[]' + boolean closingEmptyBrackets = (i > 0 && result.charAt(i - 1) == '[' && + (i < 2 || result.charAt(i - 2) != '\\')); + // To leave a character class open we must already be within some and the + // current ']' must be closing empty brackets. + // Examples: + // ] - there is no character class, so the current ']' has no effect + // [\[] - the ']' closes the character class + // []\[] - the 1st ']' leaves the character class open, while the 2nd one closes + // it + withinCharClass &= closingEmptyBrackets; break; } i++; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java index 7149373f62de38a7ac54a4bf2a6066a0a6eae208..b1717cbd0978c908ead547dead845cd767f7c277 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java @@ -571,10 +571,9 @@ public class FileConnections { @Override protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { - long result = raf.getFilePointer(); + long result; switch (seekMode) { case ENQUIRE: - return result; case START: break; default: @@ -583,17 +582,31 @@ public class FileConnections { switch (seekRWMode) { case LAST: if (lastMode == SeekRWMode.READ) { - readOffset = offset; + result = readOffset; + if (seekMode != SeekMode.ENQUIRE) { + readOffset = offset; + } } else { - writeOffset = offset; + result = writeOffset; + if (seekMode != SeekMode.ENQUIRE) { + writeOffset = offset; + } } break; case READ: - readOffset = offset; + result = readOffset; + if (seekMode != SeekMode.ENQUIRE) { + readOffset = offset; + } break; case WRITE: - writeOffset = offset; + result = writeOffset; + if (seekMode != SeekMode.ENQUIRE) { + writeOffset = offset; + } break; + default: + throw RInternalError.shouldNotReachHere(); } return result; } @@ -601,25 +614,39 @@ public class FileConnections { @Override public String[] readLines(int n, EnumSet<ReadLineWarning> warn, boolean skipNul) throws IOException { setReadPosition(); + // the readOffset field is updated from within super.readLines via the overridden + // updateReadOffset return super.readLines(n, warn, skipNul); } @Override public int readBin(ByteBuffer buffer) throws IOException { setReadPosition(); - return super.readBin(buffer); + try { + return super.readBin(buffer); + } finally { + readOffset = raf.getFilePointer(); + } } @Override public String readChar(int nchars, boolean useBytes) throws IOException { setReadPosition(); - return super.readChar(nchars, useBytes); + try { + return super.readChar(nchars, useBytes); + } finally { + readOffset = raf.getFilePointer(); + } } @Override public byte[] readBinChars() throws IOException { setReadPosition(); - return super.readBinChars(); + try { + return super.readBinChars(); + } finally { + readOffset = raf.getFilePointer(); + } } @TruffleBoundary @@ -654,18 +681,21 @@ public class FileConnections { public void writeBin(ByteBuffer buffer) throws IOException { setWritePosition(); super.writeBin(buffer); + writeOffset = raf.getFilePointer(); } @Override public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { setWritePosition(); super.writeChar(s, pad, eos, useBytes); + writeOffset = raf.getFilePointer(); } @Override public void writeString(String s, boolean nl) throws IOException { setWritePosition(); super.writeString(s, nl); + writeOffset = raf.getFilePointer(); } @Override diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java index 2910d4690b3a7264ff6e6e7cce3a776a8afb39b6..1f7d45dee4a82df8f2126688252e783b81572109 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java @@ -154,5 +154,8 @@ public class TestBuiltin_strsplit extends TestBase { assertEval("strsplit(c('a1a', 'a1b'), '1', fixed=FALSE)"); assertEval("strsplit(c('','a , b'), '[[:space:]]*,[[:space:]]*')"); + assertEval("strsplit('a[1][1]=x11&a[1][2]=x12', ']')"); + assertEval("strsplit('a[1][1]=x11&a[1][2]=x12', '[[]')"); + assertEval("strsplit('a[1][1]=x11&a[1][2]=x12', '[][]')"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java index f45bf32c920d464428e0fdef9caa6dd538d64845..9129f3984ce7819fe8cab6613e71cbff68706f4c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java @@ -265,6 +265,11 @@ public class TestConnections extends TestRBase { assertEval("truncate(fifo('__fifo_982346798', 'r', blocking=T)); unlink('__fifo_982346798')"); } + @Test + public void testSeek() { + assertEval("f1 <- file(open='w+b', encoding='UTF-8'); writeBin(charToRaw(\"abcd\"), f1); seek(f1); seek(f1,0); seek(f1)"); + } + private static final String[] LVAL = arr("T", "F"); private static String[] arr(String... args) {