org.ratpackframework.groovy.templating.internal.TemplateParser.java Source code

Java tutorial

Introduction

Here is the source code for org.ratpackframework.groovy.templating.internal.TemplateParser.java

Source

/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ratpackframework.groovy.templating.internal;

import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;

import java.io.IOException;

/**
 * Note: hardcoded to expect UTF-8.
 */
public class TemplateParser {

    private static byte[] bytes(String s) {
        return s.getBytes(CharsetUtil.UTF_8);
    }

    private static final byte[] LESS_THAN = bytes("<");
    private static final byte[] DOLLAR_BRACE = bytes("${");
    private static final byte[] PERCENT = bytes("%");
    private static final byte[] START_OUTPUT = bytes("$(\n\"\"\"");
    private static final byte[] START_CODE = bytes("\"\"\"\n);");
    private static final byte[] CLOSE_BRACE = bytes("}");
    private static final byte[] DOLLAR = bytes("$");
    private static final byte[] BACKSLASH = bytes("\\");
    private static final byte[] SEMICOLON = bytes(";");

    public void parse(ByteBuf input, ByteBuf output) throws IOException {
        startScript(output);
        byte c;
        while (input.isReadable()) {
            c = input.readByte();
            if (c == '<') {
                input.markReaderIndex();
                c = input.readByte();
                if (c != '%') {
                    output.writeBytes(LESS_THAN);
                    input.resetReaderIndex();
                } else {
                    input.markReaderIndex();
                    c = input.readByte();
                    if (c == '=') {
                        groovyExpression(input, output);
                    } else {
                        input.resetReaderIndex();
                        groovySection(input, output);
                    }
                }
                continue; // at least '<' is consumed ... read next chars.
            }
            if (c == '$') {
                input.markReaderIndex();
                c = input.readByte();
                if (c != '{') {
                    output.writeBytes(DOLLAR);
                    input.resetReaderIndex();
                } else {
                    input.markReaderIndex();
                    processGSstring(input, output);
                }
                continue; // at least '$' is consumed ... read next chars.
            }
            if (c == '\"') {
                output.writeBytes(BACKSLASH);
            }

            // Handle raw new line characters.
            if (c == '\n' || c == '\r') {
                if (c == '\r') { // on Windows, "\r\n" is a new line.
                    input.markReaderIndex();
                    c = input.readByte();
                    if (c != '\n') {
                        input.resetReaderIndex();
                    }
                }
                output.writeByte('\n');
                continue;
            }
            output.writeByte(c);
        }

        endScript(output);
    }

    private void startScript(ByteBuf output) {
        output.writeBytes(START_OUTPUT);
    }

    private void endScript(ByteBuf output) {
        output.writeBytes(START_CODE);
    }

    private void processGSstring(ByteBuf input, ByteBuf output) throws IOException {
        output.writeBytes(DOLLAR_BRACE);
        byte c;
        while (input.isReadable()) {
            c = input.readByte();
            if (c != '\n' && c != '\r') {
                output.writeByte(c);
            }
            if (c == '}') {
                break;
            }
        }
    }

    private void groovyExpression(ByteBuf input, ByteBuf output) throws IOException {
        output.writeBytes(DOLLAR_BRACE);
        byte c;
        while (input.isReadable()) {
            c = input.readByte();
            if (c == '%') {
                c = input.readByte();
                if (c != '>') {
                    output.writeBytes(PERCENT);
                } else {
                    break;
                }
            }
            if (c != '\n' && c != '\r') {
                output.writeByte(c);
            }
        }
        output.writeBytes(CLOSE_BRACE);
    }

    private void groovySection(ByteBuf input, ByteBuf output) throws IOException {
        output.writeBytes(START_CODE);
        output.writeByte('\n');
        byte c;
        while (input.isReadable()) {
            c = input.readByte();
            if (c == '%') {
                c = input.readByte();
                if (c != '>') {
                    output.writeBytes(PERCENT);
                } else {
                    break;
                }
            }

            output.writeByte(c);
        }

        output.writeByte('\n');
        output.writeBytes(SEMICOLON);
        output.writeBytes(START_OUTPUT);
    }

}