Changeset 128:a83b186b8419 in livinglogic.java.ul4

Show
Ignore:
Timestamp:
07/07/08 18:05:51 (11 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Add javadoc comments. Strings now longer use two delimiters in the UL4 file format.

Instead the terminator is written without any preceeding digits, if the string
is null.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • library/src/com/livinglogic/ul4/Template.java

    r127 r128  
    5252    } 
    5353 
     54    /** 
     55     * Contains information about the currently running loops during rendering 
     56     * of the template. 
     57     */ 
    5458    class IteratorStackEntry 
    5559    { 
     60        /** 
     61         * The register number where the loop variable has to be stored for each 
     62         * run through the loop body. 
     63         */ 
    5664        public int iteratorRegSpec; 
     65        /** 
     66         * The program counter (i.e. the index of the opcode in the {@link #opcodes} list) 
     67         * where the loop started (i.e. the location of the FOR ocode). 
     68         */ 
    5769        public int pc; 
     70        /** 
     71         * The iterator producing the values for the loop variable. 
     72         */ 
    5873        public Iterator iterator; 
    5974 
     
    6681    } 
    6782 
     83    /** 
     84     * The header used in the compiled format of the template. 
     85     */ 
    6886    public static final String HEADER = "ul4"; 
    6987 
     88    /** 
     89     * The version number used in the compiled format of the template. 
     90     */ 
    7091    public static final String VERSION = "2"; 
    7192 
     93    /** 
     94     * The start delimiter for tags (defaults to <code>&lt;?</code>) 
     95     */  
    7296    public String startdelim; 
    7397 
     98    /** 
     99     * The end delimiter for tags (defaults to <code>?&gt;</code>) 
     100     */  
    74101    public String enddelim; 
    75102 
     103    /** 
     104     * The template source. 
     105     */  
    76106    public String source; 
    77107 
     108    /** 
     109     * The list of opcodes. 
     110     */  
    78111    public List opcodes; 
    79112     
     113    /** 
     114     * The locate to be used when formatting int, float or date objects. 
     115     */  
    80116    public Locale defaultLocale; 
    81117 
     118    /** 
     119     * Has {@link annotate} been called for this template? 
     120     */ 
    82121    private boolean annotated = false; 
    83122 
     123    /** 
     124     * Creates an empty template object. 
     125     */ 
    84126    public Template() 
    85127    { 
     
    89131    } 
    90132 
     133    /** 
     134     * Appends a new opcode to {@link opcodes}. 
     135     */ 
    91136    public void opcode(int name, Location location) 
    92137    { 
     
    94139    } 
    95140 
     141    /** 
     142     * Appends a new opcode to {@link opcodes}. 
     143     */ 
    96144    public void opcode(int name, String arg, Location location) 
    97145    { 
     
    99147    } 
    100148 
     149    /** 
     150     * Appends a new opcode to {@link opcodes}. 
     151     */ 
    101152    public void opcode(int name, int r1, Location location) 
    102153    { 
     
    104155    } 
    105156 
     157    /** 
     158     * Appends a new opcode to {@link opcodes}. 
     159     */ 
    106160    public void opcode(int name, int r1, String arg, Location location) 
    107161    { 
     
    109163    } 
    110164 
     165    /** 
     166     * Appends a new opcode to {@link opcodes}. 
     167     */ 
    111168    public void opcode(int name, int r1, int r2, Location location) 
    112169    { 
     
    114171    } 
    115172 
     173    /** 
     174     * Appends a new opcode to {@link opcodes}. 
     175     */ 
    116176    public void opcode(int name, int r1, int r2, String arg, Location location) 
    117177    { 
     
    119179    } 
    120180 
     181    /** 
     182     * Appends a new opcode to {@link opcodes}. 
     183     */ 
    121184    public void opcode(int name, int r1, int r2, int r3, Location location) 
    122185    { 
     
    124187    } 
    125188 
     189    /** 
     190     * Appends a new opcode to {@link opcodes}. 
     191     */ 
    126192    public void opcode(int name, int r1, int r2, int r3, String arg, Location location) 
    127193    { 
     
    129195    } 
    130196 
     197    /** 
     198     * Appends a new opcode to {@link opcodes}. 
     199     */ 
    131200    public void opcode(int name, int r1, int r2, int r3, int r4, Location location) 
    132201    { 
     
    134203    } 
    135204 
     205    /** 
     206     * Appends a new opcode to {@link opcodes}. 
     207     */ 
    136208    public void opcode(int name, int r1, int r2, int r3, int r4, String arg, Location location) 
    137209    { 
     
    139211    } 
    140212 
     213    /** 
     214     * Appends a new opcode to {@link opcodes}. 
     215     */ 
    141216    public void opcode(int name, int r1, int r2, int r3, int r4, int r5, Location location) 
    142217    { 
     
    144219    } 
    145220 
     221    /** 
     222     * Appends a new opcode to {@link opcodes}. 
     223     */ 
    146224    public void opcode(int name, int r1, int r2, int r3, int r4, int r5, String arg, Location location) 
    147225    { 
     
    149227    } 
    150228 
    151     protected static int readintInternal(Reader reader, char terminator1, char terminator0) throws IOException 
     229    protected static int readintInternal(Reader reader, char terminator) throws IOException 
    152230    { 
    153231        int retVal = 0; 
     232        boolean digitFound = false; 
    154233        boolean terminatorFound = false; 
    155234        int readInt = reader.read(); 
     
    163242            { 
    164243                retVal = retVal * 10 + intValue; 
    165             } 
    166             else if (charValue == terminator1) 
     244                digitFound = true; 
     245            } 
     246            else if (charValue == terminator) 
    167247            { 
    168248                terminatorFound = true; 
    169             } 
    170             else if (charValue == terminator0) 
    171             { 
    172                 terminatorFound = true; 
    173                 retVal = -1; 
     249                if (!digitFound) 
     250                    retVal = -1; 
    174251            } 
    175252            else 
    176253            { 
    177                 throw new RuntimeException("Invalid terminator, expected " + terminator1 + " or " + terminator0 + ", got " + charValue); 
     254                throw new RuntimeException("Invalid terminator, expected " + terminator + ", got " + charValue); 
    178255            } 
    179256            if (!terminatorFound) 
     
    187264    protected static int readint(Reader reader, char terminator) throws IOException 
    188265    { 
    189         int retVal = readintInternal(reader, terminator, terminator); 
     266        int retVal = readintInternal(reader, terminator); 
    190267        if (0 > retVal) 
    191268        { 
     
    195272    } 
    196273 
    197     protected static String readstr(Reader reader, char terminator1, char terminator0) throws IOException 
     274    protected static String readstr(Reader reader, char terminator) throws IOException 
    198275    { 
    199276        String retVal = null; 
    200         int stringLength = readintInternal(reader, terminator1, terminator0); 
     277        int stringLength = readintInternal(reader, terminator); 
    201278        if (-1 < stringLength) 
    202279        { 
     
    257334    } 
    258335 
     336    /** 
     337     * loads the source of a template from a reader, whichout checking the version 
     338     * number of the binary file. This is helpful when updating an old stored source. 
     339     * @param reader the reader from which the source is read. 
     340     * @return The source as a string. 
     341     * @throws IOException if reading from the stream fails 
     342     */ 
    259343    public static String loadsource(Reader reader) throws IOException 
    260344    { 
     
    262346        bufferedReader.readLine(); // skip header (without checking) 
    263347        bufferedReader.readLine(); // skip version number (with checking) 
    264         readstr(bufferedReader, '<', '['); // skip start delimiter 
     348        readstr(bufferedReader, '<'); // skip start delimiter 
    265349        readcr(bufferedReader); 
    266         readstr(bufferedReader, '>', ']'); // skip end delimiter 
     350        readstr(bufferedReader, '>'); // skip end delimiter 
    267351        readcr(bufferedReader); 
    268         return readstr(bufferedReader, '\'', '"'); 
    269     } 
    270  
     352        return readstr(bufferedReader, '"'); 
     353    } 
     354 
     355    /** 
     356     * loads the source of a template from a string containing the compiled 
     357     * template. 
     358     * @param bytecode of the compiled template. 
     359     * @return The source as a string. 
     360     */ 
    271361    public static String loadsource(String bytecode) 
    272362    { 
     
    281371    } 
    282372 
     373    /** 
     374     * loads a template from a reader. 
     375     * @param reader the reader from which the template is read. 
     376     * @return The template object. 
     377     * @throws IOException if reading from the stream fails 
     378     */ 
    283379    public static Template load(Reader reader) throws IOException 
    284380    { 
     
    295391            throw new RuntimeException("Invalid version, expected " + VERSION + ", got " + version); 
    296392        } 
    297         retVal.startdelim = readstr(bufferedReader, '<', '['); 
     393        retVal.startdelim = readstr(bufferedReader, '<'); 
    298394        readcr(bufferedReader); 
    299         retVal.enddelim = readstr(bufferedReader, '>', ']'); 
     395        retVal.enddelim = readstr(bufferedReader, '>'); 
    300396        readcr(bufferedReader); 
    301         retVal.source = readstr(bufferedReader, '\'', '"'); 
     397        retVal.source = readstr(bufferedReader, '"'); 
    302398        readcr(bufferedReader); 
    303399        int count = readint(bufferedReader, '#'); 
     
    311407            int r4 = readspec(bufferedReader); 
    312408            int r5 = readspec(bufferedReader); 
    313             String code = readstr(bufferedReader, ':', '.'); 
    314             String arg = readstr(bufferedReader, ';', ','); 
     409            String code = readstr(bufferedReader, ':'); 
     410            String arg = readstr(bufferedReader, '.'); 
    315411            int readInt = bufferedReader.read(); 
    316412            if (-1 < readInt) 
     
    326422                else if ('*' == charValue) 
    327423                { 
    328                     location = new Location(retVal.source, readstr(bufferedReader, '=', '-'), 
     424                    location = new Location(retVal.source, readstr(bufferedReader, '='), 
    329425                        readint(bufferedReader, '('), readint(bufferedReader, ')'), 
    330426                        readint(bufferedReader, '{'), readint(bufferedReader, '}')); 
     
    345441    } 
    346442 
     443    /** 
     444     * loads a template from a string. 
     445     * @param bytecode of the compiled template. 
     446     * @return The template object. 
     447     * @throws IOException if reading from the stream fails 
     448     */ 
    347449    public static Template load(String bytecode) 
    348450    { 
     
    357459    } 
    358460 
     461    /** 
     462     * writes an int to a stream in such a way that the int can be reliable read again. 
     463     * @param writer the stream to which to write. 
     464     * @param value the int value to be written. 
     465     * @param terminator a terminating character written after the value. 
     466     * @throws IOException if writing to the stream fails 
     467     */ 
    359468    protected static void writeint(Writer writer, int value, char terminator) throws IOException 
    360469    { 
     
    363472    } 
    364473 
    365     protected static void writestr(Writer writer, String value, char terminator1, char terminator0) throws IOException 
     474    /** 
     475     * writes a string to a stream in such a way that the string can be reliable read again. 
     476     * @param writer the stream to which to write. 
     477     * @param value the string value to be written (may be null). 
     478     * @param terminator a terminating character written after the string length. 
     479     * @throws IOException if writing to the stream fails 
     480     */ 
     481    protected static void writestr(Writer writer, String value, char terminator) throws IOException 
    366482    { 
    367483        if (value == null) 
    368484        { 
    369             writer.write(terminator0); 
     485            writer.write(terminator); 
    370486        } 
    371487        else 
    372488        { 
    373489            writer.write(String.valueOf(value.length())); 
    374             writer.write(terminator1); 
     490            writer.write(terminator); 
    375491            writer.write(value); 
    376492        } 
    377493    } 
    378494 
     495    /** 
     496     * writes a register specification to a stream (which is either a digit or '-' in case the register spec is empty. 
     497     * @param writer the stream to which to write. 
     498     * @param spec the register number or -1 in case the register spec is empty. 
     499     * @throws IOException if writing to the stream fails 
     500     */ 
    379501    protected static void writespec(Writer writer, int spec) throws IOException 
    380502    { 
     
    385507    } 
    386508 
     509    /** 
     510     * writes the Template object to a stream. 
     511     * @param writer the stream to which to write. 
     512     * @throws IOException if writing to the stream fails 
     513     */ 
    387514    public void dump(Writer writer) throws IOException 
    388515    { 
     
    391518        writer.write(VERSION); 
    392519        writer.write("\n"); 
    393         writestr(writer, startdelim, '<', '['); 
     520        writestr(writer, startdelim, '<'); 
    394521        writer.write("\n"); 
    395         writestr(writer, enddelim, '>', ']'); 
     522        writestr(writer, enddelim, '>'); 
    396523        writer.write("\n"); 
    397         writestr(writer, source, '\'', '"'); 
     524        writestr(writer, source, '"'); 
    398525        writer.write("\n"); 
    399526        writeint(writer, opcodes.size(), '#'); 
     
    408535            writespec(writer, opcode.r4); 
    409536            writespec(writer, opcode.r5); 
    410             writestr(writer, Opcode.code2name(opcode.name), ':', '.'); 
    411             writestr(writer, opcode.arg, ';', ','); 
     537            writestr(writer, Opcode.code2name(opcode.name), ':'); 
     538            writestr(writer, opcode.arg, '.'); 
    412539            if (opcode.location != lastLocation) 
    413540            { 
    414541                writer.write("*"); 
    415                 writestr(writer, opcode.location.type, '=', '-'); 
     542                writestr(writer, opcode.location.type, '='); 
    416543                writeint(writer, opcode.location.starttag, '('); 
    417544                writeint(writer, opcode.location.endtag, ')'); 
     
    428555    } 
    429556 
     557    /** 
     558     * writes the Template object to a string. 
     559     * @param writer the stream to which to write. 
     560     * @return The string containing the template in compiled format. 
     561     */ 
    430562    public String dumps() 
    431563    { 
     
    435567            dump(writer); 
    436568        } 
    437         catch (IOException ex) // can not happen, when dumping the a StringWriter 
     569        catch (IOException ex) // can not happen, when dumping to a StringWriter 
    438570        { 
    439571        } 
     
    441573    } 
    442574 
     575    /** 
     576     * Annotates all control flow opcodes in the template with the jump location 
     577     * (i.e. a FOR opcode gets annotated with the location of the associated 
     578     * ENDFOR opcode, an IF opcode gets annotated with the location of 
     579     * the associated ELSE or ENDIF opcode, an ELSE opcode gets annotated with 
     580     * the location of ENDIF opcode). 
     581     */ 
    443582    protected void annotate() 
    444583    { 
     
    475614    } 
    476615 
     616    /** 
     617     * Renders the template. 
     618     * @param variables a map containing the top level variables that should be 
     619     *                  available to the template code. 
     620     * @param templates a map containing other template object that can be called 
     621     *                  by the template via the <code>&lt;?render?&gt;</code> tag. 
     622     * @return An iterator that returns the string output piece by piece. 
     623     */ 
    477624    public Iterator render(Map variables, Map templates) 
    478625    { 
     
    480627    } 
    481628 
     629    /** 
     630     * Renders the template and returns the resulting string. 
     631     * @param variables a map containing the top level variables that should be 
     632     *                  available to the template code. 
     633     * @param templates a map containing other template object that can be called 
     634     *                  by the template via the <code>&lt;?render?&gt;</code> tag. 
     635     * @return The render output as a string. 
     636     */ 
    482637    public String renders(Map variables, Map templates) 
    483638    { 
     
    493648    class Renderer implements Iterator 
    494649    { 
     650        /** 
     651         * The current program counter 
     652         */ 
    495653        private int pc = 0; 
     654 
     655        /** 
     656         * The ten registers of our CPU 
     657         */ 
    496658        private Object[] reg = new Object[10]; 
     659 
     660        /** 
     661         * The variables passed to the {@com.livinglogic.ul4.Template#render} call 
     662         * During the run of the iterator loop variables and variables from 
     663         * <code>&lt;?code>&gt;</code> tag will be stored here 
     664         */ 
    497665        private Map variables; 
     666 
     667        /** 
     668         * A map containing other template object that can be called by the 
     669         * template code via the <code>&lt;?render?&gt;</code> tag. 
     670         */ 
    498671        private Map templates; 
     672 
     673        /** 
     674         * The stack of active for loops 
     675         */ 
    499676        private LinkedList iterators = new LinkedList(); 
     677 
     678        /** 
     679         * If a subtemplate is running (i.e. if we're inside a 
     680         * <code>&lt;?render?&gt;</code> tag), this variable references the 
     681         * active part iterator for the subtemplate. 
     682         */ 
    500683        private Iterator subTemplateIterator = null; 
    501684 
     685        /** 
     686         * Since we implement the iterator interface we have to support both 
     687         * <code>next</code> and <code>hasNext</code>. This means that neither 
     688         * of the two methods can directly run the opcodes to get the next output 
     689         * chunk. Instead of that we have a method {@link getNextChunk} that runs 
     690         * the opcodes until the next output chunk is produced and stores it in 
     691         * <code>nextChunk</code>, when both <code>next</code> and 
     692         * <code>hasNext</code> can refer to it. 
     693         */ 
    502694        private String nextChunk = null; 
    503695 
     
    531723        } 
    532724 
     725        /** 
     726         * Gets the next output chunk and stores it in {@link nextChunk} 
     727         */ 
    533728        public void getNextChunk() 
    534729        {