/*
* Copyright 2013 Amazon Technologies, Inc.
*
* 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://aws.amazon.com/apache2.0
*
* This file 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 com.amazonaws.eclipse.cloudformation.templates.editor;
import java.util.Stack;
import org.eclipse.jface.text.BadLocationException;
import com.amazonaws.eclipse.cloudformation.templates.editor.TemplateEditor.TemplateDocument;
/**
* Common utilities for searching through documents.
*/
public class DocumentUtils {
/**
* Starting at the given position in the specified document, this method
* reads over chars until it finds a non-whitespace char and returns that
* char.
*
* @param document
* The document to search in.
* @param position
* The offset in the document to start searching at.
*
* @return The first non-whitespace char found after the specified position
* in the document.
*/
public static char readToNextChar(TemplateDocument document, int position) {
try {
while (true) {
char c = document.getChar(position++);
if (Character.isWhitespace(c)) continue;
return c;
}
} catch (BadLocationException e) {
throw new RuntimeException("Error reading ahead to next char", e);
}
}
/**
* Reads chars backwards, starting at the specified position in the
* document, until it finds the first unmatched open brace (i.e. '[' or
* '{'). If closed braces are found, they are pushed on a stack, so that the
* nested opening brace matching that one is *not* returned. This method is
* used to find the opening brace for the array or map that contains the
* specified position.
*
* @param document
* The document to search in.
* @param position
* The offset in the document to start searching at.
*
* @return The first unmatched open brace, which indicates the map or array
* that contains the specified position.
*/
public static char readToPreviousUnmatchedOpenBrace(TemplateDocument document, int position) {
try {
Stack<Character> stack = new Stack<Character>();
position--;
while (true) {
char c = document.getChar(position--);
if (Character.isWhitespace(c)) continue;
if (c == '}' || c == ']') {
stack.push(c);
} else if (c == '{' || c == '[') {
if (stack.isEmpty()) return c;
// Just assume the braces are nested correctly
stack.pop();
}
}
} catch (BadLocationException e) {
throw new RuntimeException("Error reading ahead to next char", e);
}
}
/**
* Searches the specified document, backwards, starting from the specified
* position, looking for the first occurrence of the target character, and
* returns the document position of that first occurrence.
*
* @param document
* The document to search in.
* @param position
* The offset in the document to start searching at.
* @param charToFind
* The character being searched for.
*
* @return The document position of the first occurrence of the specified
* target character, occurring before the specified starting
* position in the document.
*/
public static int findPreviousCharPosition(TemplateDocument document, int position, char charToFind) {
try {
while (true) {
position--;
if (charToFind == document.getChar(position)) return position;
}
} catch (BadLocationException e) {
throw new RuntimeException("Error reading back to previous char", e);
}
}
/**
* Searches the document backwards, starting at the specified position,
* looking for the first non-whitespace character, and returns that
* character.
*
* @param document
* The document to search in.
* @param position
* The offset in the document to start searching at.
*
* @return The first non-whitespace character that occurs before the
* specified position in the document.
*/
public static char readToPreviousChar(TemplateDocument document, int position) {
try {
position--;
while (true) {
char c = document.getChar(position--);
if (Character.isWhitespace(c)) continue;
return c;
}
} catch (BadLocationException e) {
throw new RuntimeException("Error reading ahead to next char", e);
}
}
/**
* Reads a string backwards from the current offset position to first
* occurrence of a double quote.
*
* @param document
* The document to search in.
* @param position
* The offset in the document to start searching at.
* @return The string from the specified position to the first occurrence of
* double quote.
* @throws RuntimeException if the character cannot be read from the document.
*/
public static String readToPreviousQuote(TemplateDocument document,
int position) {
StringBuilder typedString = new StringBuilder();
char c;
try {
position--;
while (true) {
c = document.getChar(position--);
if (c == '"')
break;
typedString.append(c);
}
} catch (BadLocationException e) {
throw new RuntimeException("Error reading ahead to next char", e);
}
return typedString.reverse().toString();
}
}