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 + -
显示快捷键?