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