inputentity.java
来自「java jdk 1.4的源码」· Java 代码 · 共 1,110 行 · 第 1/2 页
JAVA
1,110 行
// otherwise any "]]>" would be buffered, and we can // see right away if that's what we have default: if (buf [last + 1] == ']' && buf [last + 2] == '>') fatal ("P-072", null); continue; } } // correctly paired surrogates are OK if (c >= 0xd800 && c <= 0xdfff) { if ((last + 1) >= finish) { if (last > first) { validator.text (); contentHandler.characters (buf, first, last - first); sawContent = true; start = last + 1; } if (isEOF ()) { // calls fillbuf fatal ("P-081", new Object [] { Integer.toHexString (c) }); } first = start; last = first ; continue; } if (checkSurrogatePair (last)) last++; else { last--; // also terminate on surrogate pair oddities break; } continue; } fatal ("P-071", new Object [] { Integer.toHexString (c) }); } if (last == first) return sawContent; validator.text (); contentHandler.characters (buf, first, last - first); start = last; return true; } /** * CDATA -- character data, terminated by "]]>" and optionally * including unescaped markup delimiters (ampersand and left angle * bracket). This should otherwise be exactly like character data, * modulo differences in error report details. * * <P> The document handler's characters() or ignorableWhitespace() * methods are invoked on all the character data found * * @param contentHandler gets callbacks for character data * @param validator text() or ignorableWhitespace() methods are * called appropriately * @param ignorableWhitespace if true, whitespace characters will * be reported using contentHandler.ignorableWhitespace(); implicitly, * non-whitespace characters will cause validation errors * @param standaloneWhitespaceInvalid if true, ignorable whitespace * causes a validity error report as well as a callback */ public void unparsedContent ( ContentHandler contentHandler, ElementValidator validator, boolean ignorableWhitespace, String whitespaceInvalidMessage ) throws IOException, SAXException { // [18] CDSect ::= CDStart CData CDEnd // [19] CDStart ::= '<![CDATA[' // [20] CData ::= (Char* - (Char* ']]>' Char*)) // [21] CDEnd ::= ']]>' // Caller has already consumed the leading '<![CDATA[' so all that // remains to be parsed of [18] is "CData CDEnd" // only a literal ']]>' stops this ... int last; for (;;) { // until ']]>' seen boolean done = false; char c; // don't report ignorable whitespace as "text" for // validation purposes. boolean white = ignorableWhitespace; for (last = start; last < finish; last++) { c = buf [last]; // // Reject illegal characters. // if (!XmlChars.isChar (c)) { white = false; if (c >= 0xd800 && c <= 0xdfff) { if (checkSurrogatePair (last)) { last++; continue; } else { last--; break; } } fatal ("P-071", new Object [] { Integer.toHexString (buf [last]) }); } if (c == '\n') { if (!isInternal ()) lineNumber++; continue; } if (c == '\r') { // As above, we can't repeat CR/CRLF --> LF mapping if (isInternal ()) continue; if (white) { if (whitespaceInvalidMessage != null) errHandler.error (new SAXParseException ( Parser2.messages.getMessage (locale, whitespaceInvalidMessage), this)); contentHandler.ignorableWhitespace (buf, start, last - start); contentHandler.ignorableWhitespace (newline, 0, 1); } else { validator.text (); contentHandler.characters (buf, start, last - start); contentHandler.characters (newline, 0, 1); } lineNumber++; if (finish > (last + 1)) { if (buf [last + 1] == '\n') last++; } else { // CR at end of buffer// XXX case not yet handled ... as above } start = last + 1; continue; } if (c != ']') { if (c != ' ' && c != '\t') white = false; continue; } // assert(buf[last] == ']'); if ((last + 2) < finish) { if (buf [last + 1] == ']' && buf [last + 2] == '>') { done = true; break; } white = false; continue; } else { // "last" is at or one before end of buffered data. // Report what we have so far, not including "last", by // breaking and executing code below, outside inner // loop, then continuing on to find end of CDATA section. break; } } if (white) { if (whitespaceInvalidMessage != null) errHandler.error (new SAXParseException ( Parser2.messages.getMessage (locale, whitespaceInvalidMessage), this)); contentHandler.ignorableWhitespace (buf, start, last - start); } else { validator.text (); contentHandler.characters (buf, start, last - start); } if (done) { start = last + 3; break; } start = last; fillbuf(); if (isEOF ()) fatal ("P-073", null); } } // return false to backstep at end of buffer) private boolean checkSurrogatePair (int offset) throws SAXException { if ((offset + 1) >= finish) return false; char c1 = buf [offset++]; char c2 = buf [offset]; if ((c1 >= 0xd800 && c1 < 0xdc00) && (c2 >= 0xdc00 && c2 <= 0xdfff)) return true; fatal ("P-074", new Object [] { Integer.toHexString (c1 & 0x0ffff), Integer.toHexString (c2 & 0x0ffff) }); return false; } /** * whitespace in markup (flagged to app, discardable) * * <P> the document handler's ignorableWhitespace() method * is called on all the whitespace found */ public boolean ignorableWhitespace (ContentHandler handler) throws IOException, SAXException { char c; boolean isSpace = false; int first; // [3] S ::= #20 | #09 | #0D | #0A for (first = start;;) { if (finish <= start) { if (isSpace) handler.ignorableWhitespace (buf, first, start - first); fillbuf (); first = start; } if (finish <= start) return isSpace; c = buf [start++]; switch (c) { case '\n': if (!isInternal ()) lineNumber++;// XXX handles Macintosh line endings wrong // fallthrough case 0x09: case 0x20: isSpace = true; continue; case '\r': isSpace = true; if (!isInternal ()) lineNumber++; handler.ignorableWhitespace (buf, first, (start - 1) - first); handler.ignorableWhitespace (newline, 0, 1); if (start < finish && buf [start] == '\n') ++start; first = start; continue; default: ungetc (); if (isSpace) handler.ignorableWhitespace (buf, first, start - first); return isSpace; } } } /** * returns false iff 'next' string isn't as provided, * else skips that text and returns true * * <P> NOTE: two alternative string representations are * both passed in, since one is faster. */ public boolean peek (String next, char chars []) throws IOException, SAXException { int len; int i; if (chars != null) len = chars.length; else len = next.length (); // buffer should hold the whole thing ... give it a // chance for the end-of-buffer case and cope with EOF // by letting fillbuf compact and fill if (finish <= start || (finish - start) < len) fillbuf (); // can't peek past EOF if (finish <= start) return false; // compare the string; consume iff it matches if (chars != null) { for (i = 0; i < len && (start + i) < finish; i++) { if (buf [start + i] != chars [i]) return false; } } else { for (i = 0; i < len && (start + i) < finish; i++) { if (buf [start + i] != next.charAt (i)) return false; } } // if the first fillbuf didn't get enough data, give // fillbuf another chance to read if (i < len) { if (reader == null || isClosed) return false; // // This diagnostic "knows" that the only way big strings would // fail to be peeked is where it's a symbol ... e.g. for an // </EndTag> construct. That knowledge could also be applied // to get rid of the symbol length constraint, since having // the wrong symbol is a fatal error anyway ... // if (len > buf.length) fatal ("P-077", new Object [] { new Integer (buf.length) }); fillbuf (); return peek (next, chars); } start += len; return true; } /** * This method is used to disambiguate between XMLDecl, TextDecl, and * PI by doing a lookahead w/o consuming any characters. We look for * "<?xml" plus a whitespace character, but no more. For example, we * could have input documents with the PI "<?xml-stylesheet ... >". * * @return true iff next chars match either the prefix for XMLDecl or * TextDecl */ boolean isXmlDeclOrTextDeclPrefix() throws IOException, SAXException { // [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? // SDDecl? S? '>' // [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>' // [24] VersionInfo ::= S 'version' Eq \'|\" versionNum \'|\" String match = "<?xml"; int matchLen = match.length(); // Length of the entire prefix including whitespace int prefixLen = matchLen + 1; // buffer should hold the whole thing ... give it a // chance for the end-of-buffer case and cope with EOF // by letting fillbuf compact and fill if (finish <= start || (finish - start) < prefixLen) fillbuf (); // can't peek past EOF if (finish <= start) return false; // Compare the non-whitespace part of the prefix int i; for (i = 0; i < matchLen && (start + i) < finish; i++) { if (buf [start + i] != match.charAt (i)) return false; } // if the first fillbuf didn't get enough data, give // fillbuf another chance to read if (i < matchLen) { if (reader == null || isClosed) return false; fillbuf (); return isXmlDeclOrTextDeclPrefix(); } // assert(i == matchLen); // Match whitespace if (!XmlChars.isSpace(buf[i])) { return false; } return true; } // // Support for reporting the internal DTD subset, so <!DOCTYPE...> // declarations can be recreated. This is collected as a single // string; such subsets are normally small, and many applications // don't even care about this. // public void startRemembering () { if (startRemember != 0) throw new InternalError (); startRemember = start; } public String rememberText () { String retval; // If the internal subset crossed a buffer boundary, we // created a temporary buffer. if (rememberedText != null) { rememberedText.append (buf, startRemember, start - startRemember); retval = rememberedText.toString (); } else retval = new String (buf, startRemember, start - startRemember); startRemember = 0; rememberedText = null; return retval; } // LOCATOR METHODS private Locator getLocator () { InputEntity current = this; // don't report locations within internal entities! while (current != null && current.input == null) current = current.next; return current == null ? this : current; } /** Returns the public ID of this input source, if known */ public String getPublicId () { Locator where = getLocator (); if (where == this) return input.getPublicId (); return where.getPublicId (); } /** Returns the system ID of this input source, if known */ public String getSystemId () { Locator where = getLocator (); if (where == this) return input.getSystemId (); return where.getSystemId (); } /** Returns the current line number in this input source */ public int getLineNumber () { Locator where = getLocator (); if (where == this) return lineNumber; return where.getLineNumber (); } /** returns -1; maintaining column numbers hurts performance */ public int getColumnNumber () { return -1; // not maintained (speed) } // // n.b. for non-EOF end-of-buffer cases, reader should return // at least a handful of bytes so various lookaheads behave. // // two character pushback exists except at first; characters // represented by surrogate pairs can't be pushed back (they'd // only be in character data anyway). // // SAX exception thrown on char conversion problems; line number // will be low, as a rule. // private void fillbuf () throws IOException, SAXException { // don't touched fixed buffers, that'll usually // change entity values (and isn't needed anyway) // likewise, ignore closed streams if (reader == null || isClosed) return; // if remembering DTD text, copy! if (startRemember != 0) { if (rememberedText == null) rememberedText = new StringBuffer (buf.length); rememberedText.append (buf, startRemember, start - startRemember); } boolean extra = (finish > 0) && (start > 0); int len; if (extra) // extra pushback start--; len = finish - start; System.arraycopy (buf, start, buf, 0, len); start = 0; finish = len; try { len = buf.length - len; len = reader.read (buf, finish, len); } catch (UnsupportedEncodingException e) { fatal ("P-075", new Object [] { e.getMessage () }); } catch (CharConversionException e) { fatal ("P-076", new Object [] { e.getMessage () }); } if (len >= 0) finish += len; else close (); if (extra) // extra pushback start++; if (startRemember != 0) // assert extra == true startRemember = 1; } public void close () { try { if (reader != null && !isClosed) reader.close (); isClosed = true; } catch (IOException e) { /* NOTHING */ } } private void fatal (String messageId, Object params []) throws SAXException { SAXParseException x = new SAXParseException ( Parser2.messages.getMessage (locale, messageId, params), this); // not continuable ... e.g. WF errors close (); errHandler.fatalError (x); throw x; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?