java.util.ArrayDeque#push ( )源码实例Demo

下面列出了java.util.ArrayDeque#push ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: apiman   文件: HeaderMapDeserializer.java
/**
 * @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext)
 */
@Override
public HeaderMap deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    HeaderMap map = new HeaderMap();

    while (p.nextToken() != JsonToken.END_OBJECT) {
        String name = p.getCurrentName();

        p.nextToken();

        if (p.currentToken().isScalarValue()) {
            map.add(name, p.getValueAsString());
        } else {
            ArrayDeque<String> values = new ArrayDeque<>();
            while (p.nextToken() != JsonToken.END_ARRAY) {
                values.push(p.getValueAsString());
            }
            values.forEach(value -> map.add(name, value));
        }
    }
    return map;
}
 
源代码2 项目: buck   文件: AbstractSkylarkFileParser.java
/**
 * Updates extension load state with the list of its dependencies, and schedules any unsatisfied
 * dependencies to be loaded by adding those dependencies to the work queue.
 *
 * @param load {@link ExtensionLoadState} representing extension currently loaded
 * @param queue a work queue of extensions that still need to be loaded.
 * @return true if this extension has any unsatisfied dependencies
 */
private boolean processExtensionDependencies(
    ExtensionLoadState load, ArrayDeque<ExtensionLoadState> queue) {
  // Update this load state with the list of its dependencies.
  // Schedule missing dependencies to be loaded.
  boolean haveUnsatisfiedDeps = false;
  for (int i = 0; i < load.getAST().getImports().size(); ++i) {
    LoadImport dependency =
        ImmutableLoadImport.of(load.getLabel(), load.getAST().getImports().get(i));

    // Record dependency for this load.
    load.addDependency(dependency);
    com.google.devtools.build.lib.vfs.Path extensionPath =
        getImportPath(dependency.getLabel(), dependency.getImport());
    if (extensionDataCache.getIfPresent(extensionPath) == null) {
      // Schedule dependency to be loaded if needed.
      haveUnsatisfiedDeps = true;
      queue.push(new ExtensionLoadState(dependency, extensionPath));
    }
  }
  return haveUnsatisfiedDeps;
}
 
源代码3 项目: civcraft   文件: CivCraftUpdateTask.java
/**
 * Find all contiguous blocks, set in target and clear in source
 */
private int floodFillTarget(TileFlags src, TileFlags dest, int x, int y) {
    int cnt = 0;
    ArrayDeque<int[]> stack = new ArrayDeque<int[]>();
    stack.push(new int[] { x, y });
    
    while(stack.isEmpty() == false) {
        int[] nxt = stack.pop();
        x = nxt[0];
        y = nxt[1];
        if(src.getFlag(x, y)) { /* Set in src */
            src.setFlag(x, y, false);   /* Clear source */
            dest.setFlag(x, y, true);   /* Set in destination */
            cnt++;
            if(src.getFlag(x+1, y))
                stack.push(new int[] { x+1, y });
            if(src.getFlag(x-1, y))
                stack.push(new int[] { x-1, y });
            if(src.getFlag(x, y+1))
                stack.push(new int[] { x, y+1 });
            if(src.getFlag(x, y-1))
                stack.push(new int[] { x, y-1 });
        }
    }
    return cnt;
}
 
源代码4 项目: openjdk-jdk9   文件: CallSite.java
/**
 * Locate a late inline call site: find, in this instance's
 * {@linkplain #calls call sites}, the one furthest down the given call
 * stack.
 *
 * Multiple chains of identical call sites with the same method name / bci
 * combination are possible, so we have to try them all until we find the
 * late inline call site that has a matching inline ID.
 *
 * @return a matching call site, or {@code null} if none was found.
 */
public CallSite findCallSite(ArrayDeque<CallSite> sites) {
    if (calls == null) {
        return null;
    }
    CallSite site = sites.pop();
    for (CallSite c : calls) {
        if (c.matches(site)) {
            if (!sites.isEmpty()) {
                CallSite res = c.findCallSite(sites);
                if (res != null) {
                    sites.push(site);
                    return res;
                }
            } else {
                sites.push(site);
                return c;
            }
        }
    }
    sites.push(site);
    return null;
}
 
源代码5 项目: AsteroidOSSync   文件: DebugLogger.java
/**
 * Return a {@link List} with the last count of log statements. If there haven't been any yet, an empty list is returned.
 */
public final List<String> getLastLogs(int count)
{
    if (count > m_logList.size())
    {
        count = m_logList.size();
    }
    if (m_logList.size() == 0)
    {
        return new ArrayList<>(0);
    }
    else
    {
        final ArrayDeque<String> list = new ArrayDeque<>(count);
        count--;
        int start = m_logList.size() - 1;
        int end = start - count;
        for (int i = start; i >= end; i--)
        {

            list.push(m_logList.get(i));
        }
        return new ArrayList<>(list);
    }
}
 
源代码6 项目: EasyMPermission   文件: JavacResolution.java
public Map<JCTree, JCTree> resolveMethodMember(JavacNode node) {
	ArrayDeque<JCTree> stack = new ArrayDeque<JCTree>();
	
	{
		JavacNode n = node;
		while (n != null) {
			stack.push(n.get());
			n = n.up();
		}
	}
	
	messageSuppressor.disableLoggers();
	try {
		EnvFinder finder = new EnvFinder(node.getContext());
		while (!stack.isEmpty()) stack.pop().accept(finder);
		
		TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker(), node.getContext());
		JCTree copy = mirrorMaker.copy(finder.copyAt());
		
		memberEnterAndAttribute(copy, finder.get(), node.getContext());
		return mirrorMaker.getOriginalToCopyMap();
	} finally {
		messageSuppressor.enableLoggers();
	}
}
 
源代码7 项目: EasyMPermission   文件: JavacResolution.java
public void resolveClassMember(JavacNode node) {
	ArrayDeque<JCTree> stack = new ArrayDeque<JCTree>();
	
	{
		JavacNode n = node;
		while (n != null) {
			stack.push(n.get());
			n = n.up();
		}
	}
	
	messageSuppressor.disableLoggers();
	try {
		EnvFinder finder = new EnvFinder(node.getContext());
		while (!stack.isEmpty()) stack.pop().accept(finder);
		
		attrib(node.get(), finder.get());
	} finally {
		messageSuppressor.enableLoggers();
	}
}
 
/**
 * Returns the list of tables that one must process before processing the provided {@code table}.
 *
 * @param table The table that you wish to process
 * @return the ordered {@link ArrayDeque} of tables to process before processing {@code table}
 */
public Collection<Table> getDependentTables(Table table) {
  ArrayDeque<Table> tableStack = new ArrayDeque<>();
  while (table != null && !processedTables.contains(table)) {
    tableStack.push(table);
    processedTables.add(table);

    table = tableDependencies.get(table);
  }

  return tableStack;
}
 
源代码9 项目: netbeans   文件: VariousUtils.java
private static void createVariableBaseChain(VariableBase node, ArrayDeque<VariableBase> stack) {
    stack.push(node);
    if (node instanceof MethodInvocation) {
        createVariableBaseChain(((MethodInvocation) node).getDispatcher(), stack);
    } else if (node instanceof FieldAccess) {
        createVariableBaseChain(((FieldAccess) node).getDispatcher(), stack);
    } else if (node instanceof StaticDispatch) {
        Expression dispatcher = ((StaticDispatch) node).getDispatcher();
        if (dispatcher instanceof VariableBase) {
            createVariableBaseChain((VariableBase) dispatcher, stack);
        }
    }
}
 
源代码10 项目: buck   文件: AbstractSkylarkFileParser.java
/**
 * Creates an extension from a {@code path}.
 *
 * @param loadImport an import label representing an extension to load.
 */
private ExtensionData loadExtension(LoadImport loadImport)
    throws IOException, BuildFileParseException, InterruptedException {
  ExtensionData extension = null;
  ArrayDeque<ExtensionLoadState> work = new ArrayDeque<>();
  work.push(
      new ExtensionLoadState(
          loadImport, getImportPath(loadImport.getLabel(), loadImport.getImport())));

  while (!work.isEmpty()) {
    ExtensionLoadState load = work.peek();
    extension =
        lookupExtensionForImport(load.getPath(), load.getSkylarkImport().getImportString());

    if (extension != null) {
      // It's possible that some lower level dependencies already loaded
      // this work item.  We're done with it, so pop the queue.
      work.pop();
      continue;
    }

    // Load BuildFileAST if needed.
    boolean astLoaded = maybeLoadAST(load);
    boolean haveUnsatisfiedDeps = astLoaded && processExtensionDependencies(load, work);

    // NB: If we have unsatisfied dependencies, we don't do anything;
    // more importantly we do not pop the work queue in this case.
    // This load is kept on the queue until all of its dependencies are satisfied.

    if (!haveUnsatisfiedDeps) {
      // We are done with this load; build it and cache it.
      work.removeFirst();
      extension = buildExtensionData(load);
      extensionDataCache.put(load.getPath(), extension);
    }
  }

  Preconditions.checkNotNull(extension);
  return extension;
}
 
源代码11 项目: openjdk-jdk9   文件: ArrayDequeTest.java
/**
 * push(null) throws NPE
 */
public void testPushNull() {
    ArrayDeque q = new ArrayDeque(1);
    try {
        q.push(null);
        shouldThrow();
    } catch (NullPointerException success) {}
}
 
源代码12 项目: Logistics-Pipes-2   文件: DijkstraRouter.java
private void pushToRouteUntillParent(NetworkNode current, ArrayDeque<Tuple<UUID, EnumFacing>> route) throws InterruptedException {
	NetworkNode parent = current.parent.getKey();
	EnumFacing direction = current.parent.getVal();
	int parentDirection = direction.getOpposite().getIndex();

	NetworkNode help = current;
	while(help.getId() != parent.getId()) {
		help = help.getNeighborAt(parentDirection);
		route.push(new Tuple<UUID, EnumFacing>(help.getId(), direction));
		//help.getMember().spawnParticle(1.0f, 0.549f, 0.0f);
		Thread.sleep(120);
	}
}
 
源代码13 项目: keycloak   文件: FormattingXMLStreamWriter.java
@Override
public void setUnspecifiedElementNamespace(final String namespace) {
    ArrayDeque<String> namespaces = this.unspecifiedNamespaces;
    namespaces.pop();
    namespaces.push(namespace == null ? NO_NAMESPACE : namespace);
}
 
源代码14 项目: PyramidShader   文件: DepressionFillOperator.java
private void fillDep(Grid grid) {
    final int nbrCols = grid.getCols();
    final int nbrRows = grid.getRows();

    // flag for each grid cell to indicate whether it has been treated
    BitSet closed = new BitSet(nbrCols * nbrRows);

    // count the number of processed cells for the progress indicator
    int nbrCellsProcessed = 0;

    // plain queue
    final int expectedMaxPlainSize = grid.getCols();
    ArrayDeque<Cell> pit = new ArrayDeque(expectedMaxPlainSize);

    // priority queue with cells ordered by elevation. Lowest elevation is 
    // the head of the queue.
    PriorityQueue<Cell> open = new PriorityQueue(nbrCols * 2 + nbrRows * 2);

    // add edge cells and void cells to priority queue
    for (int row = 0; row < nbrRows && reportProgress(0); row++) {
        for (int col = 0; col < nbrCols; col++) {
            if (grid.isVoid(col, row)) {
                continue;
            }
            if (isCellOnGridBorder(grid, col, row)) {
                closed.set(col + row * nbrCols);
                open.add(new Cell(col, row, grid.getValue(col, row)));
            }
        }
    }

    while (!open.isEmpty() || !pit.isEmpty()) {
        // either consider the point with the lowest elevation in the queue
        // or consider a point in/near a "pit" which is being filled
        final Cell c = !pit.isEmpty() ? pit.pop() : open.poll();
        ++nbrCellsProcessed;

        // look at neighbours of c
        for (int i = 1; i <= 8; i++) {
            final int nRow = c.row + DY[i];
            final int nCol = c.col + DX[i];

            // ensure neighbour is within the bounds of the grid
            if (nRow < 0 || nCol < 0 || nRow >= nbrRows || nCol >= nbrCols) {
                continue;
            }
            // ensure we haven't visited the cell yet
            if (closed.get(nCol + nbrCols * nRow)) {
                continue;
            }

            closed.set(nCol + nbrCols * nRow);
            final float n = grid.getValue(nCol, nRow);

            // ensure the cell is valid
            if (Float.isNaN(n)) {
                continue;
            }

            // if the current elevation is greater than the neighbour
            // we are entering a depression therefore we add to the 
            // plain queue otherwise, add to the open queue
            if (n <= c.elevation) {
                if (n < c.elevation) {
                    // found a cell in a pit
                    grid.setValue(c.elevation, nCol, nRow);
                }
                pit.push(new Cell(nCol, nRow, c.elevation));
            } else {
                open.add(new Cell(nCol, nRow, n));
            }
        }

        if (nbrCellsProcessed % 50000 == 0) {
            if (!reportProgress(100f * nbrCellsProcessed / (nbrCols * nbrRows))) {
                return;
            }
        }
    }
}
 
源代码15 项目: Telegram-FOSS   文件: WebvttCueParser.java
/**
 * Parses the text payload of a WebVTT Cue and applies modifications on {@link WebvttCue.Builder}.
 *
 * @param id Id of the cue, {@code null} if it is not present.
 * @param markup The markup text to be parsed.
 * @param styles List of styles defined by the CSS style blocks preceeding the cues.
 * @param builder Output builder.
 */
/* package */ static void parseCueText(String id, String markup, WebvttCue.Builder builder,
    List<WebvttCssStyle> styles) {
  SpannableStringBuilder spannedText = new SpannableStringBuilder();
  ArrayDeque<StartTag> startTagStack = new ArrayDeque<>();
  List<StyleMatch> scratchStyleMatches = new ArrayList<>();
  int pos = 0;
  while (pos < markup.length()) {
    char curr = markup.charAt(pos);
    switch (curr) {
      case CHAR_LESS_THAN:
        if (pos + 1 >= markup.length()) {
          pos++;
          break; // avoid ArrayOutOfBoundsException
        }
        int ltPos = pos;
        boolean isClosingTag = markup.charAt(ltPos + 1) == CHAR_SLASH;
        pos = findEndOfTag(markup, ltPos + 1);
        boolean isVoidTag = markup.charAt(pos - 2) == CHAR_SLASH;
        String fullTagExpression = markup.substring(ltPos + (isClosingTag ? 2 : 1),
            isVoidTag ? pos - 2 : pos - 1);
        String tagName = getTagName(fullTagExpression);
        if (tagName == null || !isSupportedTag(tagName)) {
          continue;
        }
        if (isClosingTag) {
          StartTag startTag;
          do {
            if (startTagStack.isEmpty()) {
              break;
            }
            startTag = startTagStack.pop();
            applySpansForTag(id, startTag, spannedText, styles, scratchStyleMatches);
          } while(!startTag.name.equals(tagName));
        } else if (!isVoidTag) {
          startTagStack.push(StartTag.buildStartTag(fullTagExpression, spannedText.length()));
        }
        break;
      case CHAR_AMPERSAND:
        int semiColonEndIndex = markup.indexOf(CHAR_SEMI_COLON, pos + 1);
        int spaceEndIndex = markup.indexOf(CHAR_SPACE, pos + 1);
        int entityEndIndex = semiColonEndIndex == -1 ? spaceEndIndex
            : (spaceEndIndex == -1 ? semiColonEndIndex
                : Math.min(semiColonEndIndex, spaceEndIndex));
        if (entityEndIndex != -1) {
          applyEntity(markup.substring(pos + 1, entityEndIndex), spannedText);
          if (entityEndIndex == spaceEndIndex) {
            spannedText.append(" ");
          }
          pos = entityEndIndex + 1;
        } else {
          spannedText.append(curr);
          pos++;
        }
        break;
      default:
        spannedText.append(curr);
        pos++;
        break;
    }
  }
  // apply unclosed tags
  while (!startTagStack.isEmpty()) {
    applySpansForTag(id, startTagStack.pop(), spannedText, styles, scratchStyleMatches);
  }
  applySpansForTag(id, StartTag.buildWholeCueVirtualTag(), spannedText, styles,
      scratchStyleMatches);
  builder.setText(spannedText);
}
 
源代码16 项目: doov   文件: AstHtmlRenderer.java
private void toHtml(Metadata metadata, ArrayDeque<Metadata> parents) {
        parents.push(metadata);
        try {
            switch (metadata.type()) {
                case RULE:
                    rule(metadata, parents);
                    break;
                case WHEN:
                    when(metadata, parents);
                    break;
                case BINARY_PREDICATE:
                case TEMPLATE_PARAM:
                    binary(metadata, parents);
                    break;
                case LEAF_PREDICATE:
                case FIELD_PREDICATE:
                case LEAF_VALUE:
                case MAPPING_LEAF:
                case TEMPLATE_IDENTIFIER:
                    leaf(metadata, parents);
                    break;
                case MAPPING_LEAF_ITERABLE:
                    iterable(metadata, parents);
                    break;
                case TYPE_CONVERTER:
                    typeConverter(metadata, parents);
                    break;
                case UNARY_PREDICATE:
                    unary(metadata, parents);
                    break;
                case NARY_PREDICATE:
                case MULTIPLE_MAPPING:
                case THEN_MAPPING:
                case ELSE_MAPPING:
                    nary(metadata, parents);
                    break;
                case MAPPING_INPUT:
                    mappingInput(metadata, parents);
                    break;
                case FIELD_PREDICATE_MATCH_ANY:
                    iterable(metadata, parents);
//                    fieldMatchAny(metadata, parents);
                    break;
                case SINGLE_MAPPING:
                    singleMapping(metadata, parents);
                    break;
                default:
                    throw new IllegalStateException(metadata.type().name());
            }
        } finally {
            parents.pop();
        }
    }
 
源代码17 项目: dfalex   文件: DfaAuxiliaryInformation.java
/**
 * Perform a depth first search of all states, starting at the start states
 * <P>
 * To avoid stack overflow errors on large DFAs, the implementation uses an auxiliary
 * stack on the heap instead of recursing
 * 
 * @param onEnter  called with (parent, child) when a child is entered.  parent == null for roots.
 * @param onSkip  called with (parent, child) when a child is skipped because it has been entered
 *                  previously.  parent == null for roots.
 * @param onLeave  called with (parent, child) when a child is exited.  parent == null for roots.
 */
public void depthFirstSearch(
        BiConsumer<DfaState<MATCHRESULT>, DfaState<MATCHRESULT>> onEnter,
        BiConsumer<DfaState<MATCHRESULT>, DfaState<MATCHRESULT>> onSkip,
        BiConsumer<DfaState<MATCHRESULT>, DfaState<MATCHRESULT>> onLeave)
{
    @SuppressWarnings("unchecked")
    final Iterator<DfaState<MATCHRESULT>>[] iterators = 
        (Iterator<DfaState<MATCHRESULT>>[]) new Iterator<?>[getStatesByNumber().size()];
    final ArrayDeque<DfaState<MATCHRESULT>> stack = new ArrayDeque<>();
    for (int rootIndex = 0; rootIndex < m_startStates.size(); ++rootIndex)
    {
        DfaState<MATCHRESULT> st = m_startStates.get(rootIndex);
        if (iterators[st.getStateNumber()] != null)
        {
            onSkip.accept(null, st);
            continue;
        }
        iterators[st.getStateNumber()] = st.getSuccessorStates().iterator();
        stack.push(st);
        onEnter.accept(null, st);
        for (;;)
        {
            //process the next child of the stack top
            st = stack.peek();
            final int sti = st.getStateNumber();
            final Iterator<DfaState<MATCHRESULT>> iter = iterators[sti];
            if (iter.hasNext())
            {
                final DfaState<MATCHRESULT> child = iter.next();
                if (child == null)
                {
                    //shouldn't happen, but if it does get the next child
                    continue;
                }
                final int childi = child.getStateNumber();
                if (iterators[childi] != null)
                {
                    onSkip.accept(st, child);
                }
                else
                {
                    iterators[childi] = child.getSuccessorStates().iterator();
                    stack.push(child);
                    onEnter.accept(st, child);
                }
            }
            else
            {
                //top element is done
                stack.pop();
                if (stack.isEmpty())
                {
                    onLeave.accept(null, st);
                    break;
                }
                onLeave.accept(stack.peek(), st);
            }
        }
    }
}
 
源代码18 项目: JWebAssembly   文件: BranchManger.java
/**
 * Calculate the block type. The value type that is on the stack after the block.
 * 
 * @param instructions
 *            the instructions of the function
 */
void calculateBlockType( List<WasmInstruction> instructions ) {
    for( int i = size() - 1; i >= 0; i-- ) {
        BranchNode branch = get( i );
        branch.calculateBlockType( instructions );
    }

    if( startBlock != null && startBlock.getOperation() == WasmBlockOperator.IF ) {
        try {
            ArrayDeque<AnyType> stack = new ArrayDeque<>();
            stack.push( ValueType.empty );
            INSTRUCTIONS: for( int i = startIdx; i < instructions.size(); i++ ) {
                WasmInstruction instr = instructions.get( i );
                int codePos = instr.getCodePosition();
                if( codePos >= endPos ) {
                    break;
                }
                int popCount = instr.getPopCount();
                for( int p = 0; p < popCount; p++ ) {
                    stack.pop();
                }
                AnyType pushValue = instr.getPushValueType();
                if( pushValue != null ) {
                    stack.push( pushValue );
                }

                if( instr.getType() == Type.Block ) {
                    switch( ((WasmBlockInstruction)instr).getOperation() ) {
                        case RETURN:
                            // set "empty" block type
                            while( stack.size() > 1 ) {
                                stack.pop();
                            }
                            break INSTRUCTIONS;
                        case IF:
                        case BLOCK:
                        case LOOP:
                        case TRY:
                            // skip the content of the block, important to not count ELSE blocks
                            i = findEndInstruction( instructions, i );
                            break;
                    }
                }
            }
            startBlock.setData( stack.pop() );
        } catch( Throwable th ) {
            throw WasmException.create( th, startBlock.getLineNumber() );
        }
    }
}
 
源代码19 项目: ignite   文件: TxDeadlockDetection.java
/**
 * @param wfg Wait-for-graph.
 * @param txId Tx ID - start vertex for cycle search in graph.
 */
static List<GridCacheVersion> findCycle(Map<GridCacheVersion, Set<GridCacheVersion>> wfg, GridCacheVersion txId) {
    if (wfg == null || wfg.isEmpty())
        return null;

    ArrayDeque<GridCacheVersion> stack = new ArrayDeque<>();
    Set<GridCacheVersion> inPath = new HashSet<>();
    Set<GridCacheVersion> visited = new HashSet<>();
    Map<GridCacheVersion, GridCacheVersion> edgeTo = new HashMap<>();

    stack.push(txId);

    while (!stack.isEmpty()) {
        GridCacheVersion v = stack.peek();

        if (visited.contains(v)) {
            stack.pop();
            inPath.remove(v);

            continue;
        }

        visited.add(v);

        Set<GridCacheVersion> children = wfg.get(v);

        if (children == null || children.isEmpty()) {
            stack.pop();
            inPath.remove(v);

            continue;
        }

        inPath.add(v);

        for (GridCacheVersion w : children) {
            if (inPath.contains(w) && visited.contains(w)) {
                List<GridCacheVersion> cycle = new ArrayList<>();

                for (GridCacheVersion x = v; !x.equals(w); x = edgeTo.get(x))
                    cycle.add(x);

                cycle.add(w);
                cycle.add(v);

                return cycle;
            }

            edgeTo.put(w, v);
            stack.push(w);
        }
    }

    return null;
}
 
源代码20 项目: Telegram   文件: WebvttCueParser.java
/**
 * Parses the text payload of a WebVTT Cue and applies modifications on {@link WebvttCue.Builder}.
 *
 * @param id Id of the cue, {@code null} if it is not present.
 * @param markup The markup text to be parsed.
 * @param styles List of styles defined by the CSS style blocks preceeding the cues.
 * @param builder Output builder.
 */
/* package */ static void parseCueText(String id, String markup, WebvttCue.Builder builder,
    List<WebvttCssStyle> styles) {
  SpannableStringBuilder spannedText = new SpannableStringBuilder();
  ArrayDeque<StartTag> startTagStack = new ArrayDeque<>();
  List<StyleMatch> scratchStyleMatches = new ArrayList<>();
  int pos = 0;
  while (pos < markup.length()) {
    char curr = markup.charAt(pos);
    switch (curr) {
      case CHAR_LESS_THAN:
        if (pos + 1 >= markup.length()) {
          pos++;
          break; // avoid ArrayOutOfBoundsException
        }
        int ltPos = pos;
        boolean isClosingTag = markup.charAt(ltPos + 1) == CHAR_SLASH;
        pos = findEndOfTag(markup, ltPos + 1);
        boolean isVoidTag = markup.charAt(pos - 2) == CHAR_SLASH;
        String fullTagExpression = markup.substring(ltPos + (isClosingTag ? 2 : 1),
            isVoidTag ? pos - 2 : pos - 1);
        String tagName = getTagName(fullTagExpression);
        if (tagName == null || !isSupportedTag(tagName)) {
          continue;
        }
        if (isClosingTag) {
          StartTag startTag;
          do {
            if (startTagStack.isEmpty()) {
              break;
            }
            startTag = startTagStack.pop();
            applySpansForTag(id, startTag, spannedText, styles, scratchStyleMatches);
          } while(!startTag.name.equals(tagName));
        } else if (!isVoidTag) {
          startTagStack.push(StartTag.buildStartTag(fullTagExpression, spannedText.length()));
        }
        break;
      case CHAR_AMPERSAND:
        int semiColonEndIndex = markup.indexOf(CHAR_SEMI_COLON, pos + 1);
        int spaceEndIndex = markup.indexOf(CHAR_SPACE, pos + 1);
        int entityEndIndex = semiColonEndIndex == -1 ? spaceEndIndex
            : (spaceEndIndex == -1 ? semiColonEndIndex
                : Math.min(semiColonEndIndex, spaceEndIndex));
        if (entityEndIndex != -1) {
          applyEntity(markup.substring(pos + 1, entityEndIndex), spannedText);
          if (entityEndIndex == spaceEndIndex) {
            spannedText.append(" ");
          }
          pos = entityEndIndex + 1;
        } else {
          spannedText.append(curr);
          pos++;
        }
        break;
      default:
        spannedText.append(curr);
        pos++;
        break;
    }
  }
  // apply unclosed tags
  while (!startTagStack.isEmpty()) {
    applySpansForTag(id, startTagStack.pop(), spannedText, styles, scratchStyleMatches);
  }
  applySpansForTag(id, StartTag.buildWholeCueVirtualTag(), spannedText, styles,
      scratchStyleMatches);
  builder.setText(spannedText);
}