tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceIterator.java
branchRCL_3
changeset 21 52e343bb8f80
parent 20 ca8a1b6995f6
child 22 e26895079d7c
equal deleted inserted replaced
20:ca8a1b6995f6 21:52e343bb8f80
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 * SourceIterator can be used to traverse through the source file character at a time
       
    17 *
       
    18 */
       
    19 package com.nokia.tracecompiler.source;
       
    20 
       
    21 /**
       
    22  * SourceIterator can be used to traverse through the source file character at a
       
    23  * time.
       
    24  * 
       
    25  */
       
    26 public class SourceIterator {
       
    27 
       
    28 	/**
       
    29 	 * The source parser
       
    30 	 */
       
    31 	private SourceParser parser;
       
    32 
       
    33 	/**
       
    34 	 * Index of next excluded area
       
    35 	 */
       
    36 	private int nextExcludedIndex;
       
    37 
       
    38 	/**
       
    39 	 * The type of next excluded area
       
    40 	 */
       
    41 	private int nextExcludedAreaType;
       
    42 
       
    43 	/**
       
    44 	 * Offset to the start of next excluded area
       
    45 	 */
       
    46 	private int nextExcludedStart;
       
    47 
       
    48 	/**
       
    49 	 * Offset to the end of next excluded area
       
    50 	 */
       
    51 	private int nextExcludedEnd;
       
    52 
       
    53 	/**
       
    54 	 * Index of next character to be fetched
       
    55 	 */
       
    56 	private int nextIndex;
       
    57 
       
    58 	/**
       
    59 	 * Index of character returned by latest call to next
       
    60 	 */
       
    61 	private int currentIndex;
       
    62 
       
    63 	/**
       
    64 	 * Index of character returned by previous call to next
       
    65 	 */
       
    66 	private int previousIndex;
       
    67 
       
    68 	/**
       
    69 	 * Search flags
       
    70 	 */
       
    71 	private int flags;
       
    72 
       
    73 	/**
       
    74 	 * Constructor
       
    75 	 * 
       
    76 	 * @param parser
       
    77 	 *            source parser
       
    78 	 * @param startIndex
       
    79 	 *            the index where to start
       
    80 	 * @param flags
       
    81 	 *            the iterator flags
       
    82 	 */
       
    83 	SourceIterator(SourceParser parser, int startIndex, int flags) {
       
    84 		SourceDocumentInterface source = parser.getSource();
       
    85 		if (startIndex >= source.getLength()
       
    86 				&& ((flags & SourceParser.BACKWARD_SEARCH) != 0)) {
       
    87 			nextIndex = source.getLength() - 1;
       
    88 		} else {
       
    89 			nextIndex = startIndex;
       
    90 		}
       
    91 		this.parser = parser;
       
    92 		this.flags = flags;
       
    93 		if (hasNext()) {
       
    94 			boolean forward = (flags & SourceParser.BACKWARD_SEARCH) == 0;
       
    95 			nextExcludedIndex = parser.findExcludedAreaIndex(nextIndex);
       
    96 			if (nextExcludedIndex < 0) {
       
    97 				nextExcludedIndex = -1 - nextExcludedIndex;
       
    98 				if (forward) {
       
    99 					// Update increments the index, so it must be moved behind
       
   100 					// the start of search
       
   101 					nextExcludedIndex--;
       
   102 				}
       
   103 			}
       
   104 			// Increments / decrements the next excluded area according to
       
   105 			// search direction. If direction is backward, this decrements the
       
   106 			// index. In that case the above initialization has selected the
       
   107 			// index after the start of search index. If direction is forward,
       
   108 			// this increments the index.
       
   109 			updateExcludedIndex();
       
   110 			// After the excluded index has been set, the white spaces and
       
   111 			// comments are skipped
       
   112 			if (forward) {
       
   113 				forwardSeekNext();
       
   114 			} else {
       
   115 				backwardSeekNext();
       
   116 			}
       
   117 			previousIndex = startIndex;
       
   118 			currentIndex = startIndex;
       
   119 		}
       
   120 	}
       
   121 
       
   122 	/**
       
   123 	 * Determines if there are more characters to process
       
   124 	 * 
       
   125 	 * @return true if iterator has more characters
       
   126 	 */
       
   127 	public boolean hasNext() {
       
   128 		return (flags & SourceParser.BACKWARD_SEARCH) == 0 ? nextIndex < parser
       
   129 				.getSource().getLength() : nextIndex >= 0;
       
   130 	}
       
   131 
       
   132 	/**
       
   133 	 * Gets the next character from this iterator
       
   134 	 * 
       
   135 	 * @return the next character
       
   136 	 * @throws SourceParserException
       
   137 	 *             if there are no more characters
       
   138 	 */
       
   139 	public char next() throws SourceParserException {
       
   140 		char ret;
       
   141 		previousIndex = currentIndex;
       
   142 		currentIndex = nextIndex;
       
   143 		if ((flags & SourceParser.BACKWARD_SEARCH) == 0) {
       
   144 			ret = forwardNext();
       
   145 		} else {
       
   146 			ret = backwardNext();
       
   147 		}
       
   148 		return ret;
       
   149 	}
       
   150 
       
   151 	/**
       
   152 	 * Returns next character moving forward
       
   153 	 * 
       
   154 	 * @return the character
       
   155 	 * @throws SourceParserException
       
   156 	 *             if there are no more characters
       
   157 	 */
       
   158 	private char forwardNext() throws SourceParserException {
       
   159 		char c = parser.getSource().getChar(nextIndex);
       
   160 		nextIndex++;
       
   161 		forwardSeekNext();
       
   162 		return c;
       
   163 	}
       
   164 
       
   165 	/**
       
   166 	 * Skips to next index
       
   167 	 */
       
   168 	private void forwardSeekNext() {
       
   169 		// Skips over the excluded area if the index enters one
       
   170 		boolean didSkip;
       
   171 		SourceDocumentInterface source = parser.getSource();
       
   172 		try {
       
   173 			do {
       
   174 				didSkip = false;
       
   175 				if (nextIndex >= nextExcludedStart && nextExcludedStart != -1) {
       
   176 					// Skips if applicable. Otherwise just updates the next
       
   177 					// excluded
       
   178 					// area variables
       
   179 					if (isExcluded()) {
       
   180 						nextIndex = nextExcludedEnd;
       
   181 					}
       
   182 					updateExcludedIndex();
       
   183 				}
       
   184 				if ((flags & SourceParser.SKIP_WHITE_SPACES) != 0) {
       
   185 					// Skips over white spaces
       
   186 					boolean wspFound = true;
       
   187 					do {
       
   188 						// If a white space is skipped, the excluded area check
       
   189 						// needs to be done again. didSkip flag controls that
       
   190 						if (nextIndex < source.getLength()
       
   191 								&& Character.isWhitespace(source
       
   192 										.getChar(nextIndex))) {
       
   193 							nextIndex++;
       
   194 							didSkip = true;
       
   195 						} else {
       
   196 							wspFound = false;
       
   197 						}
       
   198 					} while (wspFound);
       
   199 				}
       
   200 			} while (didSkip);
       
   201 		} catch (SourceParserException e) {
       
   202 			// The exception must not be thrown out of this function
       
   203 		}
       
   204 	}
       
   205 
       
   206 	/**
       
   207 	 * Returns next character moving backward
       
   208 	 * 
       
   209 	 * @return the character
       
   210 	 * @throws SourceParserException
       
   211 	 *             if there are no more characters
       
   212 	 */
       
   213 	private char backwardNext() throws SourceParserException {
       
   214 		char c = parser.getSource().getChar(nextIndex);
       
   215 		nextIndex--;
       
   216 		backwardSeekNext();
       
   217 		return c;
       
   218 	}
       
   219 
       
   220 	/**
       
   221 	 * Skips to previous index
       
   222 	 */
       
   223 	private void backwardSeekNext() {
       
   224 		// Skips over the excluded area if the index enters one
       
   225 		boolean didSkip;
       
   226 		SourceDocumentInterface source = parser.getSource();
       
   227 		try {
       
   228 			do {
       
   229 				didSkip = false;
       
   230 				if (nextIndex <= nextExcludedEnd - 1) {
       
   231 					// Skips if applicable. Otherwise just updates the next
       
   232 					// excluded
       
   233 					// area variables
       
   234 					if (isExcluded()) {
       
   235 						nextIndex = nextExcludedStart - 1;
       
   236 					}
       
   237 					updateExcludedIndex();
       
   238 				}
       
   239 				if ((flags & SourceParser.SKIP_WHITE_SPACES) != 0) {
       
   240 					boolean wspFound = true;
       
   241 					do {
       
   242 						// If a white space is skipped, the excluded area check
       
   243 						// needs to be done again. didSkip flag controls that
       
   244 						if (nextIndex >= 0
       
   245 								&& Character.isWhitespace(source
       
   246 										.getChar(nextIndex))) {
       
   247 							nextIndex--;
       
   248 							didSkip = true;
       
   249 						} else {
       
   250 							wspFound = false;
       
   251 						}
       
   252 					} while (wspFound);
       
   253 				}
       
   254 			} while (didSkip);
       
   255 		} catch (SourceParserException e) {
       
   256 			// The exception must not be thrown out of this function
       
   257 		}
       
   258 	}
       
   259 
       
   260 	/**
       
   261 	 * Updates the excluded area index
       
   262 	 */
       
   263 	private void updateExcludedIndex() {
       
   264 		if ((flags & SourceParser.BACKWARD_SEARCH) == 0) {
       
   265 			nextExcludedIndex++;
       
   266 		} else {
       
   267 			nextExcludedIndex--;
       
   268 		}
       
   269 		// Updates the values using the next excluded area
       
   270 		if (nextExcludedIndex >= 0
       
   271 				&& nextExcludedIndex < parser.getExcludedAreas().size()) {
       
   272 			SourceExcludedArea p = parser.getExcludedAreas().get(
       
   273 					nextExcludedIndex);
       
   274 			nextExcludedStart = p.getOffset();
       
   275 			nextExcludedEnd = p.getOffset() + p.getLength();
       
   276 			nextExcludedAreaType = p.getType();
       
   277 		} else {
       
   278 			nextExcludedStart = -1;
       
   279 			nextExcludedEnd = -1;
       
   280 		}
       
   281 	}
       
   282 
       
   283 	/**
       
   284 	 * Returns the index where the next character will be fetched
       
   285 	 * 
       
   286 	 * @return the index
       
   287 	 */
       
   288 	public int nextIndex() {
       
   289 		return nextIndex;
       
   290 	}
       
   291 
       
   292 	/**
       
   293 	 * Gets the index of the character returned by last call to next
       
   294 	 * 
       
   295 	 * @return the index
       
   296 	 */
       
   297 	public int currentIndex() {
       
   298 		return currentIndex;
       
   299 	}
       
   300 
       
   301 	/**
       
   302 	 * Gets the index that preceeded the latest call to next
       
   303 	 * 
       
   304 	 * @return the index
       
   305 	 */
       
   306 	public int previousIndex() {
       
   307 		return previousIndex;
       
   308 	}
       
   309 
       
   310 	/**
       
   311 	 * Gets the next character but does not move the iterator
       
   312 	 * 
       
   313 	 * @return the next character
       
   314 	 * @throws SourceParserException
       
   315 	 *             if there are no more characters
       
   316 	 */
       
   317 	public char peek() throws SourceParserException {
       
   318 		return parser.getSource().getChar(nextIndex);
       
   319 	}
       
   320 
       
   321 	/**
       
   322 	 * Determines if the iterator skipped over characters during last call to
       
   323 	 * next
       
   324 	 * 
       
   325 	 * @return true if skipped, false otherwise
       
   326 	 */
       
   327 	public boolean hasSkipped() {
       
   328 		return (flags & SourceParser.BACKWARD_SEARCH) == 0 ? currentIndex > previousIndex + 1
       
   329 				: currentIndex < previousIndex - 1;
       
   330 	}
       
   331 
       
   332 	/**
       
   333 	 * Checks if the next area is skipped
       
   334 	 * 
       
   335 	 * @return true is skipped
       
   336 	 */
       
   337 	private boolean isExcluded() {
       
   338 		return isExcluded(nextExcludedAreaType);
       
   339 	}
       
   340 
       
   341 	/**
       
   342 	 * Checks if the given type is skipped
       
   343 	 * 
       
   344 	 * @param type
       
   345 	 *            the type
       
   346 	 * @return true is skipped
       
   347 	 */
       
   348 	private boolean isExcluded(int type) {
       
   349 		return SourceParser.isExcluded(type, flags);
       
   350 	}
       
   351 
       
   352 }