/** *Searchthegivencharacter,Ifitwasfound,thenmarkthecurrentcursor *andthecursorpointtonextcharacter.
*/ privateBoolean indexOf(char c, Mark mark) { if (!hasMoreInput()) { returnnull;
}
int end = current.stream.length; int ch; int line = current.line; int col = current.col; int i = current.cursor; for(; i < end; i ++) {
ch = current.stream[i];
if (ch == c) {
mark.update(i, line, col);
} if (ch == '\n') {
line++;
col = 0;
} else {
col++;
} if (ch == c) {
current.update(i+1, line, col); returnBoolean.TRUE;
}
}
current.update(i, line, col); returnBoolean.FALSE;
}
/** *searchthestreamforamatchtoastring *@paramstringThestringtomatch *@return<strong>true</strong>isoneisfound,thecurrentposition *instreamispositionedafterthesearchstring,<strong> *false</strong>otherwise,positioninstreamunchanged.
*/ boolean matches(String string) { int len = string.length(); int cursor = current.cursor; int streamSize = current.stream.length; if (cursor + len < streamSize) { //Try to scan in memory int line = current.line; int col = current.col; int ch; int i = 0; for(; i < len; i ++) {
ch = current.stream[i+cursor]; if (string.charAt(i) != ch) { returnfalse;
} if (ch == '\n') {
line ++;
col = 0;
} else {
col++;
}
}
current.update(i+cursor, line, col);
} else {
Mark mark = mark(); int ch = 0; int i = 0; do {
ch = nextChar(); if (((char) ch) != string.charAt(i++)) {
setCurrent(mark); returnfalse;
}
} while (i < len);
} returntrue;
}
boolean matchesETag(String tagName) {
Mark mark = mark();
if (!matches("</" + tagName)) { returnfalse;
}
skipSpaces(); if (nextChar() == '>') { returntrue;
}
setCurrent(mark); returnfalse;
}
boolean matchesETagWithoutLessThan(String tagName) {
Mark mark = mark();
if (!matches("/" + tagName)) { returnfalse;
}
skipSpaces(); if (nextChar() == '>') { returntrue;
}
setCurrent(mark); returnfalse;
}
/** *Looksaheadtoseeifthereareoptionalspacesfollowedby *thegivenString.Ifso,trueisreturnedandthosespacesand *charactersareskipped.Ifnot,falseisreturnedandthe *positionisrestoredtowherewewerebefore.
*/ boolean matchesOptionalSpacesFollowedBy(String s) {
Mark mark = mark();
skipSpaces(); boolean result = matches( s ); if( !result ) {
setCurrent(mark);
}
return result;
}
int skipSpaces() { int i = 0; while (hasMoreInput() && isSpace()) {
i++;
nextChar();
} return i;
}
/** *Skipuntilthegivenstringismatchedinthestream. *Whenreturned,thecontextispositionedpasttheendofthematch. * *@paramlimitTheStringtomatch. *@returnAnon-null<code>Mark</code>instance(positionedimmediately *beforethesearchstring)iffound,<strong>null</strong> *otherwise.
*/
Mark skipUntil(String limit) {
Mark ret = mark(); int limlen = limit.length(); char firstChar = limit.charAt(0); Boolean result = null;
Mark restart = null;
skip: while((result = indexOf(firstChar, ret)) != null) { if (result.booleanValue()) { if (restart != null) {
restart.init(current, true);
} else {
restart = mark();
} for (int i = 1 ; i < limlen ; i++) { if (peekChar() == limit.charAt(i)) {
nextChar();
} else {
current.init(restart, true); continue skip;
}
} return ret;
}
} returnnull;
}
/** *Skipuntilthegivenstringismatchedinthestream,butignoring *charsinitiallyescapedbya'\'andanyELexpressions. *Whenreturned,thecontextispositionedpasttheendofthematch. * *@paramlimitTheStringtomatch. *@paramignoreEL<code>true</code>ifsomethingthatlookslikeELshould *notbetreatedasEL. *@returnAnon-null<code>Mark</code>instance(positionedimmediately *beforethesearchstring)iffound,<strong>null</strong> *otherwise.
*/
Mark skipUntilIgnoreEsc(String limit, boolean ignoreEL) {
Mark ret = mark(); int limlen = limit.length(); int ch; int prev = 'x'; // Doesn't matter char firstChar = limit.charAt(0);
skip: for (ch = nextChar(ret) ; ch != -1 ; prev = ch, ch = nextChar(ret)) { if (ch == '\\' && prev == '\\') {
ch = 0; // Double \ is not an escape char anymore
} elseif (prev == '\\') { continue;
} elseif (!ignoreEL && (ch == '$' || ch == '#') && peekChar() == '{' ) { // Move beyond the '{'
nextChar();
skipELExpression();
} elseif (ch == firstChar) { for (int i = 1 ; i < limlen ; i++) { if (peekChar() == limit.charAt(i)) {
nextChar();
} else { continue skip;
}
} return ret;
}
} returnnull;
}
/** *Skipuntilthegivenendtagismatchedinthestream. *Whenreturned,thecontextispositionedpasttheendofthetag. * *@paramtagThenameofthetagwhoseETag(</tag>)tomatch. *@returnAnon-null<code>Mark</code>instance(positionedimmediately *beforetheETag)iffound,<strong>null</strong>otherwise.
*/
Mark skipUntilETag(String tag) {
Mark ret = skipUntil("</" + tag); if (ret != null) {
skipSpaces(); if (nextChar() != '>') {
ret = null;
}
} return ret;
}
/** *ParseELExpressionBodythatisabodyof${}or#{}expression.Initial *readerpositionisexpectedtobejustafter'${'or'#{'characters. *<p> *Incaseofsuccess,thismethodreturns<code>Mark</code>forthelast *characterbeforetheterminating'}'andreaderispositionedjustafter *the'}'character.Ifnoterminating'}'isencountered,thismethod *returns<code>null</code>. *<p> *StartingwithEL3.0,nestedpaired{}saresupported. * *@returnMarkforthelastcharacterofELexpressionor<code>null</code>
*/
Mark skipELExpression() { // ELExpressionBody. // Starts with "#{" or "${". Ends with "}". // May contain quoted "{", "}", '{', or '}' and nested "{...}"
Mark last = mark(); boolean singleQuoted = false; boolean doubleQuoted = false; int nesting = 0; int currentChar; do {
currentChar = nextChar(last); while (currentChar == '\\' && (singleQuoted || doubleQuoted)) { // skip character following '\' within quotes // No need to update 'last', as neither of these characters // can be the closing '}'.
nextChar();
currentChar = nextChar();
} if (currentChar == -1) { returnnull;
} if (currentChar == '"' && !singleQuoted) {
doubleQuoted = !doubleQuoted;
} elseif (currentChar == '\'' && !doubleQuoted) {
singleQuoted = !singleQuoted;
} elseif (currentChar == '{' && !doubleQuoted && !singleQuoted) {
nesting++;
} elseif (currentChar =='}' && !doubleQuoted && !singleQuoted) { // Note: This also matches the terminating '}' at which point // nesting will be set to -1 - hence the test for // while (currentChar != '}' || nesting > -1 ||...) below // to continue the loop until the final '}' is detected
nesting--;
}
} while (currentChar != '}' || singleQuoted || doubleQuoted || nesting > -1);
return last;
}
finalboolean isSpace() { // Note: If this logic changes, also update Node.TemplateText.rtrim() return peekChar() <= ' ';
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.