changeset 32:bdd1c8d6b560

Do not read EOF more than once, report unexpected EOF in function data.
author Mikhail Kryshen <mikhail@kryshen.net>
date Fri, 25 Sep 2009 02:37:16 +0400
parents 3e77076621a8
children b637a4491862
files nbproject/ide-targets.xml nbproject/project.xml src/kryshen/tema/FunctionDataParser.java src/kryshen/tema/TemplateParser.java src/kryshen/tema/io/TemplateReader.java
diffstat 5 files changed, 132 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nbproject/ide-targets.xml	Fri Sep 25 02:37:16 2009 +0400
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir=".." name="tema-IDE">
+    <import file="../build.xml"/>
+    <!-- TODO: edit the following target according to your needs -->
+    <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#debugj2se) -->
+    <target depends="compile" name="debug-nb">
+        <nbjpdastart addressproperty="jpda.address" name="tema" transport="dt_socket">
+            <classpath>
+                <pathelement location="${build}"/>
+                <path refid="project.libs"/>
+            </classpath>
+        </nbjpdastart>
+        <java classname="${main_class}" fork="true">
+            <classpath>
+                <pathelement location="${build}"/>
+                <path refid="project.libs"/>
+            </classpath>
+            <arg value="-demo"/>
+            <jvmarg value="-Xdebug"/>
+            <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
+        </java>
+    </target>
+</project>
--- a/nbproject/project.xml	Sun Aug 30 02:51:15 2009 +0400
+++ b/nbproject/project.xml	Fri Sep 25 02:37:16 2009 +0400
@@ -35,6 +35,10 @@
                 <action name="run">
                     <target>run.demo</target>
                 </action>
+                <action name="debug">
+                    <script>nbproject/ide-targets.xml</script>
+                    <target>debug-nb</target>
+                </action>
             </ide-actions>
             <export>
                 <type>folder</type>
@@ -65,6 +69,7 @@
                         <label>Compile manual</label>
                         <target>doc.manual</target>
                     </action>
+                    <ide-action name="debug"/>
                 </context-menu>
             </view>
             <subprojects/>
--- a/src/kryshen/tema/FunctionDataParser.java	Sun Aug 30 02:51:15 2009 +0400
+++ b/src/kryshen/tema/FunctionDataParser.java	Fri Sep 25 02:37:16 2009 +0400
@@ -103,7 +103,12 @@
         } else {
             r = tp.parse(in, out, fd, null);
         }
-        
+
+        if (r.terminator == Terminator.EOF) {
+            throw new TemplateException
+                    ("Unexpected end of instruction data", in);
+        }
+
         if (r.terminator != Terminator.SEPARATOR)
             available = false; // No more function data available.
         
--- a/src/kryshen/tema/TemplateParser.java	Sun Aug 30 02:51:15 2009 +0400
+++ b/src/kryshen/tema/TemplateParser.java	Fri Sep 25 02:37:16 2009 +0400
@@ -271,9 +271,7 @@
             int c = in.read();
             
             if (c != s.charAt(k)) {
-                if (c >= 0) {
-                    in.unread(c);
-                }
+                in.unread(c);
                 
                 for (int j = k - 1; j >= 0; j--) {
                     in.unread(s.charAt(j));
@@ -290,10 +288,7 @@
         readLoop:
             while (true) {
                 int c = in.read();
-                
-                if (c < 0)
-                    break;
-                
+                              
                 for (int i = 0; i < chars.length; i++) {
                     if (c == chars[i])
                         continue readLoop;
@@ -307,11 +302,8 @@
     private void skipEscaped(TemplateReader in) throws IOException {
         if (matchInput(in, ESCAPE_WHITESPACE)) {
             int c = in.read();
-            
-            if (c < 0)
-                return;
-            
-            if (!Character.isWhitespace(c)) {
+                       
+            if (c < 0 || !Character.isWhitespace(c)) {
                 in.unread(c);
                 in.unread(ESCAPE_WHITESPACE);
                 return;
@@ -319,10 +311,9 @@
             
             do {
                 c = in.read();
-            } while (Character.isWhitespace(c));
+            } while (c > 0 && Character.isWhitespace(c));
             
-            if (c >= 0)
-                in.unread(c);
+            in.unread(c);
             
             return;
         }
--- a/src/kryshen/tema/io/TemplateReader.java	Sun Aug 30 02:51:15 2009 +0400
+++ b/src/kryshen/tema/io/TemplateReader.java	Fri Sep 25 02:37:16 2009 +0400
@@ -20,10 +20,10 @@
 
 package kryshen.tema.io;
 
+import java.io.FilterReader;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.LineNumberReader;
-import java.io.PushbackReader;
 import kryshen.tema.TemplateParser;
 
 /**
@@ -32,7 +32,7 @@
  *
  * @author Mikhail Kryshen
  */
-public class TemplateReader extends PushbackReader {
+public class TemplateReader extends FilterReader {
     static final int UNREAD_BUFFER_SIZE;
     
     /* Calculate UNREAD_BUFFER_SIZE value. */
@@ -50,13 +50,16 @@
         max = Math.max(max, TemplateParser.ESCAPE_NEWLINE.length() + 2);
         max = Math.max(max, TemplateParser.ESCAPE_WHITESPACE.length());
         
-        UNREAD_BUFFER_SIZE = max;
+        UNREAD_BUFFER_SIZE = max + 1;
     }
-    
+
     private final String source;
     private final LineNumberReader lnReader;
     private final TemplateReader parentReader;
-    
+
+    private final int[] unreadBuffer = new int[UNREAD_BUFFER_SIZE];
+    private int unread = 0;
+
     public TemplateReader(Reader in) {
         this(new LineNumberReader(in));
     }
@@ -70,7 +73,7 @@
     }
     
     public TemplateReader(LineNumberReader in, String source) {
-        super(in, UNREAD_BUFFER_SIZE);
+        super(in);
         
         this.parentReader = null;
         this.lnReader = in;
@@ -78,7 +81,7 @@
     }
     
     public TemplateReader(Reader in, TemplateReader parent) {
-        super(in, UNREAD_BUFFER_SIZE);
+        super(in);
         
         this.parentReader = parent;
         this.lnReader = null;
@@ -98,8 +101,89 @@
         
         return parentReader.getLineNumber();
     }
-    
+
+    @Override
+    public int read() throws IOException {
+        if (unread == 0) {
+            return super.read();
+        }
+
+        return unreadBuffer[--unread];
+    }
+
+    @Override
+    public int read(char[] cbuf, int off, int len) throws IOException {
+        int n = 0;
+
+        while (unread > 0) {
+            cbuf[off + n++] = (char) unreadBuffer[--unread];
+
+            if (n == len) {
+                return n;
+            }
+        }
+
+        return n + super.read(cbuf, off + n, len - n);
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+        if (n <= unread) {
+            unread -= n;
+            return n;
+        }
+
+        n -= unread;
+        long ret = super.skip(n) + unread;
+        unread = 0;
+
+        return ret;
+    }
+
+
     public void unread(String s) throws IOException {
         unread(s.toCharArray());
     }
+
+    public void unread(int c) {
+        if (unread + 1 > UNREAD_BUFFER_SIZE) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        unreadBuffer[unread++] = c;
+    }
+
+    public void unread(char[] buff) {
+        unread(buff, 0, buff.length);
+    }
+
+    public void unread(char[] buff, int off, int len) {
+        if (unread + len > UNREAD_BUFFER_SIZE) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        for (int i = off + len - 1; i >= off; i--) {
+            unreadBuffer[unread++] = buff[i];
+        }
+    }
+
+    @Override
+    public boolean ready() throws IOException {
+        return unread > 0 || super.ready();
+    }
+
+    @Override
+    public void mark(int readAheadLimit) throws IOException {
+        throw new IOException("Not supported");
+    }
+
+    @Override
+    public void reset() throws IOException {
+        throw new IOException("Not supported");
+    }
+
+    @Override
+    public boolean markSupported() {
+        return false;
+    }
 }