tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceStringSearch.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceStringSearch.java Tue Aug 31 16:45:49 2010 +0300
@@ -0,0 +1,267 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+* String search algorithm
+*
+*/
+package com.nokia.tracecompiler.source;
+
+import java.util.List;
+
+/**
+ * String search algorithm
+ *
+ */
+public class SourceStringSearch extends SourceSearch {
+
+ /**
+ * String to be searched from the source.
+ */
+ private String searchString;
+
+ /**
+ * Number of different characters in source file alphabet. Assumes that
+ * 8-bit encoding is used
+ */
+ private final static int CHARACTER_COUNT = 256; // CodForChk_Dis_Magic
+
+ /**
+ * Mask for bad character shifts (0xFF)
+ */
+ private static final int BAD_CHARACTER_MASK = 0xFF; // CodForChk_Dis_Magic
+
+ /**
+ * String search shifts.
+ */
+ private int[] badCharacterShifts = new int[CHARACTER_COUNT];
+
+ /**
+ * User data associated with search
+ */
+ private Object searchData;
+
+ /**
+ * Creates a new string search
+ *
+ * @param parser
+ * the parser containing the source to be searched
+ * @param searchString
+ * the string to be searched
+ * @param startOffset
+ * offset to the start of search
+ * @param endOffset
+ * offset to end of search or -1 for rest of the document
+ * @param flags
+ * the search flags
+ */
+ public SourceStringSearch(SourceParser parser, String searchString,
+ int startOffset, int endOffset, int flags) {
+ super(parser, startOffset, endOffset, flags);
+ setSearchString(searchString);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.nokia.tracecompiler.source.SourceSearch#findNext()
+ */
+ @Override
+ public int findNext() {
+ try {
+ SourceDocumentInterface source = parser.getSource();
+ int stringIndex = searchString.length() - 1;
+ boolean found = false;
+ while (!found && searchIndex + stringIndex < searchEnd) {
+ char dataChar;
+ char searchChar;
+ boolean match = false;
+ do {
+ dataChar = source.getChar(searchIndex + stringIndex);
+ searchChar = searchString.charAt(stringIndex);
+ if ((flags & SourceParser.IGNORE_CASE) != 0) {
+ searchChar = Character.toLowerCase(searchChar);
+ dataChar = Character.toLowerCase(dataChar);
+ }
+ if (searchChar == '?' || searchChar == dataChar) {
+ match = true;
+ stringIndex--;
+ } else {
+ match = false;
+ }
+ } while (match && stringIndex >= 0);
+ // If string was not found, resets index and skips according
+ // to the shift table
+ if (stringIndex < 0) {
+ found = true;
+ // Checks the previous character if match beginning is set
+ if ((flags & SourceParser.MATCH_WORD_BEGINNING) != 0) {
+ if ((searchIndex > 0)
+ && isPartOfWord(source.getChar(searchIndex - 1))) {
+ found = false;
+ }
+ }
+ // Checks the character after data if match end is set
+ if (found && ((flags & SourceParser.MATCH_WORD_END) != 0)) {
+ if (((searchIndex + searchString.length()) < source
+ .getLength())
+ && isPartOfWord(source.getChar(searchIndex
+ + searchString.length()))) {
+ found = false;
+ }
+ }
+ }
+ if (!found) {
+ int diff = searchString.length() - 1 - stringIndex;
+ stringIndex = searchString.length() - 1;
+ int skip;
+
+ if (dataChar > badCharacterShifts.length - 1) {
+ skip = 1;
+ } else {
+ skip = badCharacterShifts[dataChar] - diff;
+ if (skip <= 0) {
+ skip = 1;
+ }
+ }
+
+ searchIndex += skip;
+ skipExcludedArea();
+ }
+ }
+ if (!found) {
+ searchIndex = -1;
+ }
+ } catch (SourceParserException e) {
+ searchIndex = -1;
+ }
+ int ret = searchIndex;
+ if (searchIndex != -1) {
+ searchIndex += searchString.length();
+ }
+ return ret;
+ }
+
+ /**
+ * Checks if the character is part of a word
+ *
+ * @param c
+ * the character to be checked
+ * @return true if part of word
+ */
+ private boolean isPartOfWord(char c) {
+ return Character.isLetterOrDigit(c) || c == '_';
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.nokia.tracecompiler.source.SourceSearch#findAll(java.util.List)
+ */
+ @Override
+ public void findAll(List<Integer> list) throws SourceParserException {
+ resetSearch(0, -1);
+ int index;
+ do {
+ index = findNext();
+ if (index > 0) {
+ list.add(new Integer(index));
+ }
+ } while (index > 0);
+ }
+
+ /**
+ * Changes the search string
+ *
+ * @param searchString
+ * the string to be searched
+ */
+ public void setSearchString(String searchString) {
+ this.searchString = searchString;
+ int length = searchString.length();
+ // Elements not found in the string get the maximum shift distance
+ for (int i = 0; i < badCharacterShifts.length; i++) {
+ badCharacterShifts[i] = searchString.length();
+ }
+ // Characters of the search string are mapped into the
+ // shift distances array. If a character is found multiple
+ // times, the smallest shitft distance is stored
+ for (int i = 0; i < searchString.length() - 1; i++) {
+ if ((flags & SourceParser.IGNORE_CASE) != 0) {
+ badCharacterShifts[Character
+ .toLowerCase(searchString.charAt(i))
+ & BAD_CHARACTER_MASK] = length - i - 1;
+
+ } else {
+ badCharacterShifts[searchString.charAt(i) & BAD_CHARACTER_MASK] = length
+ - i - 1;
+ }
+ }
+ }
+
+ /**
+ * Returns the search string
+ *
+ * @return the string
+ */
+ public String getSearchString() {
+ return searchString;
+ }
+
+ /**
+ * Checks if the given string matches the search string
+ *
+ * @param string
+ * the string
+ * @return true if they match
+ */
+ public boolean isSearchStringMatch(String string) {
+ int index = 0;
+ boolean match = true;
+ while (index < string.length() && match) {
+ char dataChar = string.charAt(index);
+ char searchChar = searchString.charAt(index);
+ if ((flags & SourceParser.IGNORE_CASE) != 0) {
+ searchChar = Character.toLowerCase(searchChar);
+ dataChar = Character.toLowerCase(dataChar);
+ }
+ if (searchChar == '?' || searchChar == dataChar) {
+ index++;
+ } else {
+ match = false;
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Sets the user variable associated with this searcher
+ *
+ * @param data
+ * the variable
+ */
+ public void setSearchData(Object data) {
+ searchData = data;
+ }
+
+ /**
+ * Gets the user variable associated with this searcher
+ *
+ * @return the variable
+ */
+ public Object getSearchData() {
+ return searchData;
+ }
+
+}
\ No newline at end of file