All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jamon.parser.PositionalPushbackReader Maven / Gradle / Ivy

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.jamon.parser;

import java.io.IOException;
import java.io.Reader;

import org.jamon.api.Location;
import org.jamon.api.TemplateLocation;
import org.jamon.node.LocationImpl;

/**
 * A "pushback reader" which also tracks the current position in the file. Unlike
 * {@link java.io.PushbackReader}, this class allows pushing back an EOF marker as well
 *
 * @author ian
 **/

public class PositionalPushbackReader {
  private static class Position {
    void assign(Position position) {
      row = position.row;
      column = position.column;
    }

    public void nextColumn() {
      column++;
    }

    public void nextRow() {
      row++;
      column = 1;
    }

    public org.jamon.api.Location location(TemplateLocation templateLocation) {
      return new LocationImpl(templateLocation, row, column);
    }

    public boolean isLineStart() {
      return column == 1;
    }

    private int row = 1;

    private int column = 1;
  }

  /**
   * @param templateLocation The path to the resource being read.
   * @param reader The underlying reader to use
   */
  public PositionalPushbackReader(TemplateLocation templateLocation, Reader reader) {
    this(templateLocation, reader, 1);
  }

  public PositionalPushbackReader(
    TemplateLocation templateLocation, Reader reader, int pushbackBufferSize) {
    this.reader = reader;
    this.templateLocation = templateLocation;
    positions = new Position[pushbackBufferSize + 2];
    {
      for (int i = 0; i < positions.length; i++) {
        positions[i] = new Position();
      }
    }
    pushedbackChars = new int[pushbackBufferSize];
  }

  public int read() throws IOException {
    int c;
    if (pushedbackCharsPending > 0) {
      c = pushedbackChars[--pushedbackCharsPending];
    }
    else {
      c = reader.read();
    }
    for (int i = positions.length - 1; i > 0; i--) {
      positions[i].assign(positions[i - 1]);
    }

    if (c == '\n') {
      positions[0].nextRow();
    }
    else {
      positions[0].nextColumn();
    }
    return c;
  }

  public void unread(int c) throws IOException {
    if (pushedbackCharsPending >= pushedbackChars.length) {
      throw new IOException("Trying to push back characters than allowed");
    }
    pushedbackChars[pushedbackCharsPending++] = c;

    for (int i = 0; i < positions.length - 1; i++) {
      positions[i].assign(positions[i + 1]);
    }
  }

  /**
   * Get the location of the character just read.
   *
   * @return The current location (line and column numbers starting at 1)
   */
  public org.jamon.api.Location getLocation() {
    return positions[1].location(templateLocation);
  }

  /**
   * Get the location of the next character to be read (if there is one).
   *
   * @return The location of the next character
   */
  public Location getNextLocation() {
    return positions[0].location(templateLocation);
  }

  /**
   * @return True if the character just read was at the begining of a line
   */
  public boolean isLineStart() {
    return positions[1].isLineStart();
  }

  /**
   * Mark that we are just starting a node.
   **/
  public void markNodeBeginning() {
    currentNodePosition.assign(positions[1]);
  }

  /**
   * Mark that we have just finished a node
   **/
  public void markNodeEnd() {
    currentNodePosition.assign(positions[0]);
  }

  /**
   * Get the location of the current node, as set by {@link #markNodeBeginning()} or
   * {@link #markNodeEnd()}
   *
   * @return The location of the current node
   */
  public org.jamon.api.Location getCurrentNodeLocation() {
    return currentNodePosition.location(templateLocation);
  }

  private final Reader reader;
  private final TemplateLocation templateLocation;
  int pushedbackCharsPending = 0;
  final int pushedbackChars[];
  private final Position[] positions;
  private Position currentNodePosition = new Position();
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy